GT2/GT2-Android/node_modules/art/modes/canvas/surface.js

142 lines
3.7 KiB
JavaScript

var Class = require('../../core/class');
var Container = require('../../dom/container');
var Element = require('../../dom/native');
var fps = 1000 / 60, invalids = [], renderTimer, renderInvalids = function(){
clearTimeout(renderTimer);
renderTimer = null;
var canvases = invalids;
invalids = [];
for (var i = 0, l = canvases.length; i < l; i++){
var c = canvases[i];
c._valid = true;
c.render();
}
};
var resolution = typeof window !== 'undefined' && window.devicePixelRatio || 1;
var previousHit = null, previousHitSurface = null;
var CanvasSurface = Class(Element, Container, {
initialize: function(width, height, existingElement){
var element = this.element = existingElement || document.createElement('canvas');
var context = this.context = element.getContext('2d');
this._valid = true;
if (width != null && height != null) this.resize(width, height);
element.addEventListener('mousemove', this, false);
element.addEventListener('mouseout', this, false);
element.addEventListener('mouseover', this, false);
element.addEventListener('mouseup', this, false);
element.addEventListener('mousedown', this, false);
element.addEventListener('click', this, false);
},
handleEvent: function(event){
if (event.clientX == null) return;
var element = this.element,
rect = element.getBoundingClientRect(),
x = event.clientX - rect.left - element.clientLeft,
y = event.clientY - rect.top - element.clientTop,
hit = this.hitTest(x, y);
if (hit !== previousHit){
if (previousHit){
previousHit.dispatch({
type: 'mouseout',
target: previousHit,
relatedTarget: hit,
sourceEvent: event
});
}
if (hit){
hit.dispatch({
type: 'mouseover',
target: hit,
relatedTarget: previousHit,
sourceEvent: event
});
}
previousHit = hit;
previousHitSurface = this;
this.refreshCursor();
}
if (hit) hit.dispatch(event);
},
refreshCursor: function(){
if (previousHitSurface !== this) return;
var hit = previousHit, hitCursor = '', hitTooltip = '';
while (hit){
if (!hitCursor && hit._cursor){
hitCursor = hit._cursor;
if (hitTooltip) break;
}
if (!hitTooltip && hit._tooltip){
hitTooltip = hit._tooltip;
if (hitCursor) break;
}
hit = hit.parentNode;
}
// TODO: No way to set cursor/title on the surface
this.element.style.cursor = hitCursor;
this.element.title = hitTooltip;
},
resize: function(width, height){
var element = this.element;
element.setAttribute('width', width * resolution);
element.setAttribute('height', height * resolution);
element.style.width = width + 'px';
element.style.height = height + 'px';
this.width = width;
this.height = height;
return this;
},
invalidate: function(left, top, width, height){
if (this._valid){
this._valid = false;
invalids.push(this);
if (!renderTimer){
if (window.mozRequestAnimationFrame){
renderTimer = true;
window.mozRequestAnimationFrame(renderInvalids);
} else {
renderTimer = setTimeout(renderInvalids, fps);
}
}
}
return this;
},
hitTest: function(x, y){
if (x < 0 || y < 0 || x > this.width || y > this.height) return null;
var node = this.lastChild;
while (node){
var hit = node.hitTest(x, y);
if (hit) return hit;
node = node.previousSibling;
}
return null;
},
render: function(){
var node = this.firstChild, context = this.context;
context.setTransform(resolution, 0, 0, resolution, 0, 0);
context.clearRect(0, 0, this.width, this.height);
while (node){
node.renderTo(context, resolution, 0, 0, resolution, 0, 0);
node = node.nextSibling;
}
this.refreshCursor();
}
});
CanvasSurface.tagName = 'canvas';
module.exports = CanvasSurface;