cleaned up Stage.js

This commit is contained in:
Eric Rowell
2013-03-23 23:50:51 -07:00
parent 3a903d6c7c
commit f0037ce9c6

View File

@@ -1,7 +1,31 @@
(function() {
// CONSTANTS
var EVENTS = ['mousedown', 'mousemove', 'mouseup', 'mouseout', 'touchstart', 'touchmove', 'touchend'],
var STAGE = 'Stage',
STRING = 'string',
PX = 'px',
MOUSEOUT = 'mouseout',
MOUSELEAVE = 'mouseleave',
MOUSEOUT = 'mouseout',
MOUSEOVER = 'mouseover',
MOUSEENTER = 'mouseenter',
MOUSEMOVE = 'mousemove',
MOUSEDOWN = 'mousedown',
MOUSEUP = 'mouseup',
CLICK = 'click',
DBL_CLICK = 'dblclick',
TOUCHSTART = 'touchstart'
TOUCHEND = 'touchend'
TAP = 'tap',
DBL_TAP = 'dbltap',
TOUCHMOVE = 'touchmove',
DIV = 'div',
RELATIVE = 'relative',
INLINE_BLOCK = 'inline-block',
KINETICJS_CONTENT = 'kineticjs-content',
SPACE = ' ',
CONTAINER = 'container',
EVENTS = [MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEOUT, TOUCHSTART, TOUCHMOVE, TOUCHEND],
// cached variables
eventsLength = EVENTS.length;
@@ -20,12 +44,11 @@
Kinetic.Stage.prototype = {
_initStage: function(config) {
var dd = Kinetic.DD;
this.createAttrs();
// call super constructor
Kinetic.Container.call(this, config);
this._setStageDefaultProperties();
this.nodeType = STAGE;
this.dblClickWindow = 400;
this._id = Kinetic.Global.idCounter++;
this._buildDOM();
this._bindContentEvents();
@@ -38,14 +61,10 @@
* @param {DomElement} container can pass in a dom element or id string
*/
setContainer: function(container) {
/*
* if container is a string, assume it's an id for
* a DOM element
*/
if( typeof container === 'string') {
if( typeof container === STRING) {
container = document.getElementById(container);
}
this.setAttr('container', container);
this.setAttr(CONTAINER, container);
},
draw: function() {
// clear children layers
@@ -101,8 +120,11 @@
* @methodOf Kinetic.Stage.prototype
*/
clear: function() {
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layers = this.children,
len = length,
n;
for(n = 0; n < len; n++) {
layers[n].clear();
}
},
@@ -114,7 +136,7 @@
Kinetic.Node.prototype.remove.call(this);
if(content && Kinetic.Type._isInDocument(content)) {
this.attrs.container.removeChild(content);
this.getContainer().removeChild(content);
}
},
/**
@@ -170,8 +192,8 @@
* is very high quality
*/
toDataURL: function(config) {
config = config || {};
var mimeType = config.mimeType || null,
var config = config || {},
mimeType = config.mimeType || null,
quality = config.quality || null,
x = config.x || 0,
y = config.y || 0,
@@ -187,9 +209,10 @@
}
function drawLayer(n) {
var layer = layers[n];
var layerUrl = layer.toDataURL();
var imageObj = new Image();
var layer = layers[n],
layerUrl = layer.toDataURL(),
imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
@@ -237,20 +260,22 @@
* @param {Object} pos point object
*/
getIntersection: function(pos) {
var shape;
var layers = this.getChildren();
var layers = this.getChildren(),
len = layers.length,
end = len - 1,
n, layer, p, colorKey, shape;
/*
* traverse through layers from top to bottom and look
* for hit detection
*/
for(var n = layers.length - 1; n >= 0; n--) {
var layer = layers[n];
for(n = end; n >= 0; n--) {
layer = layers[n];
if(layer.isVisible() && layer.isListening()) {
var p = layer.hitCanvas.context.getImageData(Math.round(pos.x), Math.round(pos.y), 1, 1).data;
p = layer.hitCanvas.context.getImageData(Math.round(pos.x), Math.round(pos.y), 1, 1).data;
// this indicates that a hit pixel may have been found
if(p[3] === 255) {
var colorKey = Kinetic.Type._rgbToHex(p[0], p[1], p[2]);
colorKey = Kinetic.Type._rgbToHex(p[0], p[1], p[2]);
shape = Kinetic.Global.shapes[colorKey];
return {
shape: shape,
@@ -270,19 +295,22 @@
},
_resizeDOM: function() {
if(this.content) {
var width = this.attrs.width;
var height = this.attrs.height;
var width = this.getWidth(),
height = this.getHeight(),
layers = this.getChildren(),
len = layers.length,
n;
// set content dimensions
this.content.style.width = width + 'px';
this.content.style.height = height + 'px';
this.content.style.width = width + PX;
this.content.style.height = height + PX;
this.bufferCanvas.setSize(width, height, 1);
this.hitCanvas.setSize(width, height);
// set pointer defined layer dimensions
var layers = this.children;
for(var n = 0; n < layers.length; n++) {
var layer = layers[n];
for(n = 0; n < len; n++) {
layer = layers[n];
layer.getCanvas().setSize(width, height);
layer.hitCanvas.setSize(width, height);
layer.draw();
@@ -326,7 +354,7 @@
var that = this,
n, pubEvent, f;
for (var n = 0; n < eventsLength; n++) {
for (n = 0; n < eventsLength; n++) {
pubEvent = EVENTS[n];
f = that['_' + pubEvent];
that.content.addEventListener(pubEvent, f.bind(that), false);
@@ -334,12 +362,12 @@
},
_mouseout: function(evt) {
this._setPointerPosition(evt);
var go = Kinetic.Global;
// if there's a current target shape, run mouseout handlers
var targetShape = this.targetShape;
var go = Kinetic.Global,
targetShape = this.targetShape;
if(targetShape && !go.isDragging()) {
targetShape._handleEvent('mouseout', evt);
targetShape._handleEvent('mouseleave', evt);
targetShape._handleEvent(MOUSEOUT, evt);
targetShape._handleEvent(MOUSELEAVE, evt);
this.targetShape = null;
}
this.mousePos = undefined;
@@ -348,22 +376,23 @@
this._setPointerPosition(evt);
var go = Kinetic.Global,
dd = Kinetic.DD,
obj = this.getIntersection(this.getPointerPosition());
obj = this.getIntersection(this.getPointerPosition()),
shape;
if(obj) {
var shape = obj.shape;
shape = obj.shape;
if(shape) {
if(!go.isDragging() && obj.pixel[3] === 255 && (!this.targetShape || this.targetShape._id !== shape._id)) {
if(this.targetShape) {
this.targetShape._handleEvent('mouseout', evt, shape);
this.targetShape._handleEvent('mouseleave', evt, shape);
this.targetShape._handleEvent(MOUSEOUT, evt, shape);
this.targetShape._handleEvent(MOUSELEAVE, evt, shape);
}
shape._handleEvent('mouseover', evt, this.targetShape);
shape._handleEvent('mouseenter', evt, this.targetShape);
shape._handleEvent(MOUSEOVER, evt, this.targetShape);
shape._handleEvent(MOUSEENTER, evt, this.targetShape);
this.targetShape = shape;
}
else {
shape._handleEvent('mousemove', evt);
shape._handleEvent(MOUSEMOVE, evt);
}
}
}
@@ -372,8 +401,8 @@
* to run mouseout from previous target shape
*/
else if(this.targetShape && !go.isDragging()) {
this.targetShape._handleEvent('mouseout', evt);
this.targetShape._handleEvent('mouseleave', evt);
this.targetShape._handleEvent(MOUSEOUT, evt);
this.targetShape._handleEvent(MOUSELEAVE, evt);
this.targetShape = null;
}
@@ -383,18 +412,20 @@
}
},
_mousedown: function(evt) {
var obj, dd = Kinetic.DD;
this._setPointerPosition(evt);
obj = this.getIntersection(this.getPointerPosition());
var dd = Kinetic.DD,
obj = this.getIntersection(this.getPointerPosition()),
shape;
if(obj && obj.shape) {
var shape = obj.shape;
shape = obj.shape;
this.clickStart = true;
this.clickStartShape = shape;
shape._handleEvent('mousedown', evt);
shape._handleEvent(MOUSEDOWN, evt);
}
//init stage drag and drop
if(dd && this.attrs.draggable && !dd.node) {
if(dd && this.isDraggable() && !dd.node) {
this._startDrag(evt);
}
},
@@ -402,11 +433,12 @@
this._setPointerPosition(evt);
var that = this,
go = Kinetic.Global,
obj = this.getIntersection(this.getPointerPosition());
obj = this.getIntersection(this.getPointerPosition()),
shape;
if(obj && obj.shape) {
var shape = obj.shape;
shape._handleEvent('mouseup', evt);
shape = obj.shape;
shape._handleEvent(MOUSEUP, evt);
// detect if click or double click occurred
if(this.clickStart) {
@@ -415,10 +447,10 @@
* the correct shape, don't fire click or dbl click event
*/
if(!go.isDragging() && shape._id === this.clickStartShape._id) {
shape._handleEvent('click', evt);
shape._handleEvent(CLICK, evt);
if(this.inDoubleClickWindow) {
shape._handleEvent('dblclick', evt);
shape._handleEvent(DBL_CLICK, evt);
}
this.inDoubleClickWindow = true;
setTimeout(function() {
@@ -430,18 +462,20 @@
this.clickStart = false;
},
_touchstart: function(evt) {
this._setPointerPosition(evt);
var dd = Kinetic.DD,
go = Kinetic.Global,
obj;
obj = this.getIntersection(this.getPointerPosition()),
shape;
this._setPointerPosition(evt);
evt.preventDefault();
obj = this.getIntersection(this.getPointerPosition());
if(obj && obj.shape) {
var shape = obj.shape;
shape = obj.shape;
this.tapStart = true;
shape._handleEvent('touchstart', evt);
this.tapStartShape = shape;
shape._handleEvent(TOUCHSTART, evt);
}
// init stage drag and drop
@@ -451,11 +485,14 @@
},
_touchend: function(evt) {
this._setPointerPosition(evt);
var that = this, dd = Kinetic.DD, obj = this.getIntersection(this.getPointerPosition());
var that = this,
go = Kinetic.Global,
obj = this.getIntersection(this.getPointerPosition()),
shape;
if(obj && obj.shape) {
var shape = obj.shape;
shape._handleEvent('touchend', evt);
shape = obj.shape;
shape._handleEvent(TOUCHEND, evt);
// detect if tap or double tap occurred
if(this.tapStart) {
@@ -463,11 +500,11 @@
* if dragging and dropping, don't fire tap or dbltap
* event
*/
if(!dd || !dd.isDragging || !dd.node) {
shape._handleEvent('tap', evt);
if(!go.isDragging() && shape._id === this.tapStartShape._id) {
shape._handleEvent(TAP, evt);
if(this.inDoubleClickWindow) {
shape._handleEvent('dbltap', evt);
shape._handleEvent(DBL_TAP, evt);
}
this.inDoubleClickWindow = true;
setTimeout(function() {
@@ -481,12 +518,15 @@
},
_touchmove: function(evt) {
this._setPointerPosition(evt);
var dd = Kinetic.DD;
var dd = Kinetic.DD,
obj = this.getIntersection(this.getPointerPosition()),
shape;
evt.preventDefault();
var obj = this.getIntersection(this.getPointerPosition());
if(obj && obj.shape) {
var shape = obj.shape;
shape._handleEvent('touchmove', evt);
shape = obj.shape;
shape._handleEvent(TOUCHMOVE, evt);
}
// start drag and drop
@@ -499,8 +539,9 @@
* @param {Event} evt
*/
_setMousePosition: function(evt) {
var mouseX = evt.clientX - this._getContentPosition().left;
var mouseY = evt.clientY - this._getContentPosition().top;
var mouseX = evt.clientX - this._getContentPosition().left,
mouseY = evt.clientY - this._getContentPosition().top;
this.mousePos = {
x: mouseX,
y: mouseY
@@ -511,12 +552,15 @@
* @param {Event} evt
*/
_setTouchPosition: function(evt) {
var touch, touchX, touchY;
if(evt.touches !== undefined && evt.touches.length === 1) {
// one finger
var touch = evt.touches[0];
// Get the information for finger #1
var touchX = touch.clientX - this._getContentPosition().left;
var touchY = touch.clientY - this._getContentPosition().top;
touch = evt.touches[0];
// get the information for finger #1
touchX = touch.clientX - this._getContentPosition().left;
touchY = touch.clientY - this._getContentPosition().top;
this.touchPos = {
x: touchX,
@@ -539,10 +583,10 @@
*/
_buildDOM: function() {
// content
this.content = document.createElement('div');
this.content.style.position = 'relative';
this.content.style.display = 'inline-block';
this.content.className = 'kineticjs-content';
this.content = document.createElement(DIV);
this.content.style.position = RELATIVE;
this.content.style.display = INLINE_BLOCK;
this.content.className = KINETICJS_CONTENT;
this.attrs.container.appendChild(this.content);
this.bufferCanvas = new Kinetic.SceneCanvas();
@@ -556,23 +600,14 @@
* @param {function} handler
*/
_onContent: function(typesStr, handler) {
var types = typesStr.split(' ');
for(var n = 0; n < types.length; n++) {
var baseEvent = types[n];
var types = typesStr.split(SPACE),
len = types.length,
n, baseEvent;
for(n = 0; n < len; n++) {
baseEvent = types[n];
this.content.addEventListener(baseEvent, handler, false);
}
},
/**
* set defaults
*/
_setStageDefaultProperties: function() {
this.nodeType = 'Stage';
this.dblClickWindow = 400;
this.targetShape = null;
this.mousePos = undefined;
this.clickStart = false;
this.touchPos = undefined;
this.tapStart = false;
}
};
Kinetic.Global.extend(Kinetic.Stage, Kinetic.Container);