mirror of
https://github.com/konvajs/konva.git
synced 2025-09-18 18:27:58 +08:00
lots of refactoring, and code hardening. Also fixed bug in which dragend events were being fired before mouseup/touchend events
This commit is contained in:
@@ -206,10 +206,6 @@
|
||||
canvas = layer.getCanvas();
|
||||
}
|
||||
|
||||
if(layer && layer.getClearBeforeDraw()) {
|
||||
canvas.clear();
|
||||
}
|
||||
|
||||
if(this.isVisible()) {
|
||||
if (clip) {
|
||||
canvas._clip(this);
|
||||
@@ -229,20 +225,21 @@
|
||||
},
|
||||
drawHit: function() {
|
||||
var clip = !!this.getClipFunc() && this.nodeType !== 'Stage',
|
||||
dd = Kinetic.DD,
|
||||
hitCanvas;
|
||||
|
||||
if (clip) {
|
||||
hitCanvas = this.getLayer().hitCanvas;
|
||||
hitCanvas._clip(this);
|
||||
}
|
||||
if(this.isVisible() && this.isListening()) {
|
||||
if(this.shouldDrawHit()) {
|
||||
if (clip) {
|
||||
hitCanvas = this.getLayer().hitCanvas;
|
||||
hitCanvas._clip(this);
|
||||
}
|
||||
var children = this.children, len = children.length;
|
||||
for(var n = 0; n < len; n++) {
|
||||
children[n].drawHit();
|
||||
}
|
||||
}
|
||||
if (clip) {
|
||||
hitCanvas.getContext().restore();
|
||||
if (clip) {
|
||||
hitCanvas.getContext().restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,7 +1,7 @@
|
||||
(function() {
|
||||
Kinetic.DD = {
|
||||
anim: new Kinetic.Animation(),
|
||||
moving: false,
|
||||
started: false,
|
||||
offset: {
|
||||
x: 0,
|
||||
y: 0
|
||||
@@ -35,9 +35,6 @@
|
||||
|
||||
if(!dd.moving) {
|
||||
dd.moving = true;
|
||||
node.setListening(false);
|
||||
|
||||
// execute dragstart events if defined
|
||||
node._handleEvent('dragstart', evt);
|
||||
}
|
||||
|
||||
@@ -45,37 +42,53 @@
|
||||
node._handleEvent('dragmove', evt);
|
||||
}
|
||||
};
|
||||
Kinetic.DD._endDrag = function(evt) {
|
||||
var dd = Kinetic.DD, node = dd.node;
|
||||
Kinetic.DD._endDragBefore = function(evt) {
|
||||
var dd = Kinetic.DD,
|
||||
evt = evt || {},
|
||||
node = dd.node,
|
||||
nodeType, layer;
|
||||
|
||||
if(node) {
|
||||
var nodeType = node.nodeType, stage = node.getStage();
|
||||
node.setListening(true);
|
||||
if(nodeType === 'Stage') {
|
||||
node.draw();
|
||||
}
|
||||
// else if group, shape, or layer
|
||||
else {
|
||||
if((nodeType === 'Group' || nodeType === 'Shape') && node.getDragOnTop()) {
|
||||
node.getStage().dragLayer.remove();
|
||||
}
|
||||
nodeType = node.nodeType,
|
||||
layer = node.getLayer();
|
||||
|
||||
node.moveToTop();
|
||||
node.getLayer().draw();
|
||||
if((nodeType === 'Group' || nodeType === 'Shape') && node.getDragOnTop()) {
|
||||
node.getStage().dragLayer.remove();
|
||||
}
|
||||
|
||||
delete dd.node;
|
||||
dd.anim.stop();
|
||||
|
||||
// only fire dragend event if the drag and drop
|
||||
// operation actually started. This can be detected by
|
||||
// checking dd.moving
|
||||
// operation actually started.
|
||||
if(dd.moving) {
|
||||
dd.moving = false;
|
||||
node._handleEvent('dragend', evt);
|
||||
evt.dragEndNode = node;
|
||||
}
|
||||
|
||||
delete dd.node;
|
||||
|
||||
node.moveToTop();
|
||||
|
||||
if (layer) {
|
||||
layer.draw();
|
||||
}
|
||||
else {
|
||||
node.draw();
|
||||
}
|
||||
}
|
||||
};
|
||||
Kinetic.DD._endDragAfter = function(evt) {
|
||||
var evt = evt || {},
|
||||
dragEndNode = evt.dragEndNode;
|
||||
|
||||
if (evt && dragEndNode) {
|
||||
dragEndNode._handleEvent('dragend', evt);
|
||||
}
|
||||
};
|
||||
Kinetic.DD._endDrag = function() {
|
||||
this._endDragBefore();
|
||||
this._endDragAfter();
|
||||
};
|
||||
Kinetic.Node.prototype._startDrag = function(evt) {
|
||||
var dd = Kinetic.DD,
|
||||
that = this,
|
||||
@@ -99,22 +112,12 @@
|
||||
// Group or Shape node types
|
||||
else {
|
||||
if(this.getDragOnTop()) {
|
||||
|
||||
|
||||
// WARNING: it's important to delay the moveTo operation,
|
||||
// layer redraws, and anim.start() until after the method execution
|
||||
// has completed or else there will be a flicker on mobile devices
|
||||
// due to the time it takes to append the dd canvas to the DOM
|
||||
//setTimeout(function() {
|
||||
//if(dd.node) {
|
||||
// clear shape from layer canvas
|
||||
that.setVisible(false);
|
||||
layer.draw();
|
||||
that.setVisible(true);
|
||||
stage.add(stage.dragLayer);
|
||||
dd.anim.start();
|
||||
//}
|
||||
//}, 0);
|
||||
// clear shape from layer canvas
|
||||
that.setVisible(false);
|
||||
layer.draw();
|
||||
that.setVisible(true);
|
||||
stage.add(stage.dragLayer);
|
||||
dd.anim.start();
|
||||
}
|
||||
else {
|
||||
dd.anim.start();
|
||||
@@ -173,6 +176,7 @@
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Kinetic.Node.prototype._dragCleanup = function() {
|
||||
this.off('mousedown.kinetic');
|
||||
this.off('touchstart.kinetic');
|
||||
@@ -229,6 +233,10 @@
|
||||
// called before the stage mouseup event is triggered in order
|
||||
// to render the hit graph just in time to pick up the event
|
||||
var html = document.getElementsByTagName('html')[0];
|
||||
html.addEventListener('mouseup', Kinetic.DD._endDrag, true);
|
||||
html.addEventListener('touchend', Kinetic.DD._endDrag, true);
|
||||
html.addEventListener('mouseup', Kinetic.DD._endDragBefore, true);
|
||||
html.addEventListener('touchend', Kinetic.DD._endDragBefore, true);
|
||||
|
||||
html.addEventListener('mouseup', Kinetic.DD._endDragAfter, false);
|
||||
html.addEventListener('touchend', Kinetic.DD._endDragAfter, false);
|
||||
|
||||
})();
|
||||
|
32
src/Layer.js
32
src/Layer.js
@@ -46,30 +46,6 @@
|
||||
this.afterDrawFunc.call(this);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* draw children nodes on hit. this includes any groups
|
||||
* or shapes
|
||||
* @name drawHit
|
||||
* @methodOf Kinetic.Layer.prototype
|
||||
*/
|
||||
drawHit: function() {
|
||||
this.hitCanvas.clear();
|
||||
Kinetic.Container.prototype.drawHit.call(this);
|
||||
},
|
||||
/**
|
||||
* draw children nodes on scene. this includes any groups
|
||||
* or shapes
|
||||
* @name drawScene
|
||||
* @methodOf Kinetic.Layer.prototype
|
||||
* @param {Kinetic.Canvas} [canvas]
|
||||
*/
|
||||
drawScene: function(canvas) {
|
||||
canvas = canvas || this.getCanvas();
|
||||
if(this.getClearBeforeDraw()) {
|
||||
canvas.clear();
|
||||
}
|
||||
Kinetic.Container.prototype.drawScene.call(this, canvas);
|
||||
},
|
||||
toDataURL: function(config) {
|
||||
config = config || {};
|
||||
var mimeType = config.mimeType || null,
|
||||
@@ -117,6 +93,14 @@
|
||||
var stage = this.getStage();
|
||||
return (stage && stage._isTempDDLayerActive()) ? stage.dragLayer.canvas : this.canvas;
|
||||
},
|
||||
/**
|
||||
* get layer hit canvas
|
||||
* @name getHitCanvas
|
||||
* @methodOf Kinetic.Layer.prototype
|
||||
*/
|
||||
getHitCanvas: function() {
|
||||
return this.hitCanvas;
|
||||
},
|
||||
/**
|
||||
* get layer canvas context
|
||||
* @name getContext
|
||||
|
@@ -916,7 +916,7 @@
|
||||
}
|
||||
},
|
||||
/*
|
||||
* draw both scene and hit graphs.
|
||||
* draw both scene and hit graphs. If the node being drawn is the stage, all of the layers will be cleared and redra
|
||||
* @name draw
|
||||
* @methodOf Kinetic.Node.prototype
|
||||
* the scene renderer
|
||||
@@ -926,10 +926,15 @@
|
||||
|
||||
if(layer && layer.getClearBeforeDraw()) {
|
||||
layer.getCanvas().clear();
|
||||
layer.getHitCanvas().clear();
|
||||
}
|
||||
|
||||
this.drawScene();
|
||||
this.drawHit();
|
||||
},
|
||||
shouldDrawHit: function() {
|
||||
var dd = Kinetic.DD;
|
||||
return this.isVisible() && this.isListening() && (!dd || !dd.moving);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -188,7 +188,7 @@
|
||||
canvas = this.getLayer().hitCanvas,
|
||||
context = canvas.getContext();
|
||||
|
||||
if(drawFunc && this.isVisible() && this.isListening()) {
|
||||
if(drawFunc && this.shouldDrawHit()) {
|
||||
context.save();
|
||||
canvas._applyLineJoin(this);
|
||||
canvas._applyAncestorTransforms(this);
|
||||
|
20
src/Stage.js
20
src/Stage.js
@@ -51,6 +51,22 @@
|
||||
}
|
||||
this.setAttr('container', container);
|
||||
},
|
||||
draw: function() {
|
||||
// clear children layers
|
||||
var children = this.getChildren(),
|
||||
len = children.length,
|
||||
n, layer;
|
||||
|
||||
for(n = 0; n < len; n++) {
|
||||
layer = children[n];
|
||||
if (layer.getClearBeforeDraw()) {
|
||||
layer.getCanvas().clear();
|
||||
layer.getHitCanvas().clear();
|
||||
}
|
||||
}
|
||||
|
||||
Kinetic.Node.prototype.draw.call(this);
|
||||
},
|
||||
/**
|
||||
* draw layer scene graphs
|
||||
* @name draw
|
||||
@@ -396,7 +412,9 @@
|
||||
},
|
||||
_mouseup: function(evt) {
|
||||
this._setUserPosition(evt);
|
||||
var that = this, dd = Kinetic.DD, obj = this.getIntersection(this.getUserPosition());
|
||||
var that = this,
|
||||
dd = Kinetic.DD,
|
||||
obj = this.getIntersection(this.getUserPosition());
|
||||
|
||||
if(obj && obj.shape) {
|
||||
var shape = obj.shape;
|
||||
|
@@ -38,13 +38,13 @@ Test.Modules.DD = {
|
||||
clientX: 291,
|
||||
clientY: 112 + top
|
||||
});
|
||||
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 291,
|
||||
clientY: 112 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle});
|
||||
},
|
||||
'test dragstart, dragmove, dragend': function(containerId) {
|
||||
var stage = new Kinetic.Stage({
|
||||
@@ -89,16 +89,17 @@ Test.Modules.DD = {
|
||||
var dragEnd = false;
|
||||
var mouseup = false;
|
||||
var layerDragMove = false;
|
||||
var events = [];
|
||||
|
||||
circle.on('dragstart', function() {
|
||||
dragStart = true;
|
||||
});
|
||||
|
||||
/*
|
||||
|
||||
circle.on('dragmove', function() {
|
||||
dragMove = true;
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
layer.on('dragmove', function() {
|
||||
//console.log('move');
|
||||
@@ -106,13 +107,17 @@ Test.Modules.DD = {
|
||||
|
||||
circle.on('dragend', function() {
|
||||
dragEnd = true;
|
||||
// test set draggable false after drag end
|
||||
//this.setDraggable(false);
|
||||
console.log('dragend');
|
||||
events.push('dragend');
|
||||
});
|
||||
|
||||
|
||||
|
||||
circle.on('mouseup', function() {
|
||||
//console.log('mousup')
|
||||
console.log('mouseup');
|
||||
events.push('mouseup');
|
||||
});
|
||||
|
||||
warn(layer.toDataURL() === dataUrls['drag circle before'], 'start data url is incorrect');
|
||||
/*
|
||||
* simulate drag and drop
|
||||
@@ -136,23 +141,23 @@ Test.Modules.DD = {
|
||||
//test(dragMove, 'dragmove event was not triggered');
|
||||
test(!dragEnd, 'dragend event should not have been triggered');
|
||||
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 100,
|
||||
clientY: 98 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle});
|
||||
|
||||
test(dragStart, 'dragstart event was not triggered');
|
||||
//test(dragMove, 'dragmove event was not triggered');
|
||||
test(dragMove, 'dragmove event was not triggered');
|
||||
test(dragEnd, 'dragend event was not triggered');
|
||||
|
||||
test(events.toString() === 'mouseup,dragend', 'mouseup should occur before dragend');
|
||||
|
||||
warn(layer.toDataURL() === dataUrls['drag circle after'], 'end data url is incorrect');
|
||||
|
||||
console.log(layer);
|
||||
showHit(layer);
|
||||
|
||||
console.log(layer.eventListeners['dragmove']);
|
||||
},
|
||||
'cancel drag and drop by setting draggable to false': function(containerId) {
|
||||
var stage = new Kinetic.Stage({
|
||||
@@ -210,13 +215,12 @@ Test.Modules.DD = {
|
||||
clientY: 100 + top
|
||||
});
|
||||
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 100,
|
||||
clientY: 100 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle});
|
||||
|
||||
test(circle.getPosition().x === 380, 'circle x should be 380');
|
||||
test(circle.getPosition().y === 100, 'circle y should be 100');
|
||||
@@ -279,13 +283,12 @@ Test.Modules.DD = {
|
||||
clientY: 109 + top
|
||||
});
|
||||
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 210,
|
||||
clientY: 109 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle2});
|
||||
|
||||
//console.log(layer.toDataURL())
|
||||
warn(layer.toDataURL() === dataUrls['drag layer after'], 'end data url is incorrect');
|
||||
@@ -315,6 +318,7 @@ Test.Modules.EVENT = {
|
||||
var click = false
|
||||
|
||||
text.on('click', function() {
|
||||
console.log('text click');
|
||||
click = true;
|
||||
});
|
||||
|
||||
@@ -326,17 +330,18 @@ Test.Modules.EVENT = {
|
||||
showHit(layer);
|
||||
|
||||
stage._mousedown({
|
||||
clientX: 291,
|
||||
clientY: 112 + top
|
||||
clientX: 300,
|
||||
clientY: 120 + top
|
||||
});
|
||||
stage._mouseup({
|
||||
clientX: 291,
|
||||
clientY: 112 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 300,
|
||||
clientY: 120 + top
|
||||
});
|
||||
Kinetic.DD._endDragAfter({dragEndNode:text});
|
||||
|
||||
//TODO: can't get this to pass
|
||||
test(click, 'click event should have been fired when mousing down and then up on text');
|
||||
|
||||
},
|
||||
@@ -544,13 +549,12 @@ Test.Modules.EVENT = {
|
||||
test(!mouseout, '3) mouseout should be false');
|
||||
|
||||
// mouseup inside circle
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 290,
|
||||
clientY: 100 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle});
|
||||
|
||||
test(mouseover, '4) mouseover should be true');
|
||||
test(mousemove, '4) mousemove should be true');
|
||||
@@ -575,13 +579,12 @@ Test.Modules.EVENT = {
|
||||
test(!mouseout, '5) mouseout should be false');
|
||||
|
||||
// mouseup inside circle to trigger double click
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 290,
|
||||
clientY: 100 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle});
|
||||
|
||||
test(mouseover, '6) mouseover should be true');
|
||||
test(mousemove, '6) mousemove should be true');
|
||||
@@ -638,7 +641,7 @@ Test.Modules.EVENT = {
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
//Kinetic.DD._endDrag();
|
||||
|
||||
test(touchstart, '9) touchstart should be true');
|
||||
test(!touchmove, '9) touchmove should be false');
|
||||
@@ -669,7 +672,7 @@ Test.Modules.EVENT = {
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
//Kinetic.DD._endDrag();
|
||||
|
||||
test(touchstart, '11) touchstart should be true');
|
||||
test(!touchmove, '11) touchmove should be false');
|
||||
@@ -990,13 +993,12 @@ Test.Modules.EVENT = {
|
||||
clientX: 374,
|
||||
clientY: 114 + top
|
||||
});
|
||||
Kinetic.DD._endDragBefore();
|
||||
stage._mouseup({
|
||||
clientX: 374,
|
||||
clientY: 114 + top
|
||||
});
|
||||
// end drag is tied to document mouseup and touchend event
|
||||
// which can't be simulated. call _endDrag manually
|
||||
Kinetic.DD._endDrag();
|
||||
Kinetic.DD._endDragAfter({dragEndNode:circle});
|
||||
|
||||
test(e.toString() === 'circle,group1,group2,layer,stage', 'problem with event bubbling');
|
||||
}
|
||||
@@ -1051,24 +1053,27 @@ Test.Modules['HIT FUNCS'] = {
|
||||
clientY: 112 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 0, 'mouseovers should be 0');
|
||||
test(mouseouts === 0, 'mouseouts should be 0');
|
||||
test(mouseovers === 0, '1) mouseovers should be 0');
|
||||
test(mouseouts === 0, '1) mouseouts should be 0');
|
||||
|
||||
stage._mousemove({
|
||||
clientX: 286,
|
||||
clientY: 118 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 1, 'mouseovers should be 1');
|
||||
test(mouseouts === 0, 'mouseouts should be 0');
|
||||
test(mouseovers === 1, '2) mouseovers should be 1');
|
||||
test(mouseouts === 0, '2)mouseouts should be 0');
|
||||
|
||||
stage._mousemove({
|
||||
clientX: 113,
|
||||
clientY: 112 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 1, 'mouseovers should be 1');
|
||||
test(mouseouts === 1, 'mouseouts should be 1');
|
||||
test(mouseovers === 1, '3) mouseovers should be 1');
|
||||
test(mouseouts === 1, '3) mouseouts should be 1');
|
||||
|
||||
showHit(layer);
|
||||
|
||||
|
||||
// set drawBufferFunc with setter
|
||||
|
||||
@@ -1081,32 +1086,34 @@ Test.Modules['HIT FUNCS'] = {
|
||||
canvas.stroke(this);
|
||||
});
|
||||
|
||||
layer.getHitCanvas().clear();
|
||||
layer.drawHit();
|
||||
|
||||
|
||||
// move mouse far outside circle
|
||||
stage._mousemove({
|
||||
clientX: 113,
|
||||
clientY: 112 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 1, 'mouseovers should be 1');
|
||||
test(mouseouts === 1, 'mouseouts should be 1');
|
||||
test(mouseovers === 1, '4) mouseovers should be 1');
|
||||
test(mouseouts === 1, '4) mouseouts should be 1');
|
||||
|
||||
stage._mousemove({
|
||||
clientX: 286,
|
||||
clientY: 118 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 1, 'mouseovers should be 1');
|
||||
test(mouseouts === 1, 'mouseouts should be 1');
|
||||
test(mouseovers === 1, '5) mouseovers should be 1');
|
||||
test(mouseouts === 1, '5) mouseouts should be 1');
|
||||
|
||||
stage._mousemove({
|
||||
clientX: 321,
|
||||
clientY: 112 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 1, 'mouseovers should be 1');
|
||||
test(mouseouts === 1, 'mouseouts should be 1');
|
||||
test(mouseovers === 1, '6) mouseovers should be 1');
|
||||
test(mouseouts === 1, '6) mouseouts should be 1');
|
||||
|
||||
// move to center of circle
|
||||
stage._mousemove({
|
||||
@@ -1114,7 +1121,8 @@ Test.Modules['HIT FUNCS'] = {
|
||||
clientY: 112 + top
|
||||
});
|
||||
|
||||
test(mouseovers === 2, 'mouseovers should be 2');
|
||||
test(mouseouts === 1, 'mouseouts should be 1');
|
||||
test(mouseovers === 2, '7) mouseovers should be 2');
|
||||
test(mouseouts === 1, '7) mouseouts should be 1');
|
||||
|
||||
}
|
||||
};
|
||||
|
Reference in New Issue
Block a user