From 586ea3d860cb2aed78500846fdf14184f1fe8d97 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 22 Sep 2021 10:14:38 -0500 Subject: [PATCH] fix line, fix finger, close #1181, close #1177 --- src/Global.ts | 3 ++ src/Stage.ts | 6 ++- src/shapes/Arrow.ts | 6 +++ test/import-test.js | 17 +------- test/import-test.mjs | 27 ++++++++++++ test/package.json | 3 ++ test/unit/Arrow-test.ts | 80 +++++++++++++++++++++++++++++------ test/unit/TouchEvents-test.ts | 54 +++++++++++++++++++++++ 8 files changed, 167 insertions(+), 29 deletions(-) create mode 100644 test/import-test.mjs create mode 100644 test/package.json diff --git a/src/Global.ts b/src/Global.ts index b5015a01..d54b8f17 100644 --- a/src/Global.ts +++ b/src/Global.ts @@ -87,6 +87,9 @@ export const Konva = { _mouseInDblClickWindow: false, _touchInDblClickWindow: false, _pointerInDblClickWindow: false, + _mouseDblClickPointerId: null, + _touchDblClickPointerId: null, + _pointerDblClickPointerId: null, /** * Global pixel ratio configuration. KonvaJS automatically detect pixel ratio of current device. diff --git a/src/Stage.ts b/src/Stage.ts index c9eb49a6..652f324a 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -671,12 +671,16 @@ export class Stage extends Container { const event = { evt: evt, pointerId }; let fireDblClick = false; - if (Konva['_' + eventType + 'InDblClickWindow']) { + if ( + Konva['_' + eventType + 'InDblClickWindow'] && + Konva['_' + eventType + 'InDblClickWindowId'] === pointerId + ) { fireDblClick = true; clearTimeout(this[eventType + 'DblTimeout']); } else if (!DD.justDragged) { // don't set inDblClickWindow after dragging Konva['_' + eventType + 'InDblClickWindow'] = true; + Konva['_' + eventType + 'InDblClickWindowId'] = pointerId; clearTimeout(this[eventType + 'DblTimeout']); } diff --git a/src/shapes/Arrow.ts b/src/shapes/Arrow.ts index 2f75115e..d9b03cea 100644 --- a/src/shapes/Arrow.ts +++ b/src/shapes/Arrow.ts @@ -105,6 +105,7 @@ export class Arrow extends Line { if (this.pointerAtBeginning()) { ctx.save(); + ctx.beginPath(); ctx.translate(points[0], points[1]); if (fromTension) { dx = (tp[0] + tp[2]) / 2 - points[0]; @@ -122,6 +123,11 @@ export class Arrow extends Line { ctx.restore(); } + const hasPointer = this.pointerAtEnding() || this.pointerAtBeginning(); + if (!hasPointer) { + return; + } + // here is a tricky part // we need to disable dash for arrow pointers var isDashEnabled = this.dashEnabled(); diff --git a/test/import-test.js b/test/import-test.js index d2779830..5057c5b9 100644 --- a/test/import-test.js +++ b/test/import-test.js @@ -5,22 +5,7 @@ function equal(val1, val2, message) { } // try to import only core -import Konva from '../lib/Core.js'; - -// no external shapes -// equal(Konva.Rect, undefined, 'no external shapes'); - -import { Rect } from '../lib/shapes/Rect.js'; - -equal(Rect !== undefined, true, 'Rect is defined'); - -equal(Konva.Rect, Rect, 'Rect is injected'); - -import Konva2 from '../lib/index-node.js'; - -equal(Konva2.Rect, Rect, 'Rect is injected'); - -equal(Konva2, Konva, 'Same Konva'); +const Konva = require('../cmj').default; // just do a simple action const stage = new Konva.Stage(); diff --git a/test/import-test.mjs b/test/import-test.mjs new file mode 100644 index 00000000..d2779830 --- /dev/null +++ b/test/import-test.mjs @@ -0,0 +1,27 @@ +function equal(val1, val2, message) { + if (val1 !== val2) { + throw new Error('Not passed: ' + message); + } +} + +// try to import only core +import Konva from '../lib/Core.js'; + +// no external shapes +// equal(Konva.Rect, undefined, 'no external shapes'); + +import { Rect } from '../lib/shapes/Rect.js'; + +equal(Rect !== undefined, true, 'Rect is defined'); + +equal(Konva.Rect, Rect, 'Rect is injected'); + +import Konva2 from '../lib/index-node.js'; + +equal(Konva2.Rect, Rect, 'Rect is injected'); + +equal(Konva2, Konva, 'Same Konva'); + +// just do a simple action +const stage = new Konva.Stage(); +stage.toDataURL(); diff --git a/test/package.json b/test/package.json new file mode 100644 index 00000000..5bbefffb --- /dev/null +++ b/test/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/test/unit/Arrow-test.ts b/test/unit/Arrow-test.ts index 6695dbe0..8ef67ee0 100644 --- a/test/unit/Arrow-test.ts +++ b/test/unit/Arrow-test.ts @@ -2,7 +2,7 @@ import { assert } from 'chai'; import { addStage, Konva, cloneAndCompareLayer } from './test-utils'; -describe('Arrow', function () { +describe.only('Arrow', function () { // ====================================================== it('add arrow', function () { var stage = addStage(); @@ -66,6 +66,68 @@ describe('Arrow', function () { ); }); + it('dash checks', function () { + var stage = addStage(); + + var layer = new Konva.Layer(); + stage.add(layer); + + var width = stage.width(); + var height = stage.height(); + + // regular line + var arrow = new Konva.Arrow({ + x: stage.width() / 4, + y: stage.height() / 4, + points: [0, 0, width / 2, height / 2], + pointerLength: 20, + pointerWidth: 20, + fill: 'red', + stroke: 'red', + strokeWidth: 4, + dash: [10, 5], + }); + layer.add(arrow); + + // arrow with no end (like a simple line) + var arrowNoEnd = new Konva.Arrow({ + x: stage.width() / 4 + 50, + y: stage.height() / 4, + points: [0, 0, width / 2, height / 2], + pointerLength: 20, + pointerWidth: 20, + pointerAtEnding: false, + fill: 'blue', + stroke: 'blue', + strokeWidth: 4, + dash: [10, 5], + }); + layer.add(arrowNoEnd); + + var arrowStartButNoEnd = new Konva.Arrow({ + x: stage.width() / 4 + 100, + y: stage.height() / 4, + points: [0, 0, width / 2, height / 2], + pointerLength: 20, + pointerWidth: 20, + pointerAtEnding: false, + pointerAtBeginning: true, + fill: 'green', + stroke: 'green', + strokeWidth: 4, + dash: [10, 5], + }); + layer.add(arrowStartButNoEnd); + layer.draw(); + + var trace = layer.getContext().getTrace(); + + assert.equal( + trace, + 'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,144.5,50);beginPath();moveTo(0,0);lineTo(289,100);setLineDash(10,5);lineDashOffset=0;lineWidth=4;strokeStyle=red;stroke();save();beginPath();translate(289,100);rotate(0.333);moveTo(0,0);lineTo(-20,10);lineTo(-20,-10);closePath();restore();setLineDash();fillStyle=red;fill();lineWidth=4;strokeStyle=red;stroke();restore();save();transform(1,0,0,1,194.5,50);beginPath();moveTo(0,0);lineTo(289,100);setLineDash(10,5);lineDashOffset=0;lineWidth=4;strokeStyle=blue;stroke();restore();save();transform(1,0,0,1,244.5,50);beginPath();moveTo(0,0);lineTo(289,100);setLineDash(10,5);lineDashOffset=0;lineWidth=4;strokeStyle=green;stroke();save();beginPath();translate(0,0);rotate(3.475);moveTo(0,0);lineTo(-20,10);lineTo(-20,-10);closePath();restore();setLineDash();fillStyle=green;fill();lineWidth=4;strokeStyle=green;stroke();restore();' + ); + }); + it('direction with tension', function () { var stage = addStage(); var layer = new Konva.Layer(); @@ -85,7 +147,7 @@ describe('Arrow', function () { assert.equal( trace, - 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(50,50);quadraticCurveTo(75,25,100,50);quadraticCurveTo(125,75,100,100);lineWidth=2;strokeStyle=red;stroke();save();beginPath();translate(100,100);rotate(2);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();save();translate(50,50);rotate(2);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();setLineDash();fillStyle=red;fill();lineWidth=2;strokeStyle=red;stroke();restore();' + 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(50,50);quadraticCurveTo(75,25,100,50);quadraticCurveTo(125,75,100,100);lineWidth=2;strokeStyle=red;stroke();save();beginPath();translate(100,100);rotate(2);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();save();beginPath();translate(50,50);rotate(2);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();setLineDash();fillStyle=red;fill();lineWidth=2;strokeStyle=red;stroke();restore();' ); }); @@ -95,15 +157,9 @@ describe('Arrow', function () { var arrow = new Konva.Arrow({ points: [ - 79.57486136783733, - 63.27171903881701, - 87.33826247689463, - 80.73937153419593, - 124.99075785582254, - 82.29205175600738, - 141.68207024029573, - 107.52310536044362, - 165.74861367837337, + 79.57486136783733, 63.27171903881701, 87.33826247689463, + 80.73937153419593, 124.99075785582254, 82.29205175600738, + 141.68207024029573, 107.52310536044362, 165.74861367837337, 104.80591497227356, ], stroke: 'red', @@ -120,7 +176,7 @@ describe('Arrow', function () { assert.equal( trace, - 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(79,63);quadraticCurveTo(72,74,87,80);bezierCurveTo(117,93,94,67,124,82);bezierCurveTo(149,94,119,95,141,107);quadraticCurveTo(159,117,165,104);lineWidth=2;strokeStyle=red;stroke();save();beginPath();translate(165,104);rotate(5);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();save();translate(79,63);rotate(4);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();setLineDash();fillStyle=red;fill();lineWidth=2;strokeStyle=red;stroke();restore();' + 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(79,63);quadraticCurveTo(72,74,87,80);bezierCurveTo(117,93,94,67,124,82);bezierCurveTo(149,94,119,95,141,107);quadraticCurveTo(159,117,165,104);lineWidth=2;strokeStyle=red;stroke();save();beginPath();translate(165,104);rotate(5);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();save();beginPath();translate(79,63);rotate(4);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();setLineDash();fillStyle=red;fill();lineWidth=2;strokeStyle=red;stroke();restore();' ); }); diff --git a/test/unit/TouchEvents-test.ts b/test/unit/TouchEvents-test.ts index b6c49d69..d75993bc 100644 --- a/test/unit/TouchEvents-test.ts +++ b/test/unit/TouchEvents-test.ts @@ -469,6 +469,60 @@ describe('TouchEvents', function () { assert.equal(stageTouchEnd, 3); }); + it('letting go of two fingers quickly should not fire dbltap', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + var touchend = 0; + var dbltap = 0; + + stage.on('dbltap', function (e) { + dbltap += 1; + }); + + stage.on('touchend', function (e) { + touchend += 1; + }); + + simulateTouchStart( + stage, + [{ x: 100, y: 100, id: 0 }], + [{ x: 100, y: 100, id: 0 }] + ); + + simulateTouchStart( + stage, + [{ x: 110, y: 110, id: 1 }], + [{ x: 110, y: 110, id: 1 }] + ); + + assert.equal( + touchend, + 0, + '1) no touchend triggered after holding down two fingers' + ); + assert.equal( + dbltap, + 0, + '1) no dbltap triggered after holding down two fingers' + ); + + simulateTouchEnd(stage, [], [{ x: 100, y: 100, id: 0 }]); + simulateTouchEnd(stage, [], [{ x: 110, y: 110, id: 1 }]); + + assert.equal( + touchend, + 2, + '2) touchend triggered twice after letting go two fingers' + ); + assert.equal( + dbltap, + 0, + '2) no dbltap triggered after letting go two fingers' + ); + }); + it('can capture touch events', function () { Konva.capturePointerEventsEnabled = true; var stage = addStage();