mirror of
https://github.com/konvajs/konva.git
synced 2025-05-05 22:24:34 +08:00
drag and drop operatons now dynamically generate a temporary top layer for high performance drag and drop. When completed, the top layer is removed. Also cleaned up a bit of drag and drop logic
This commit is contained in:
parent
36584a3ce2
commit
7ba40a6a68
@ -31,7 +31,6 @@
|
|||||||
this.frame.timeDiff = 0;
|
this.frame.timeDiff = 0;
|
||||||
this.frame.lastTime = new Date().getTime();
|
this.frame.lastTime = new Date().getTime();
|
||||||
Kinetic.Animation._addAnimation(this);
|
Kinetic.Animation._addAnimation(this);
|
||||||
Kinetic.Animation._handleAnimation();
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* stop animation
|
* stop animation
|
||||||
@ -59,6 +58,7 @@
|
|||||||
|
|
||||||
Kinetic.Animation._addAnimation = function(anim) {
|
Kinetic.Animation._addAnimation = function(anim) {
|
||||||
this.animations.push(anim);
|
this.animations.push(anim);
|
||||||
|
this._handleAnimation();
|
||||||
};
|
};
|
||||||
Kinetic.Animation._removeAnimation = function(anim) {
|
Kinetic.Animation._removeAnimation = function(anim) {
|
||||||
var id = anim.id;
|
var id = anim.id;
|
||||||
|
@ -150,8 +150,6 @@
|
|||||||
/**
|
/**
|
||||||
* apply shadow
|
* apply shadow
|
||||||
* @name applyShadow
|
* @name applyShadow
|
||||||
* @param {CanvasContext} context
|
|
||||||
* @param {Function} func draw function
|
|
||||||
* @methodOf Kinetic.Canvas.prototype
|
* @methodOf Kinetic.Canvas.prototype
|
||||||
* @param {Kinetic.Shape} shape
|
* @param {Kinetic.Shape} shape
|
||||||
* @param {Function} drawFunc
|
* @param {Function} drawFunc
|
||||||
@ -194,6 +192,13 @@
|
|||||||
pixelRatio = 1 / pixelRatio;
|
pixelRatio = 1 / pixelRatio;
|
||||||
this.getContext().scale(pixelRatio, pixelRatio);
|
this.getContext().scale(pixelRatio, pixelRatio);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
_applyAncestorTransforms: function(node) {
|
||||||
|
var context = this.context;
|
||||||
|
node.eachAncestorReverse(function(no) {
|
||||||
|
var t = no.getTransform(), m = t.getMatrix();
|
||||||
|
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,12 +5,74 @@
|
|||||||
offset: {
|
offset: {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
|
},
|
||||||
|
prevParent: null,
|
||||||
|
topLayer: null
|
||||||
|
};
|
||||||
|
Kinetic.Node.prototype._startDrag = function() {
|
||||||
|
var dd = Kinetic.DD;
|
||||||
|
var stage = this.getStage();
|
||||||
|
var pos = stage.getUserPosition();
|
||||||
|
|
||||||
|
if(pos) {
|
||||||
|
var m = this.getTransform().getTranslation(), ap = this.getAbsolutePosition(), nodeType = this.nodeType;
|
||||||
|
|
||||||
|
dd.node = this;
|
||||||
|
dd.offset.x = pos.x - ap.x;
|
||||||
|
dd.offset.y = pos.y - ap.y;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if dragging and dropping the stage,
|
||||||
|
* draw all of the layers
|
||||||
|
*/
|
||||||
|
if(nodeType === 'Stage') {
|
||||||
|
dd.anim.node = this;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* if node type is a group or shape, create a top layer,
|
||||||
|
* and move the node to the top layer
|
||||||
|
*/
|
||||||
|
if(nodeType === 'Group' || nodeType === 'Shape') {
|
||||||
|
var lastContainer = null;
|
||||||
|
dd.prevParent = this.getParent();
|
||||||
|
|
||||||
|
// re-construct node tree
|
||||||
|
this.eachAncestorReverse(function(node) {
|
||||||
|
if(node.nodeType === 'Layer') {
|
||||||
|
dd.topLayer = new Kinetic.Layer({
|
||||||
|
x: node.getX(),
|
||||||
|
y: node.getY(),
|
||||||
|
scale: node.getScale(),
|
||||||
|
rotation: node.getRotation()
|
||||||
|
});
|
||||||
|
lastContainer = dd.topLayer;
|
||||||
|
stage.add(dd.topLayer);
|
||||||
|
}
|
||||||
|
else if(node.nodeType === 'Group') {
|
||||||
|
var group = new Kinetic.Group({
|
||||||
|
x: node.getX(),
|
||||||
|
y: node.getY(),
|
||||||
|
scale: node.getScale(),
|
||||||
|
rotation: node.getRotation()
|
||||||
|
});
|
||||||
|
|
||||||
|
lastContainer.add(group);
|
||||||
|
lastContainer = group;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.moveTo(lastContainer);
|
||||||
|
dd.prevParent.getLayer().draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
dd.anim.node = this.getLayer();
|
||||||
|
}
|
||||||
|
dd.anim.start();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Kinetic.DD._drag = function(evt) {
|
||||||
Kinetic.DD._startDrag = function(evt) {
|
var dd = Kinetic.DD, node = dd.node;
|
||||||
var dd = Kinetic.DD;
|
|
||||||
var node = dd.node;
|
|
||||||
|
|
||||||
if(node) {
|
if(node) {
|
||||||
var pos = node.getStage().getUserPosition();
|
var pos = node.getStage().getUserPosition();
|
||||||
@ -40,14 +102,21 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
Kinetic.DD._endDrag = function(evt) {
|
Kinetic.DD._endDrag = function(evt) {
|
||||||
var dd = Kinetic.DD;
|
var dd = Kinetic.DD, node = dd.node;
|
||||||
var node = dd.node;
|
|
||||||
if(node) {
|
if(node) {
|
||||||
|
var nodeType = node.nodeType;
|
||||||
node.setListening(true);
|
node.setListening(true);
|
||||||
if(node.nodeType === 'Stage') {
|
if(nodeType === 'Stage') {
|
||||||
node.draw();
|
node.draw();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if(nodeType === 'Group' || nodeType === 'Shape') {
|
||||||
|
node.moveTo(dd.prevParent);
|
||||||
|
dd.topLayer.remove();
|
||||||
|
dd.prevParent = null;
|
||||||
|
dd.topLayer = null;
|
||||||
|
}
|
||||||
|
|
||||||
node.getLayer().draw();
|
node.getLayer().draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,37 +159,9 @@
|
|||||||
|
|
||||||
Kinetic.Node.prototype._listenDrag = function() {
|
Kinetic.Node.prototype._listenDrag = function() {
|
||||||
this._dragCleanup();
|
this._dragCleanup();
|
||||||
var that = this;
|
this.on('mousedown.kinetic touchstart.kinetic', this._startDrag);
|
||||||
this.on('mousedown.kinetic touchstart.kinetic', function(evt) {
|
|
||||||
that._initDrag();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
Kinetic.Node.prototype._initDrag = function() {
|
|
||||||
var dd = Kinetic.DD;
|
|
||||||
var stage = this.getStage();
|
|
||||||
var pos = stage.getUserPosition();
|
|
||||||
|
|
||||||
if(pos) {
|
|
||||||
var m = this.getTransform().getTranslation();
|
|
||||||
var am = this.getAbsoluteTransform().getTranslation();
|
|
||||||
var ap = this.getAbsolutePosition();
|
|
||||||
dd.node = this;
|
|
||||||
dd.offset.x = pos.x - ap.x;
|
|
||||||
dd.offset.y = pos.y - ap.y;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* if dragging and dropping the stage,
|
|
||||||
* draw all of the layers
|
|
||||||
*/
|
|
||||||
if(this.nodeType === 'Stage') {
|
|
||||||
dd.anim.node = this;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dd.anim.node = this.getLayer();
|
|
||||||
}
|
|
||||||
dd.anim.start();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Kinetic.Node.prototype._dragChange = function() {
|
Kinetic.Node.prototype._dragChange = function() {
|
||||||
if(this.attrs.draggable) {
|
if(this.attrs.draggable) {
|
||||||
this._listenDrag();
|
this._listenDrag();
|
||||||
@ -145,7 +186,6 @@
|
|||||||
this.off('mousedown.kinetic');
|
this.off('mousedown.kinetic');
|
||||||
this.off('touchstart.kinetic');
|
this.off('touchstart.kinetic');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get draggable. Alias of getDraggable()
|
* get draggable. Alias of getDraggable()
|
||||||
* @name isDraggable
|
* @name isDraggable
|
||||||
|
36
src/Node.js
36
src/Node.js
@ -436,6 +436,42 @@
|
|||||||
getRotationDeg: function() {
|
getRotationDeg: function() {
|
||||||
return Kinetic.Type._radToDeg(this.getRotation());
|
return Kinetic.Type._radToDeg(this.getRotation());
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* iterate through ancestors in reverse
|
||||||
|
* @name eachAncestorReverse
|
||||||
|
* @methodOf Kinetic.Node.prototype
|
||||||
|
* @param {Function} func function is passed two arguments, a node and
|
||||||
|
* the iterator integer
|
||||||
|
*/
|
||||||
|
eachAncestorReverse: function(func) {
|
||||||
|
var family = [], parent = this.getParent();
|
||||||
|
|
||||||
|
// build family by traversing ancestors
|
||||||
|
family.unshift(this);
|
||||||
|
while(parent) {
|
||||||
|
family.unshift(parent);
|
||||||
|
parent = parent.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
var len = family.length;
|
||||||
|
for(var n = 0; n < len; n++) {
|
||||||
|
func(family[n], n);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* iterate through ancestors
|
||||||
|
* @name eachAncestor
|
||||||
|
* @methodOf Kinetic.Node.prototype
|
||||||
|
* @param {Function} func function is passed two arguments, a node and
|
||||||
|
* the iterator integer
|
||||||
|
*/
|
||||||
|
eachAncestor: function(func) {
|
||||||
|
var family = [], parent = this.getParent(), n = 0;
|
||||||
|
while(parent) {
|
||||||
|
func(parent, n++);
|
||||||
|
parent = parent.parent;
|
||||||
|
}
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* set rotation in degrees
|
* set rotation in degrees
|
||||||
* @name setRotationDeg
|
* @name setRotationDeg
|
||||||
|
28
src/Shape.js
28
src/Shape.js
@ -205,23 +205,11 @@
|
|||||||
var attrs = this.attrs, drawFunc = attrs.drawFunc, canvas = canvas || this.getLayer().getCanvas(), context = canvas.getContext();
|
var attrs = this.attrs, drawFunc = attrs.drawFunc, canvas = canvas || this.getLayer().getCanvas(), context = canvas.getContext();
|
||||||
|
|
||||||
if(drawFunc && this.isVisible()) {
|
if(drawFunc && this.isVisible()) {
|
||||||
var stage = this.getStage(), family = [], parent = this.parent;
|
|
||||||
|
|
||||||
family.unshift(this);
|
|
||||||
while(parent) {
|
|
||||||
family.unshift(parent);
|
|
||||||
parent = parent.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.save();
|
context.save();
|
||||||
canvas._handlePixelRatio();
|
canvas._handlePixelRatio();
|
||||||
canvas._applyOpacity(this);
|
canvas._applyOpacity(this);
|
||||||
canvas._applyLineJoin(this);
|
canvas._applyLineJoin(this);
|
||||||
var len = family.length;
|
canvas._applyAncestorTransforms(this);
|
||||||
for(var n = 0; n < len; n++) {
|
|
||||||
var node = family[n], t = node.getTransform(), m = t.getMatrix();
|
|
||||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
drawFunc.call(this, canvas);
|
drawFunc.call(this, canvas);
|
||||||
context.restore();
|
context.restore();
|
||||||
@ -231,21 +219,9 @@
|
|||||||
var attrs = this.attrs, drawFunc = attrs.drawHitFunc || attrs.drawFunc, canvas = this.getLayer().hitCanvas, context = canvas.getContext();
|
var attrs = this.attrs, drawFunc = attrs.drawHitFunc || attrs.drawFunc, canvas = this.getLayer().hitCanvas, context = canvas.getContext();
|
||||||
|
|
||||||
if(drawFunc && this.isVisible() && this.isListening()) {
|
if(drawFunc && this.isVisible() && this.isListening()) {
|
||||||
var stage = this.getStage(), family = [], parent = this.parent;
|
|
||||||
|
|
||||||
family.unshift(this);
|
|
||||||
while(parent) {
|
|
||||||
family.unshift(parent);
|
|
||||||
parent = parent.parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
context.save();
|
context.save();
|
||||||
canvas._applyLineJoin(this);
|
canvas._applyLineJoin(this);
|
||||||
var len = family.length;
|
canvas._applyAncestorTransforms(this);
|
||||||
for(var n = 0; n < len; n++) {
|
|
||||||
var node = family[n], t = node.getTransform(), m = t.getMatrix();
|
|
||||||
context.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
|
||||||
}
|
|
||||||
|
|
||||||
drawFunc.call(this, canvas);
|
drawFunc.call(this, canvas);
|
||||||
context.restore();
|
context.restore();
|
||||||
|
18
src/Stage.js
18
src/Stage.js
@ -26,12 +26,9 @@
|
|||||||
this._id = Kinetic.Global.idCounter++;
|
this._id = Kinetic.Global.idCounter++;
|
||||||
this._buildDOM();
|
this._buildDOM();
|
||||||
this._bindContentEvents();
|
this._bindContentEvents();
|
||||||
|
Kinetic.Global.stages.push(this);
|
||||||
var go = Kinetic.Global;
|
|
||||||
go.stages.push(this);
|
|
||||||
this._addId(this);
|
this._addId(this);
|
||||||
this._addName(this);
|
this._addName(this);
|
||||||
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* set container dom element which contains the stage wrapper div element
|
* set container dom element which contains the stage wrapper div element
|
||||||
@ -333,11 +330,6 @@
|
|||||||
this.targetShape = null;
|
this.targetShape = null;
|
||||||
}
|
}
|
||||||
this.mousePos = undefined;
|
this.mousePos = undefined;
|
||||||
|
|
||||||
// end drag and drop
|
|
||||||
if(dd) {
|
|
||||||
dd._endDrag(evt);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_mousemove: function(evt) {
|
_mousemove: function(evt) {
|
||||||
this._setUserPosition(evt);
|
this._setUserPosition(evt);
|
||||||
@ -373,7 +365,7 @@
|
|||||||
|
|
||||||
// start drag and drop
|
// start drag and drop
|
||||||
if(dd) {
|
if(dd) {
|
||||||
dd._startDrag(evt);
|
dd._drag(evt);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_mousedown: function(evt) {
|
_mousedown: function(evt) {
|
||||||
@ -387,7 +379,7 @@
|
|||||||
|
|
||||||
//init stage drag and drop
|
//init stage drag and drop
|
||||||
if(Kinetic.DD && this.attrs.draggable) {
|
if(Kinetic.DD && this.attrs.draggable) {
|
||||||
this._initDrag();
|
this._startDrag();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_mouseup: function(evt) {
|
_mouseup: function(evt) {
|
||||||
@ -440,7 +432,7 @@
|
|||||||
* init stage drag and drop
|
* init stage drag and drop
|
||||||
*/
|
*/
|
||||||
if(Kinetic.DD && this.attrs.draggable) {
|
if(Kinetic.DD && this.attrs.draggable) {
|
||||||
this._initDrag();
|
this._startDrag();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_touchend: function(evt) {
|
_touchend: function(evt) {
|
||||||
@ -491,7 +483,7 @@
|
|||||||
|
|
||||||
// start drag and drop
|
// start drag and drop
|
||||||
if(dd) {
|
if(dd) {
|
||||||
dd._startDrag(evt);
|
dd._drag(evt);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
|
@ -177,7 +177,7 @@ Test.Modules.MANUAL = {
|
|||||||
anim.stop();
|
anim.stop();
|
||||||
}, 3000);
|
}, 3000);
|
||||||
},
|
},
|
||||||
'*ANIMATION - test multiple animations': function(containerId) {
|
'ANIMATION - test multiple animations': function(containerId) {
|
||||||
var stage = new Kinetic.Stage({
|
var stage = new Kinetic.Stage({
|
||||||
container: containerId,
|
container: containerId,
|
||||||
width: 578,
|
width: 578,
|
||||||
|
Loading…
Reference in New Issue
Block a user