fix dragstart bug. close #708

This commit is contained in:
Anton Lavrenov 2019-08-12 17:31:13 +07:00
parent 37fcd13fa0
commit 57d9917b62
6 changed files with 199 additions and 1420 deletions

1450
konva.js

File diff suppressed because it is too large Load Diff

2
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -443,7 +443,7 @@ export abstract class Container<ChildType extends Node> extends Node<
var layer = this.getLayer();
var layerUnderDrag = false;
DD._dragElements.forEach(elem => {
if (elem.isDragging && elem.node.getLayer() === layer) {
if (elem.dragStatus === 'dragging' && elem.node.getLayer() === layer) {
layerUnderDrag = true;
}
});

View File

@ -7,7 +7,7 @@ export const DD = {
get isDragging() {
var flag = false;
DD._dragElements.forEach(elem => {
if (elem.isDragging) {
if (elem.dragStatus === 'dragging') {
flag = true;
}
});
@ -28,9 +28,13 @@ export const DD = {
node: Node;
startPointerPos: Vector2d;
offset: Vector2d;
isDragging: boolean;
pointerId?: number;
dragStopped: boolean;
// when we just put pointer down on a node
// it will create drag element
dragStatus: 'ready' | 'dragging' | 'stopped';
// dragStarted: boolean;
// isDragging: boolean;
// dragStopped: boolean;
}
>(),
@ -55,7 +59,7 @@ export const DD = {
if (!pos) {
return;
}
if (!elem.isDragging) {
if (elem.dragStatus !== 'dragging') {
var dragDistance = node.dragDistance();
var distance = Math.max(
Math.abs(pos.x - elem.startPointerPos.x),
@ -64,16 +68,7 @@ export const DD = {
if (distance < dragDistance) {
return;
}
elem.isDragging = true;
node.fire(
'dragstart',
{
type: 'dragstart',
target: node,
evt: evt
},
true
);
node.startDrag(evt);
// a user can stop dragging inside `dragstart`
if (!node.isDragging()) {
return;
@ -112,13 +107,12 @@ export const DD = {
return;
}
if (elem.isDragging) {
if (elem.dragStatus === 'dragging') {
DD.justDragged = true;
Konva.listenClickTap = false;
}
elem.dragStopped = true;
elem.isDragging = false;
elem.dragStatus = 'stopped';
const drawNode =
elem.node.getLayer() ||
@ -130,7 +124,7 @@ export const DD = {
},
_endDragAfter(evt) {
DD._dragElements.forEach((elem, key) => {
if (elem.dragStopped) {
if (elem.dragStatus === 'stopped') {
elem.node.fire(
'dragend',
{

View File

@ -2229,32 +2229,47 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
}
// drag & drop
_createDragElement(evt) {
var pointerId = evt ? evt.pointerId : undefined;
var stage = this.getStage();
var ap = this.getAbsolutePosition();
var pos =
stage._getPointerById(pointerId) ||
stage._changedPointerPositions[0] ||
ap;
DD._dragElements.set(this._id, {
node: this,
startPointerPos: pos,
offset: {
x: pos.x - ap.x,
y: pos.y - ap.y
},
dragStatus: 'ready',
pointerId
});
}
/**
* initiate drag and drop
* initiate drag and drop.
* @method
* @name Konva.Node#startDrag
*/
startDrag(evt?: any) {
// forceDrag means it is started by user
const forceDrag = !evt;
var pointerId = evt ? evt.pointerId : undefined;
var stage = this.getStage(),
pos = stage._getPointerById(pointerId),
ap = this.getAbsolutePosition();
if (pos || forceDrag) {
DD._dragElements.set(this._id, {
node: this,
startPointerPos: pos,
offset: forceDrag ? {x: 0, y: 0 } : {
x: pos.x - ap.x,
y: pos.y - ap.y
},
isDragging: forceDrag ? true : false,
pointerId,
dragStopped: false
});
if (!DD._dragElements.has(this._id)) {
this._createDragElement(evt);
}
const elem = DD._dragElements.get(this._id);
elem.dragStatus = 'dragging';
this.fire(
'dragstart',
{
type: 'dragstart',
target: this,
evt: evt && evt.evt
},
true
);
}
_setDragPosition(evt, elem) {
@ -2300,7 +2315,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
var evt = {};
const elem = DD._dragElements.get(this._id);
if (elem) {
elem.dragStopped = true;
elem.dragStatus = 'stopped';
}
DD._endDragBefore(evt);
DD._endDragAfter(evt);
@ -2318,7 +2333,7 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
*/
isDragging() {
const elem = DD._dragElements.get(this._id);
return elem ? elem.isDragging : false;
return elem ? elem.dragStatus === 'dragging' : false;
}
_listenDrag() {
@ -2340,11 +2355,12 @@ export abstract class Node<Config extends NodeConfig = NodeConfig> {
if (this.isAncestorOf(elem.node)) {
hasDraggingChild = true;
}
})
});
// nested drag can be started
// in that case we don't need to start new drag
if (!hasDraggingChild) {
this.startDrag(evt);
this._createDragElement(evt);
}
});
}

View File

@ -659,22 +659,32 @@ suite('DragAndDrop', function() {
]);
// move one finger
stage.simulateTouchMove([
{
x: 100,
y: 100,
id: 0
},
{
x: 270,
y: 70,
id: 1
}
]);
stage.simulateTouchMove(
[
{
x: 100,
y: 100,
id: 0
},
{
x: 270,
y: 70,
id: 1
}
],
[
{
x: 100,
y: 100,
id: 0
}
]
);
assert.equal(dragstart1, 1);
assert.equal(circle1.isDragging(), true);
assert.equal(dragmove1, 1);
assert.equal(dragmove2, 0);
assert.equal(circle1.x(), 100);
assert.equal(circle1.y(), 100);
@ -944,6 +954,41 @@ suite('DragAndDrop', function() {
assert.equal(circle.y(), 80);
});
test('calling startDrag show still fire event when required', function() {
var stage = addStage();
var layer = new Konva.Layer();
var circle = new Konva.Circle({
x: 70,
y: 70,
radius: 70,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
name: 'myCircle',
draggable: true
});
var dragstart = 0;
circle.on('dragstart', function() {
dragstart += 1;
});
layer.add(circle);
stage.add(layer);
// register pointer
stage.simulateMouseMove({ x: 70, y: 80 });
circle.startDrag();
assert.equal(dragstart, 1);
assert.equal(circle.isDragging(), true);
// moving by one pixel should move circle too
stage.simulateMouseMove({ x: 70, y: 81 });
stage.simulateMouseUp({ x: 70, y: 81 });
assert.equal(circle.x(), 70);
assert.equal(circle.y(), 71);
});
test('try nested dragging', function() {
var stage = addStage();
var layer = new Konva.Layer({