From f0037ce9c6de16f584d239afb5446f921d7f49c9 Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Sat, 23 Mar 2013 23:50:51 -0700 Subject: [PATCH] cleaned up Stage.js --- src/Stage.js | 229 +++++++++++++++++++++++++++++---------------------- 1 file changed, 132 insertions(+), 97 deletions(-) diff --git a/src/Stage.js b/src/Stage.js index a5fcfbf8..c0759d13 100644 --- a/src/Stage.js +++ b/src/Stage.js @@ -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);