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:
Eric Rowell 2012-12-30 23:14:23 -08:00
parent 36584a3ce2
commit 7ba40a6a68
7 changed files with 130 additions and 81 deletions

View File

@ -31,7 +31,6 @@
this.frame.timeDiff = 0;
this.frame.lastTime = new Date().getTime();
Kinetic.Animation._addAnimation(this);
Kinetic.Animation._handleAnimation();
},
/**
* stop animation
@ -59,6 +58,7 @@
Kinetic.Animation._addAnimation = function(anim) {
this.animations.push(anim);
this._handleAnimation();
};
Kinetic.Animation._removeAnimation = function(anim) {
var id = anim.id;

View File

@ -150,8 +150,6 @@
/**
* apply shadow
* @name applyShadow
* @param {CanvasContext} context
* @param {Function} func draw function
* @methodOf Kinetic.Canvas.prototype
* @param {Kinetic.Shape} shape
* @param {Function} drawFunc
@ -194,6 +192,13 @@
pixelRatio = 1 / 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]);
});
}
};

View File

@ -5,12 +5,74 @@
offset: {
x: 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._startDrag = function(evt) {
var dd = Kinetic.DD;
var node = dd.node;
Kinetic.DD._drag = function(evt) {
var dd = Kinetic.DD, node = dd.node;
if(node) {
var pos = node.getStage().getUserPosition();
@ -40,14 +102,21 @@
}
};
Kinetic.DD._endDrag = function(evt) {
var dd = Kinetic.DD;
var node = dd.node;
var dd = Kinetic.DD, node = dd.node;
if(node) {
var nodeType = node.nodeType;
node.setListening(true);
if(node.nodeType === 'Stage') {
if(nodeType === 'Stage') {
node.draw();
}
else {
if(nodeType === 'Group' || nodeType === 'Shape') {
node.moveTo(dd.prevParent);
dd.topLayer.remove();
dd.prevParent = null;
dd.topLayer = null;
}
node.getLayer().draw();
}
@ -90,37 +159,9 @@
Kinetic.Node.prototype._listenDrag = function() {
this._dragCleanup();
var that = this;
this.on('mousedown.kinetic touchstart.kinetic', function(evt) {
that._initDrag();
});
this.on('mousedown.kinetic touchstart.kinetic', this._startDrag);
};
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() {
if(this.attrs.draggable) {
this._listenDrag();
@ -145,7 +186,6 @@
this.off('mousedown.kinetic');
this.off('touchstart.kinetic');
};
/**
* get draggable. Alias of getDraggable()
* @name isDraggable

View File

@ -436,6 +436,42 @@
getRotationDeg: function() {
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
* @name setRotationDeg
@ -761,7 +797,7 @@
context = canvas.getContext();
context.save();
canvas._counterPixelRatio();
if(x || y) {
context.translate(-1 * x, -1 * y);
}

View File

@ -205,23 +205,11 @@
var attrs = this.attrs, drawFunc = attrs.drawFunc, canvas = canvas || this.getLayer().getCanvas(), context = canvas.getContext();
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();
canvas._handlePixelRatio();
canvas._applyOpacity(this);
canvas._applyLineJoin(this);
var len = family.length;
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]);
}
canvas._applyAncestorTransforms(this);
drawFunc.call(this, canvas);
context.restore();
@ -231,21 +219,9 @@
var attrs = this.attrs, drawFunc = attrs.drawHitFunc || attrs.drawFunc, canvas = this.getLayer().hitCanvas, context = canvas.getContext();
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();
canvas._applyLineJoin(this);
var len = family.length;
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]);
}
canvas._applyAncestorTransforms(this);
drawFunc.call(this, canvas);
context.restore();

View File

@ -26,12 +26,9 @@
this._id = Kinetic.Global.idCounter++;
this._buildDOM();
this._bindContentEvents();
var go = Kinetic.Global;
go.stages.push(this);
Kinetic.Global.stages.push(this);
this._addId(this);
this._addName(this);
},
/**
* set container dom element which contains the stage wrapper div element
@ -333,11 +330,6 @@
this.targetShape = null;
}
this.mousePos = undefined;
// end drag and drop
if(dd) {
dd._endDrag(evt);
}
},
_mousemove: function(evt) {
this._setUserPosition(evt);
@ -373,7 +365,7 @@
// start drag and drop
if(dd) {
dd._startDrag(evt);
dd._drag(evt);
}
},
_mousedown: function(evt) {
@ -387,7 +379,7 @@
//init stage drag and drop
if(Kinetic.DD && this.attrs.draggable) {
this._initDrag();
this._startDrag();
}
},
_mouseup: function(evt) {
@ -440,7 +432,7 @@
* init stage drag and drop
*/
if(Kinetic.DD && this.attrs.draggable) {
this._initDrag();
this._startDrag();
}
},
_touchend: function(evt) {
@ -491,7 +483,7 @@
// start drag and drop
if(dd) {
dd._startDrag(evt);
dd._drag(evt);
}
},
/**

View File

@ -177,7 +177,7 @@ Test.Modules.MANUAL = {
anim.stop();
}, 3000);
},
'*ANIMATION - test multiple animations': function(containerId) {
'ANIMATION - test multiple animations': function(containerId) {
var stage = new Kinetic.Stage({
container: containerId,
width: 578,