From 8fcd882ba5d2da288c846d9a76911729e7d56728 Mon Sep 17 00:00:00 2001 From: Eric Rowell Date: Wed, 26 Feb 2014 08:46:26 -0800 Subject: [PATCH] added throttling to mousemove and touchmove. Added logic to prevent Android from detecting both touch and mouse events --- src/Stage.js | 176 ++++++++++++++++++---------------- test/unit/DragAndDrop-test.js | 47 ++++----- 2 files changed, 118 insertions(+), 105 deletions(-) diff --git a/src/Stage.js b/src/Stage.js index 87db0145..e0f8d302 100644 --- a/src/Stage.js +++ b/src/Stage.js @@ -344,58 +344,64 @@ } }, _mouseover: function(evt) { - this._fire(CONTENT_MOUSEOVER, evt); + if (!Kinetic.UA.mobile) { + this._fire(CONTENT_MOUSEOVER, evt); + } }, _mouseout: function(evt) { - this._setPointerPosition(evt); - var targetShape = this.targetShape; + if (!Kinetic.UA.mobile) { + this._setPointerPosition(evt); + var targetShape = this.targetShape; - if(targetShape && !Kinetic.isDragging()) { - targetShape._fireAndBubble(MOUSEOUT, evt); - targetShape._fireAndBubble(MOUSELEAVE, evt); - this.targetShape = null; + if(targetShape && !Kinetic.isDragging()) { + targetShape._fireAndBubble(MOUSEOUT, evt); + targetShape._fireAndBubble(MOUSELEAVE, evt); + this.targetShape = null; + } + this.pointerPos = undefined; + + this._fire(CONTENT_MOUSEOUT, evt); } - this.pointerPos = undefined; - - this._fire(CONTENT_MOUSEOUT, evt); }, - _mousemove: function(evt) { - this._setPointerPosition(evt); - var dd = Kinetic.DD, - shape = this.getIntersection(this.getPointerPosition()); + _mousemove: Kinetic.Util._throttle(function(evt) { + if (!Kinetic.UA.mobile) { + this._setPointerPosition(evt); + var dd = Kinetic.DD, + shape = this.getIntersection(this.getPointerPosition()); - if(shape && shape.isListening()) { - if(!Kinetic.isDragging() && (!this.targetShape || this.targetShape._id !== shape._id)) { - if(this.targetShape) { - this.targetShape._fireAndBubble(MOUSEOUT, evt, shape); - this.targetShape._fireAndBubble(MOUSELEAVE, evt, shape); + if(shape && shape.isListening()) { + if(!Kinetic.isDragging() && (!this.targetShape || this.targetShape._id !== shape._id)) { + if(this.targetShape) { + this.targetShape._fireAndBubble(MOUSEOUT, evt, shape); + this.targetShape._fireAndBubble(MOUSELEAVE, evt, shape); + } + shape._fireAndBubble(MOUSEOVER, evt, this.targetShape); + shape._fireAndBubble(MOUSEENTER, evt, this.targetShape); + this.targetShape = shape; + } + else { + shape._fireAndBubble(MOUSEMOVE, evt); } - shape._fireAndBubble(MOUSEOVER, evt, this.targetShape); - shape._fireAndBubble(MOUSEENTER, evt, this.targetShape); - this.targetShape = shape; } + /* + * if no shape was detected, clear target shape and try + * to run mouseout from previous target shape + */ else { - shape._fireAndBubble(MOUSEMOVE, evt); + if(this.targetShape && !Kinetic.isDragging()) { + this.targetShape._fireAndBubble(MOUSEOUT, evt); + this.targetShape._fireAndBubble(MOUSELEAVE, evt); + this.targetShape = null; + } + } - } - /* - * if no shape was detected, clear target shape and try - * to run mouseout from previous target shape - */ - else { - if(this.targetShape && !Kinetic.isDragging()) { - this.targetShape._fireAndBubble(MOUSEOUT, evt); - this.targetShape._fireAndBubble(MOUSELEAVE, evt); - this.targetShape = null; - } - } + // content event + this._fire(CONTENT_MOUSEMOVE, evt); - // content event - this._fire(CONTENT_MOUSEMOVE, evt); - - if(dd) { - dd._drag(evt); + if(dd) { + dd._drag(evt); + } } // always call preventDefault for desktop events because some browsers @@ -403,21 +409,23 @@ if (evt.preventDefault) { evt.preventDefault(); } - }, + }, 17), _mousedown: function(evt) { - this._setPointerPosition(evt); - var shape = this.getIntersection(this.getPointerPosition()); + if (!Kinetic.UA.mobile) { + this._setPointerPosition(evt); + var shape = this.getIntersection(this.getPointerPosition()); - Kinetic.listenClickTap = true; + Kinetic.listenClickTap = true; - if (shape && shape.isListening()) { - this.clickStartShape = shape; - shape._fireAndBubble(MOUSEDOWN, evt); + if (shape && shape.isListening()) { + this.clickStartShape = shape; + shape._fireAndBubble(MOUSEDOWN, evt); + } + + // content event + this._fire(CONTENT_MOUSEDOWN, evt); } - // content event - this._fire(CONTENT_MOUSEDOWN, evt); - // always call preventDefault for desktop events because some browsers // try to drag and drop the canvas element if (evt.preventDefault) { @@ -425,46 +433,48 @@ } }, _mouseup: function(evt) { - this._setPointerPosition(evt); - var that = this, - shape = this.getIntersection(this.getPointerPosition()), - clickStartShape = this.clickStartShape, - fireDblClick = false; + if (!Kinetic.UA.mobile) { + this._setPointerPosition(evt); + var that = this, + shape = this.getIntersection(this.getPointerPosition()), + clickStartShape = this.clickStartShape, + fireDblClick = false; - if(Kinetic.inDblClickWindow) { - fireDblClick = true; - Kinetic.inDblClickWindow = false; - } - else { - Kinetic.inDblClickWindow = true; - } + if(Kinetic.inDblClickWindow) { + fireDblClick = true; + Kinetic.inDblClickWindow = false; + } + else { + Kinetic.inDblClickWindow = true; + } - setTimeout(function() { - Kinetic.inDblClickWindow = false; - }, Kinetic.dblClickWindow); + setTimeout(function() { + Kinetic.inDblClickWindow = false; + }, Kinetic.dblClickWindow); - if (shape && shape.isListening()) { - shape._fireAndBubble(MOUSEUP, evt); + if (shape && shape.isListening()) { + shape._fireAndBubble(MOUSEUP, evt); - // detect if click or double click occurred - if(Kinetic.listenClickTap && clickStartShape && clickStartShape._id === shape._id) { - shape._fireAndBubble(CLICK, evt); + // detect if click or double click occurred + if(Kinetic.listenClickTap && clickStartShape && clickStartShape._id === shape._id) { + shape._fireAndBubble(CLICK, evt); - if(fireDblClick) { - shape._fireAndBubble(DBL_CLICK, evt); + if(fireDblClick) { + shape._fireAndBubble(DBL_CLICK, evt); + } } } - } - // content events - this._fire(CONTENT_MOUSEUP, evt); - if (Kinetic.listenClickTap) { - this._fire(CONTENT_CLICK, evt); - if(fireDblClick) { - this._fire(CONTENT_DBL_CLICK, evt); + // content events + this._fire(CONTENT_MOUSEUP, evt); + if (Kinetic.listenClickTap) { + this._fire(CONTENT_CLICK, evt); + if(fireDblClick) { + this._fire(CONTENT_DBL_CLICK, evt); + } } - } - Kinetic.listenClickTap = false; + Kinetic.listenClickTap = false; + } // always call preventDefault for desktop events because some browsers // try to drag and drop the canvas element @@ -534,7 +544,7 @@ Kinetic.listenClickTap = false; }, - _touchmove: function(evt) { + _touchmove: Kinetic.Util._throttle(function(evt) { this._setPointerPosition(evt); var dd = Kinetic.DD, shape = this.getIntersection(this.getPointerPosition()); @@ -553,7 +563,7 @@ if(dd) { dd._drag(evt); } - }, + }, 17), _setPointerPosition: function(evt) { var evt = evt ? evt : window.event, contentPosition = this._getContentPosition(), diff --git a/test/unit/DragAndDrop-test.js b/test/unit/DragAndDrop-test.js index e671e909..b80ce661 100644 --- a/test/unit/DragAndDrop-test.js +++ b/test/unit/DragAndDrop-test.js @@ -1,40 +1,43 @@ suite('DragAndDrop', function() { // ====================================================== - test('test drag and drop properties and methods', function() { - var stage = addStage(); - var layer = new Kinetic.Layer(); - var circle = new Kinetic.Circle({ - x: stage.getWidth() / 2, - y: stage.getHeight() / 2, - radius: 70, - fill: 'green', - stroke: 'black', - strokeWidth: 4, - name: 'myCircle' - }); + test('test drag and drop properties and methods', function(done) { + var stage = addStage(); + var layer = new Kinetic.Layer(); + var circle = new Kinetic.Circle({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + radius: 70, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + name: 'myCircle' + }); stage.add(layer); layer.add(circle); setTimeout(function() { - layer.draw(); - // test defaults - //assert.equal(circle.draggable(), false); + layer.draw(); - //change properties - circle.setDraggable(true); + // test defaults + assert.equal(circle.draggable(), false); + + //change properties + circle.setDraggable(true); - //circle.on('click', function(){}); + //circle.on('click', function(){}); - layer.draw(); + layer.draw(); - showHit(layer); + showHit(layer); - // test new properties - //assert.equal(circle.getDraggable(), true); + // test new properties + assert.equal(circle.getDraggable(), true); + + done(); }, 50); });