From 4f1124460779d6f70f6f20818bea5121dd332459 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 6 May 2021 08:41:34 -0500 Subject: [PATCH] fix arrow head direction. close #501 --- src/shapes/Arrow.ts | 27 ++++++++++++++++++++++++--- test/unit/Arrow-test.ts | 21 ++++++++++++++++----- test/unit/Container-test.ts | 6 +++++- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/shapes/Arrow.ts b/src/shapes/Arrow.ts index c78a99d7..7e847391 100644 --- a/src/shapes/Arrow.ts +++ b/src/shapes/Arrow.ts @@ -3,6 +3,7 @@ import { Line, LineConfig } from './Line'; import { GetSet } from '../types'; import { getNumberValidator } from '../Validators'; import { _registerNode } from '../Global'; +import { Path } from './Path'; export interface ArrowConfig extends LineConfig { points: number[]; @@ -49,20 +50,40 @@ export class Arrow extends Line { if (fromTension) { tp = this.getTensionPoints(); } + var length = this.pointerLength(); var n = points.length; var dx, dy; if (fromTension) { - dx = points[n - 2] - (tp[tp.length - 2] + tp[tp.length - 4]) / 2; - dy = points[n - 1] - (tp[tp.length - 1] + tp[tp.length - 3]) / 2; + const lastPoints = [ + tp[tp.length - 4], + tp[tp.length - 3], + tp[tp.length - 2], + tp[tp.length - 1], + points[n - 2], + points[n - 1], + ]; + const lastLength = Path.calcLength( + tp[tp.length - 4], + tp[tp.length - 3], + 'C', + lastPoints + ); + const previous = Path.getPointOnQuadraticBezier( + Math.min(1, 1 - length / lastLength), + ...lastPoints + ); + + dx = points[n - 2] - previous.x; + dy = points[n - 1] - previous.y; } else { dx = points[n - 2] - points[n - 4]; dy = points[n - 1] - points[n - 3]; } var radians = (Math.atan2(dy, dx) + PI2) % PI2; - var length = this.pointerLength(); + var width = this.pointerWidth(); if (this.pointerAtEnding()) { diff --git a/test/unit/Arrow-test.ts b/test/unit/Arrow-test.ts index 831f3ced..6695dbe0 100644 --- a/test/unit/Arrow-test.ts +++ b/test/unit/Arrow-test.ts @@ -81,11 +81,11 @@ describe('Arrow', function () { layer.add(arrow); stage.add(layer); - var trace = layer.getContext().getTrace(); + var trace = layer.getContext().getTrace(false, true); 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(1.893);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();save();translate(50,50);rotate(2.82);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();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();' ); }); @@ -94,7 +94,18 @@ describe('Arrow', function () { var layer = new Konva.Layer(); var arrow = new Konva.Arrow({ - points: [79, 63, 87, 80, 124, 82, 141, 107, 165, 104], + points: [ + 79.57486136783733, + 63.27171903881701, + 87.33826247689463, + 80.73937153419593, + 124.99075785582254, + 82.29205175600738, + 141.68207024029573, + 107.52310536044362, + 165.74861367837337, + 104.80591497227356, + ], stroke: 'red', fill: 'red', tension: 1, @@ -105,11 +116,11 @@ describe('Arrow', function () { layer.add(arrow); stage.add(layer); - var trace = layer.getContext().getTrace(); + var trace = layer.getContext().getTrace(false, true); assert.equal( trace, - 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(79,63);quadraticCurveTo(71.86,73.607,87,80);bezierCurveTo(116.86,92.607,94.263,67.131,124,82);bezierCurveTo(148.263,94.131,118.223,94.778,141,107);quadraticCurveTo(159.223,116.778,165,104);lineWidth=2;strokeStyle=red;stroke();save();beginPath();translate(165,104);rotate(5.796);moveTo(0,0);lineTo(-10,5);lineTo(-10,-5);closePath();restore();save();translate(79,63);rotate(4.681);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();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/Container-test.ts b/test/unit/Container-test.ts index 0c76bc12..b7abd823 100644 --- a/test/unit/Container-test.ts +++ b/test/unit/Container-test.ts @@ -1,6 +1,6 @@ import { assert } from 'chai'; import { Shape } from '../../src/Shape.js'; -import { addStage, Konva, compareLayers } from './test-utils'; +import { addStage, Konva, compareLayers, isNode } from './test-utils'; describe('Container', function () { // ====================================================== @@ -71,6 +71,10 @@ describe('Container', function () { // ====================================================== it('clip function', function () { + if (isNode) { + // how to use Path2D in nodejs env? + return; + } var stage = addStage(); // cliped by circle is the same as draw circle