konva/src/DragAndDrop.js

280 lines
7.5 KiB
JavaScript
Raw Normal View History

(function() {
Kinetic.DD = {
// properties
anim: new Kinetic.Animation(),
isDragging: false,
offset: {
x: 0,
y: 0
},
node: null,
2013-12-19 22:47:06 +08:00
distance: 1,
// methods
_drag: function(evt) {
var dd = Kinetic.DD,
node = dd.node;
if(node) {
2013-12-19 22:47:06 +08:00
if(!dd.isDragging) {
var pos = node.getStage().getPointerPosition();
var dragDistance = node.getAttr('dragDistance') || dd.distance;
var distance = Math.max(
Math.abs(pos.x - dd.startPointerPos.x),
Math.abs(pos.y - dd.startPointerPos.y)
);
if (distance < dragDistance) {
return;
}
}
2013-08-12 18:00:08 +08:00
node._setDragPosition(evt);
if(!dd.isDragging) {
dd.isDragging = true;
2013-05-21 22:14:27 +08:00
node.fire('dragstart', evt, true);
}
// execute ondragmove if defined
2013-05-21 22:14:27 +08:00
node.fire('dragmove', evt, true);
}
},
_endDragBefore: function(evt) {
var dd = Kinetic.DD,
node = dd.node,
nodeType, layer;
if(node) {
2014-02-27 08:49:18 +08:00
nodeType = node.nodeType;
layer = node.getLayer();
dd.anim.stop();
// only fire dragend event if the drag and drop
// operation actually started.
if(dd.isDragging) {
dd.isDragging = false;
Kinetic.listenClickTap = false;
if (evt) {
evt.dragEndNode = node;
}
}
delete dd.node;
(layer || node).draw();
}
},
_endDragAfter: function(evt) {
evt = evt || {};
var dragEndNode = evt.dragEndNode;
if (evt && dragEndNode) {
2014-02-27 08:49:18 +08:00
dragEndNode.fire('dragend', evt, true);
}
}
};
// Node extenders
/**
* initiate drag and drop
* @method
* @memberof Kinetic.Node.prototype
*/
Kinetic.Node.prototype.startDrag = function() {
var dd = Kinetic.DD,
stage = this.getStage(),
layer = this.getLayer(),
pos = stage.getPointerPosition(),
ap = this.getAbsolutePosition();
if(pos) {
if (dd.node) {
dd.node.stopDrag();
}
dd.node = this;
2013-12-19 22:47:06 +08:00
dd.startPointerPos = pos;
dd.offset.x = pos.x - ap.x;
dd.offset.y = pos.y - ap.y;
dd.anim.setLayers(layer || this.getLayers());
dd.anim.start();
2013-08-12 18:00:08 +08:00
this._setDragPosition();
}
};
2013-08-12 18:00:08 +08:00
Kinetic.Node.prototype._setDragPosition = function(evt) {
var dd = Kinetic.DD,
2013-08-12 18:00:08 +08:00
pos = this.getStage().getPointerPosition(),
2014-02-28 00:07:29 +08:00
dbf = this.getDragBoundFunc();
if (!pos) {
return;
}
var newNodePos = {
x: pos.x - dd.offset.x,
y: pos.y - dd.offset.y
};
2013-08-12 18:00:08 +08:00
if(dbf !== undefined) {
newNodePos = dbf.call(this, newNodePos, evt);
}
this.setAbsolutePosition(newNodePos);
};
/**
* stop drag and drop
* @method
* @memberof Kinetic.Node.prototype
*/
Kinetic.Node.prototype.stopDrag = function() {
var dd = Kinetic.DD,
evt = {};
dd._endDragBefore(evt);
dd._endDragAfter(evt);
};
Kinetic.Node.prototype.setDraggable = function(draggable) {
this._setAttr('draggable', draggable);
this._dragChange();
};
var origDestroy = Kinetic.Node.prototype.destroy;
Kinetic.Node.prototype.destroy = function() {
var dd = Kinetic.DD;
// stop DD
if(dd.node && dd.node._id === this._id) {
this.stopDrag();
}
origDestroy.call(this);
};
/**
* determine if node is currently in drag and drop mode
* @method
* @memberof Kinetic.Node.prototype
*/
Kinetic.Node.prototype.isDragging = function() {
var dd = Kinetic.DD;
return dd.node && dd.node._id === this._id && dd.isDragging;
};
Kinetic.Node.prototype._listenDrag = function() {
var that = this;
this._dragCleanup();
if (this.getClassName() === 'Stage') {
this.on('contentMousedown.kinetic contentTouchstart.kinetic', function(evt) {
if(!Kinetic.DD.node) {
that.startDrag(evt);
}
});
}
else {
this.on('mousedown.kinetic touchstart.kinetic', function(evt) {
if(!Kinetic.DD.node) {
that.startDrag(evt);
}
});
}
// listening is required for drag and drop
/*
this._listeningEnabled = true;
this._clearSelfAndAncestorCache('listeningEnabled');
*/
};
Kinetic.Node.prototype._dragChange = function() {
if(this.attrs.draggable) {
this._listenDrag();
}
else {
// remove event listeners
this._dragCleanup();
/*
* force drag and drop to end
* if this node is currently in
* drag and drop mode
*/
var stage = this.getStage();
var dd = Kinetic.DD;
if(stage && dd.node && dd.node._id === this._id) {
dd.node.stopDrag();
}
}
};
Kinetic.Node.prototype._dragCleanup = function() {
2013-11-06 18:29:45 +08:00
if (this.getClassName() === 'Stage') {
this.off('contentMousedown.kinetic');
this.off('contentTouchstart.kinetic');
} else {
this.off('mousedown.kinetic');
this.off('touchstart.kinetic');
}
};
Kinetic.Factory.addGetterSetter(Kinetic.Node, 'dragBoundFunc');
/**
2014-01-08 16:07:38 +08:00
* get/set drag bound function. This is used to override the default
* drag and drop position
2014-01-08 16:07:38 +08:00
* @name dragBoundFunc
2013-05-16 15:28:49 +08:00
* @method
* @memberof Kinetic.Node.prototype
* @param {Function} dragBoundFunc
2014-01-08 16:07:38 +08:00
* @returns {Function}
* @example
* // get drag bound function<br>
* var dragBoundFunc = node.dragBoundFunc();<br><br>
*
* // create vertical drag and drop<br>
* node.dragBoundFunc(function(){<br>
* return {<br>
* x: this.getAbsolutePosition().x,<br>
* y: pos.y<br>
* };<br>
* });
*/
Kinetic.Factory.addGetter(Kinetic.Node, 'draggable', false);
Kinetic.Factory.addOverloadedGetterSetter(Kinetic.Node, 'draggable');
/**
* get/set draggable flag
* @name draggable
2013-05-16 15:28:49 +08:00
* @method
* @memberof Kinetic.Node.prototype
* @param {Boolean} draggable
* @returns {Boolean}
* @example
2014-01-08 16:07:38 +08:00
* // get draggable flag<br>
* var draggable = node.draggable();<br><br>
*
2014-01-08 16:07:38 +08:00
* // enable drag and drop<br>
* node.draggable(true);<br><br>
*
2014-01-08 16:07:38 +08:00
* // disable drag and drop<br>
* node.draggable(false);
*/
var html = Kinetic.document.documentElement;
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);
})();