From 467147b4c7980511ee9303d08038a63ef17632c8 Mon Sep 17 00:00:00 2001 From: CPatchane Date: Thu, 28 Dec 2023 14:45:39 +0100 Subject: [PATCH 01/80] Add support for ctx.roundRect https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/roundRect --- src/Context.ts | 13 +++++++++++++ test/unit/Context-test.ts | 1 + 2 files changed, 14 insertions(+) diff --git a/src/Context.ts b/src/Context.ts index 928aaa8b6..ef75ca2ac 100644 --- a/src/Context.ts +++ b/src/Context.ts @@ -58,6 +58,7 @@ var COMMA = ',', 'putImageData', 'quadraticCurveTo', 'rect', + 'roundRect', 'restore', 'rotate', 'save', @@ -586,6 +587,18 @@ export class Context { rect(x: number, y: number, width: number, height: number) { this._context.rect(x, y, width, height); } + /** + * roundRect function. + * @method + * @name Konva.Context#roundRect + */ + roundRect(x: number, y: number, width: number, height: number, radii: number) { + if (this._context.roundRect) { + this._context.roundRect(x, y, width, height, radii); + } else { + this._context.rect(x, y, width, height); + } + } /** * putImageData function. * @method diff --git a/test/unit/Context-test.ts b/test/unit/Context-test.ts index 7d5a256c6..7cf6fc5d8 100644 --- a/test/unit/Context-test.ts +++ b/test/unit/Context-test.ts @@ -22,6 +22,7 @@ describe('Context', function () { 'arc', 'arcTo', 'rect', + 'roundRect', 'ellipse', 'fill', 'stroke', From 49e6e3e824eb3201908d623d201ab08fb03b0e6e Mon Sep 17 00:00:00 2001 From: CPatchane Date: Tue, 2 Jan 2024 21:13:15 +0100 Subject: [PATCH 02/80] Remove the existence check --- src/Context.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Context.ts b/src/Context.ts index ef75ca2ac..766958f5e 100644 --- a/src/Context.ts +++ b/src/Context.ts @@ -592,12 +592,14 @@ export class Context { * @method * @name Konva.Context#roundRect */ - roundRect(x: number, y: number, width: number, height: number, radii: number) { - if (this._context.roundRect) { - this._context.roundRect(x, y, width, height, radii); - } else { - this._context.rect(x, y, width, height); - } + roundRect( + x: number, + y: number, + width: number, + height: number, + radii: number + ) { + this._context.roundRect(x, y, width, height, radii); } /** * putImageData function. From f6ccabb34a2983a43b6e492d95743949a4801196 Mon Sep 17 00:00:00 2001 From: CPatchane Date: Tue, 2 Jan 2024 21:13:32 +0100 Subject: [PATCH 03/80] Correctly type radii param --- src/Context.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Context.ts b/src/Context.ts index 766958f5e..5917a74e4 100644 --- a/src/Context.ts +++ b/src/Context.ts @@ -597,7 +597,7 @@ export class Context { y: number, width: number, height: number, - radii: number + radii: number | DOMPointInit | (number | DOMPointInit)[] ) { this._context.roundRect(x, y, width, height, radii); } From a1660e1ccbd18c8b1b7d7303ea25f7a14a2d7858 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 5 Jan 2024 10:55:28 -0500 Subject: [PATCH 04/80] fix filters work. close #1697 --- src/Node.ts | 9 ++++++--- test/manual/Pixelate-test.ts | 24 ++++++++++++++++++++++-- test/unit/Node-cache-test.ts | 2 +- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Node.ts b/src/Node.ts index ae4ac02e9..85deed311 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -343,10 +343,13 @@ export abstract class Node { return; } - // let's just add 1 pixel extra, // because using Math.floor on x, y position may shift drawing - width += offset * 2 + 1; - height += offset * 2 + 1; + // to avoid shift we need to increase size + // but we better to avoid it, for better filters flows + const extraPaddingX = Math.abs(Math.round(rect.x) - x) > 0.5 ? 1 : 0; + const extraPaddingY = Math.abs(Math.round(rect.y) - y) > 0.5 ? 1 : 0; + width += offset * 2 + extraPaddingX; + height += offset * 2 + extraPaddingY; x -= offset; y -= offset; diff --git a/test/manual/Pixelate-test.ts b/test/manual/Pixelate-test.ts index cb22ea303..a8a9dc416 100644 --- a/test/manual/Pixelate-test.ts +++ b/test/manual/Pixelate-test.ts @@ -1,6 +1,5 @@ -import { assert } from 'chai'; - import { addStage, Konva, loadImage } from '../unit/test-utils'; +import { cloneAndCompareLayer } from '../unit/test-utils'; describe('Pixelate', function () { // ====================================================== @@ -42,4 +41,25 @@ describe('Pixelate', function () { done(); }); }); + + it('make sure we have no extra transparent pixels', function (done) { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + Konva.Image.fromURL( + 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGUAAABmCAYAAADS6F9hAAAAAXNSR0IArs4c6QAAAXJJREFUeF7t1cEJADAMw8B2/6Fd6BT3UCYQEiZ3205HGbhFoXp8mKJ4TYoCNilKUUQDIFM/pSigARCppRQFNAAitZSigAZApJZSFNAAiNRSigIaAJFaSlFAAyBSSykKaABEailFAQ2ASC2lKKABEKmlFAU0ACK1lKKABkCkllIU0ACI1FKKAhoAkVpKUUADIFJLKQpoAERqKUUBDYBILaUooAEQqaUUBTQAIrWUooAGQKSWUhTQAIjUUooCGgCRWkpRQAMgUkspCmgARGopRQENgEgtpSigARCppRQFNAAitZSigAZApJZSFNAAiNRSigIaAJFaSlFAAyBSSykKaABEailFAQ2ASC2lKKABEKmlFAU0ACK1lKKABkCkllIU0ACI1FKKAhoAkVpKUUADIFJLKQpoAERqKUUBDYBILaUooAEQqaUUBTQAIrWUooAGQKSWUhTQAIjUUooCGgCRWkpRQAMgUkspCmgARGopRQENgEgPgGOW3jCsp3sAAAAASUVORK5CYII=', + function (image) { + layer.add(image); + + image.cache(); + image.filters([Konva.Filters.Pixelate]); + image.pixelSize(4); + layer.draw(); + cloneAndCompareLayer(layer); + + done(); + } + ); + }); }); diff --git a/test/unit/Node-cache-test.ts b/test/unit/Node-cache-test.ts index 1fbf759c6..687a1c5ad 100644 --- a/test/unit/Node-cache-test.ts +++ b/test/unit/Node-cache-test.ts @@ -1469,7 +1469,7 @@ describe('Caching', function () { layer.draw(); assert.equal( circle._cache.get('canvas').filter.width, - 21 * circle._cache.get('canvas').filter.pixelRatio + 20 * circle._cache.get('canvas').filter.pixelRatio ); circle.filters([]); // TODO: should we clear cache canvas? From 0d502baccd1ab102b43625623a1e76f9fb3eb9ec Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 17 Jan 2024 19:12:49 -0500 Subject: [PATCH 05/80] fix buffer export --- CHANGELOG.md | 5 +++++ src/Container.ts | 8 ++++---- src/Node.ts | 10 ++++++++-- src/Shape.ts | 21 +++++---------------- test/unit/Shape-test.ts | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 73d6115b7..d750190be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.1 (2024-01-17) + +- Fix Pixelate filter work/fix caching size +- Fix node export when large buffer canvas is used + ### 9.3.0 (2023-12-20) - New attribute `rotateLineVisible` for `Konva.Transformer` to show/hide rotate line diff --git a/src/Container.ts b/src/Container.ts index 10f992926..167831bec 100644 --- a/src/Container.ts +++ b/src/Container.ts @@ -342,7 +342,7 @@ export abstract class Container< }); this._requestDraw(); } - drawScene(can?: SceneCanvas, top?: Node) { + drawScene(can?: SceneCanvas, top?: Node, bufferCanvas?: SceneCanvas) { var layer = this.getLayer()!, canvas = can || (layer && layer.getCanvas()), context = canvas && canvas.getContext(), @@ -361,7 +361,7 @@ export abstract class Container< this._drawCachedSceneCanvas(context); context.restore(); } else { - this._drawChildren('drawScene', canvas, top); + this._drawChildren('drawScene', canvas, top, bufferCanvas); } return this; } @@ -387,7 +387,7 @@ export abstract class Container< } return this; } - _drawChildren(drawMethod, canvas, top) { + _drawChildren(drawMethod, canvas, top, bufferCanvas?) { var context = canvas && canvas.getContext(), clipWidth = this.clipWidth(), clipHeight = this.clipHeight(), @@ -426,7 +426,7 @@ export abstract class Container< } this.children?.forEach(function (child) { - child[drawMethod](canvas, top); + child[drawMethod](canvas, top, bufferCanvas); }); if (hasComposition) { context.restore(); diff --git a/src/Node.ts b/src/Node.ts index 85deed311..0aa9f59de 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -449,7 +449,7 @@ export abstract class Node { return this._cache.has(CANVAS); } - abstract drawScene(canvas?: Canvas, top?: Node): void; + abstract drawScene(canvas?: Canvas, top?: Node, bufferCanvas?: Canvas): void; abstract drawHit(canvas?: Canvas, top?: Node): void; /** * Return client rectangle {x, y, width, height} of node. This rectangle also include all styling (strokes, shadows, etc). @@ -1932,6 +1932,12 @@ export abstract class Node { }), context = canvas.getContext(); + const bufferCanvas = new SceneCanvas({ + width: canvas.width, + height: canvas.height, + pixelRatio: canvas.pixelRatio, + }); + if (config.imageSmoothingEnabled === false) { context._context.imageSmoothingEnabled = false; } @@ -1941,7 +1947,7 @@ export abstract class Node { context.translate(-1 * x, -1 * y); } - this.drawScene(canvas); + this.drawScene(canvas, undefined, bufferCanvas); context.restore(); return canvas; diff --git a/src/Shape.ts b/src/Shape.ts index c327dc121..6f403878c 100644 --- a/src/Shape.ts +++ b/src/Shape.ts @@ -469,10 +469,6 @@ export class Shape< // so they use that method with forced fill // it probably will be simpler, then copy/paste the code - // buffer canvas is available only inside the stage - if (!this.getStage()) { - return false; - } // force skip buffer canvas const perfectDrawEnabled = this.attrs.perfectDrawEnabled ?? true; if (!perfectDrawEnabled) { @@ -573,7 +569,7 @@ export class Shape< } return rect; } - drawScene(can?: SceneCanvas, top?: Node) { + drawScene(can?: SceneCanvas, top?: Node, bufferCanvas?: SceneCanvas) { // basically there are 3 drawing modes // 1 - simple drawing when nothing is cached. // 2 - when we are caching current @@ -586,7 +582,6 @@ export class Shape< drawFunc = this.getSceneFunc(), hasShadow = this.hasShadow(), stage, - bufferCanvas, bufferContext; var skipBuffer = canvas.isCache; @@ -614,8 +609,8 @@ export class Shape< // if buffer canvas is needed if (this._useBufferCanvas() && !skipBuffer) { stage = this.getStage(); - bufferCanvas = stage.bufferCanvas; - bufferContext = bufferCanvas.getContext(); + const bc = bufferCanvas || stage.bufferCanvas; + bufferContext = bc.getContext(); bufferContext.clear(); bufferContext.save(); bufferContext._applyLineJoin(this); @@ -626,20 +621,14 @@ export class Shape< drawFunc.call(this, bufferContext, this); bufferContext.restore(); - var ratio = bufferCanvas.pixelRatio; + var ratio = bc.pixelRatio; if (hasShadow) { context._applyShadow(this); } context._applyOpacity(this); context._applyGlobalCompositeOperation(this); - context.drawImage( - bufferCanvas._canvas, - 0, - 0, - bufferCanvas.width / ratio, - bufferCanvas.height / ratio - ); + context.drawImage(bc._canvas, 0, 0, bc.width / ratio, bc.height / ratio); } else { context._applyLineJoin(this); diff --git a/test/unit/Shape-test.ts b/test/unit/Shape-test.ts index d3035562c..0415825f4 100644 --- a/test/unit/Shape-test.ts +++ b/test/unit/Shape-test.ts @@ -12,6 +12,7 @@ import { compareLayers, loadImage, Konva, + compareCanvases, } from './test-utils'; describe('Shape', function () { @@ -1479,6 +1480,40 @@ describe('Shape', function () { } }); + it('export when buffer canvas is used should handle scaling correctly', async function () { + var stage = addStage(); + + var layer = new Konva.Layer(); + stage.add(layer); + + var group = new Konva.Group(); + layer.add(group); + + var text = new Konva.Text({ + text: 'hello', + fontSize: 300, + fill: 'green', + shadowColor: 'black', + }); + group.add(text); + + const canvas1 = group.toCanvas({ + x: group.x(), + y: group.y(), + width: text.width(), + height: text.height(), + }); + text.stroke('transparent'); + const canvas2 = group.toCanvas({ + x: group.x(), + y: group.y(), + width: text.width(), + height: text.height(), + }); + + compareCanvases(canvas2, canvas1, 255, 10); + }); + // ====================================================== it('optional disable shadow for stroke', function () { var stage = addStage(); From 80fad798586834014832eefbaaa49bd0b11339ec Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 17 Jan 2024 19:13:18 -0500 Subject: [PATCH 06/80] update CHANGELOG with new version From 297241add4ff546cba20ea2e6870365b52b2a95a Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 17 Jan 2024 19:13:36 -0500 Subject: [PATCH 07/80] build for 9.3.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cfe497577..69f58f092 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.0", + "version": "9.3.1", "author": "Anton Lavrenov", "files": [ "README.md", From abfdf7153f7443d24bf7bb56be0c3120e5ca3daf Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 17 Jan 2024 19:13:36 -0500 Subject: [PATCH 08/80] update cdn link From 76cace8b38cc873cc66438faa7bd336f6df8bcfa Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 26 Jan 2024 11:08:12 -0500 Subject: [PATCH 09/80] fix large memory usage --- CHANGELOG.md | 4 ++++ src/Node.ts | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d750190be..bea8207ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.2 (2024-01-26) + +- Fix large memory usage on node export + ### 9.3.1 (2024-01-17) - Fix Pixelate filter work/fix caching size diff --git a/src/Node.ts b/src/Node.ts index 0aa9f59de..0ffba2b37 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -1933,8 +1933,10 @@ export abstract class Node { context = canvas.getContext(); const bufferCanvas = new SceneCanvas({ - width: canvas.width, - height: canvas.height, + // width and height already multiplied by pixelRatio + // so we need to revert that + width: canvas.width / canvas.pixelRatio, + height: canvas.height / canvas.pixelRatio, pixelRatio: canvas.pixelRatio, }); From b37e14afff4a0ea3d66b0f13b0aa9f927ee892d2 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 26 Jan 2024 11:08:36 -0500 Subject: [PATCH 10/80] update CHANGELOG with new version From f212a1ad69342ba83f4c0256d30a1fbe455bd659 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 26 Jan 2024 11:08:48 -0500 Subject: [PATCH 11/80] build for 9.3.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 69f58f092..f49b1fb33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.1", + "version": "9.3.2", "author": "Anton Lavrenov", "files": [ "README.md", From 1e2c28738b4247b50f793234cb55e1a3911511f5 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 26 Jan 2024 11:08:49 -0500 Subject: [PATCH 12/80] update cdn link From 4da037a2fa44cb6826e749c2314c0d48a843f69e Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 9 Feb 2024 11:44:32 -0500 Subject: [PATCH 13/80] Another fix for exporting buffered shapes --- CHANGELOG.md | 4 ++++ src/Node.ts | 5 +++-- test/unit/Shape-test.ts | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bea8207ba..e6b4e84fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.3 (2024-02-09) + +- Another fix for exporting buffered shapes + ### 9.3.2 (2024-01-26) - Fix large memory usage on node export diff --git a/src/Node.ts b/src/Node.ts index 0ffba2b37..1cf0c38d9 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -1935,8 +1935,9 @@ export abstract class Node { const bufferCanvas = new SceneCanvas({ // width and height already multiplied by pixelRatio // so we need to revert that - width: canvas.width / canvas.pixelRatio, - height: canvas.height / canvas.pixelRatio, + // also increase size by x nd y offset to make sure content fits canvas + width: canvas.width / canvas.pixelRatio + Math.abs(x), + height: canvas.height / canvas.pixelRatio + Math.abs(y), pixelRatio: canvas.pixelRatio, }); diff --git a/test/unit/Shape-test.ts b/test/unit/Shape-test.ts index 0415825f4..8f023462b 100644 --- a/test/unit/Shape-test.ts +++ b/test/unit/Shape-test.ts @@ -1514,6 +1514,42 @@ describe('Shape', function () { compareCanvases(canvas2, canvas1, 255, 10); }); + it('export when buffer canvas is used should handle scaling correctly another time', async function () { + var stage = addStage(); + + var layer = new Konva.Layer(); + stage.add(layer); + + var group = new Konva.Group({ + x: 400, + }); + layer.add(group); + + var text = new Konva.Text({ + text: 'hello', + fontSize: 300, + fill: 'green', + shadowColor: 'black', + }); + group.add(text); + + const canvas1 = group.toCanvas({ + x: group.x(), + y: group.y(), + width: text.width(), + height: text.height(), + }); + text.stroke('transparent'); + const canvas2 = group.toCanvas({ + x: group.x(), + y: group.y(), + width: text.width(), + height: text.height(), + }); + + compareCanvases(canvas2, canvas1, 240, 110); + }); + // ====================================================== it('optional disable shadow for stroke', function () { var stage = addStage(); From 93106aba5346942919a4c251a13fbb991487b6d4 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 9 Feb 2024 11:45:02 -0500 Subject: [PATCH 14/80] update CHANGELOG with new version From ea92753221ad68f79e06ea3b0bed0e4c1e6acc0d Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 9 Feb 2024 11:45:12 -0500 Subject: [PATCH 15/80] build for 9.3.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f49b1fb33..f4750b8d1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.2", + "version": "9.3.3", "author": "Anton Lavrenov", "files": [ "README.md", From e7672858b7ffed5a9f4dfe7fde65d823941510b4 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 9 Feb 2024 11:45:12 -0500 Subject: [PATCH 16/80] update cdn link From eb4e2b4fef506e6250692cd6fd528e4a54569381 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Sun, 3 Mar 2024 10:42:25 +0700 Subject: [PATCH 17/80] fix cliping with zero size. close #1723 --- src/Container.ts | 6 ++++-- test/unit/Group-test.ts | 41 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/Container.ts b/src/Container.ts index 167831bec..efd4c2f53 100644 --- a/src/Container.ts +++ b/src/Container.ts @@ -392,7 +392,9 @@ export abstract class Container< clipWidth = this.clipWidth(), clipHeight = this.clipHeight(), clipFunc = this.clipFunc(), - hasClip = (clipWidth && clipHeight) || clipFunc; + hasClip = + (typeof clipWidth === 'number' && typeof clipHeight === 'number') || + clipFunc; const selfCache = top === this; @@ -408,7 +410,7 @@ export abstract class Container< } else { var clipX = this.clipX(); var clipY = this.clipY(); - context.rect(clipX, clipY, clipWidth, clipHeight); + context.rect(clipX || 0, clipY || 0, clipWidth, clipHeight); } context.clip.apply(context, clipArgs); m = transform.copy().invert().getMatrix(); diff --git a/test/unit/Group-test.ts b/test/unit/Group-test.ts index f0cc602a0..c2ec769ff 100644 --- a/test/unit/Group-test.ts +++ b/test/unit/Group-test.ts @@ -55,15 +55,43 @@ describe('Group', function () { var path = new Konva.Group({ width: 100, height: 100, - clipFunc: () => [new Path2D('M0 0v50h50Z')] + clipFunc: () => [new Path2D('M0 0v50h50Z')], }); layer.add(path); stage.add(layer); - const trace = layer.getContext().getTrace() + const trace = layer.getContext().getTrace(); - assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();clip([object Path2D]);transform(1,0,0,1,0,0);restore();'); + assert.equal( + trace, + 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();clip([object Path2D]);transform(1,0,0,1,0,0);restore();' + ); + }); + + it('clip group with by zero size', function () { + var stage = addStage(); + + var layer = new Konva.Layer(); + + var group = new Konva.Group({ + width: 100, + height: 100, + clipWidth: 0, + clipHeight: 0, + }); + + layer.add(group); + stage.add(layer); + + const trace = layer.getContext().getTrace(); + + console.log(trace); + + assert.equal( + trace, + 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();rect(0,0,0,0);clip();transform(1,0,0,1,0,0);restore();' + ); }); it('clip group with a Path2D and clipRule', function () { @@ -80,8 +108,11 @@ describe('Group', function () { layer.add(path); stage.add(layer); - const trace = layer.getContext().getTrace() + const trace = layer.getContext().getTrace(); - assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();clip([object Path2D],evenodd);transform(1,0,0,1,0,0);restore();'); + assert.equal( + trace, + 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();clip([object Path2D],evenodd);transform(1,0,0,1,0,0);restore();' + ); }); }); From 8cdac23faa32cf2be271e5d369a4dc4711e8d5f5 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Sun, 3 Mar 2024 10:43:27 +0700 Subject: [PATCH 18/80] update CHANGELOG with new version --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6b4e84fc..7b132d728 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.4 (2024-03-03) + +- Fix clipping with zero size + ### 9.3.3 (2024-02-09) - Another fix for exporting buffered shapes From 9f8c653745c89b4509424a397ee86b795e1d78c7 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Sun, 3 Mar 2024 10:43:42 +0700 Subject: [PATCH 19/80] build for 9.3.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4750b8d1..85f0f0ba0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.3", + "version": "9.3.4", "author": "Anton Lavrenov", "files": [ "README.md", From fe8b7e0fc3694c880d3831ae628ce0452c4800e9 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Sun, 3 Mar 2024 10:43:42 +0700 Subject: [PATCH 20/80] update cdn link From b09ceb34f32c024b6440cdc40ac4f0be61c1e30e Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Sun, 3 Mar 2024 11:45:55 +0700 Subject: [PATCH 21/80] change events order for transformer. fix #1724 --- src/shapes/Transformer.ts | 7 +++- test/unit/Transformer-test.ts | 74 +++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/shapes/Transformer.ts b/src/shapes/Transformer.ts index f699a132d..3585326cd 100644 --- a/src/shapes/Transformer.ts +++ b/src/shapes/Transformer.ts @@ -1109,11 +1109,14 @@ export class Transformer extends Group { const attrs = newLocalTransform.decompose(); node.setAttrs(attrs); - this._fire('transform', { evt: evt, target: node }); - node._fire('transform', { evt: evt, target: node }); node.getLayer()?.batchDraw(); }); this.rotation(Util._getRotation(newAttrs.rotation)); + // trigger transform event AFTER we update rotation + this._nodes.forEach((node) => { + this._fire('transform', { evt: evt, target: node }); + node._fire('transform', { evt: evt, target: node }); + }); this._resetTransformCache(); this.update(); this.getLayer()!.batchDraw(); diff --git a/test/unit/Transformer-test.ts b/test/unit/Transformer-test.ts index 782969936..4d1ef8293 100644 --- a/test/unit/Transformer-test.ts +++ b/test/unit/Transformer-test.ts @@ -4929,4 +4929,78 @@ describe('Transformer', function () { assertAlmostEqual(rect.scaleX(), 1); assertAlmostEqual(rect.scaleY(), 1); }); + + it('should be able to prevent rotation in transform event', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + var rect = new Konva.Rect({ + x: 55, + y: 55, + draggable: true, + width: 100, + height: 100, + fill: 'yellow', + }); + layer.add(rect); + + var tr = new Konva.Transformer({ + nodes: [rect], + }); + layer.add(tr); + layer.draw(); + + tr.on('transform', function (e) { + tr.rotation(0); + }); + + simulateMouseDown(tr, { + x: 100, + y: 2, + }); + simulateMouseMove(tr, { + x: 110, + y: 2, + }); + assert.equal(tr.rotation(), 0); + simulateMouseUp(tr, { x: 110, y: 2 }); + }); + + // it('skip render on hit graph while transforming', function () { + // var stage = addStage(); + // var layer = new Konva.Layer(); + // stage.add(layer); + + // var rect = new Konva.Rect({ + // x: 55, + // y: 55, + // draggable: true, + // width: 100, + // height: 100, + // fill: 'yellow', + // }); + // layer.add(rect); + + // var tr = new Konva.Transformer({ + // nodes: [rect], + // }); + // layer.add(tr); + // layer.draw(); + + // simulateMouseDown(tr, { + // x: 100, + // y: 2, + // }); + // simulateMouseMove(tr, { + // x: 110, + // y: 2, + // }); + // const shape = layer.getIntersection({ + // x: 100, + // y: 100, + // }); + // assert.equal(shape, null); + // simulateMouseUp(tr, { x: 110, y: 2 }); + // }); }); From 73d65cb7d3e8e1274913a3f604e081c0fab93f6d Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 4 Mar 2024 05:16:19 +0700 Subject: [PATCH 22/80] improve transformer performance --- src/Global.ts | 3 ++ src/Node.ts | 5 ++- src/Stage.ts | 8 ++-- src/shapes/Transformer.ts | 8 +++- test/unit/Transformer-test.ts | 78 +++++++++++++++++++---------------- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/src/Global.ts b/src/Global.ts index e68715df0..48e5f6865 100644 --- a/src/Global.ts +++ b/src/Global.ts @@ -155,6 +155,9 @@ export const Konva = { isDragging() { return Konva['DD'].isDragging; }, + isTransforming() { + return Konva['Transformer']?.isTransforming(); + }, /** * returns whether or not a drag and drop operation is ready, but may * not necessarily have started diff --git a/src/Node.ts b/src/Node.ts index 1cf0c38d9..281601c74 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -1029,7 +1029,10 @@ export abstract class Node { } }); - var dragSkip = !skipDragCheck && !Konva.hitOnDragEnabled && layerUnderDrag; + var dragSkip = + !skipDragCheck && + !Konva.hitOnDragEnabled && + (layerUnderDrag || Konva.isTransforming()); return this.isListening() && this.isVisible() && !dragSkip; } diff --git a/src/Stage.ts b/src/Stage.ts index 4740d796e..6b4d8b264 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -507,7 +507,8 @@ export class Stage extends Container { this.setPointersPositions(evt); var targetShape = this._getTargetShape(eventType); - var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled; + var eventsEnabled = + !(Konva.isDragging() || Konva.isTransforming()) || Konva.hitOnDragEnabled; if (targetShape && eventsEnabled) { targetShape._fireAndBubble(events.pointerout, { evt: evt }); targetShape._fireAndBubble(events.pointerleave, { evt: evt }); @@ -590,12 +591,13 @@ export class Stage extends Container { if (!events) { return; } - if (DD.isDragging && DD.node!.preventDefault() && evt.cancelable) { + if (Konva.isDragging() && DD.node!.preventDefault() && evt.cancelable) { evt.preventDefault(); } this.setPointersPositions(evt); - var eventsEnabled = !DD.isDragging || Konva.hitOnDragEnabled; + var eventsEnabled = + !(Konva.isDragging() || Konva.isTransforming()) || Konva.hitOnDragEnabled; if (!eventsEnabled) { return; } diff --git a/src/shapes/Transformer.ts b/src/shapes/Transformer.ts index 3585326cd..0c9796204 100644 --- a/src/shapes/Transformer.ts +++ b/src/shapes/Transformer.ts @@ -203,6 +203,7 @@ function getSnap(snaps: Array, newRotationRad: number, tol: number) { return snapped; } +let activeTransformersCount = 0; /** * Transformer constructor. Transformer is a special type of group that allow you transform Konva * primitives and shapes. Transforming tool is not changing `width` and `height` properties of nodes @@ -244,7 +245,6 @@ function getSnap(snaps: Array, newRotationRad: number, tol: number) { * }); * layer.add(transformer); */ - export class Transformer extends Group { _nodes: Array; _movingAnchorName: string | null = null; @@ -254,6 +254,10 @@ export class Transformer extends Group { cos: number; _cursorChange: boolean; + static isTransforming = () => { + return activeTransformersCount > 0; + }; + constructor(config?: TransformerConfig) { // call super constructor super(config); @@ -690,6 +694,7 @@ export class Transformer extends Group { x: pos.x - ap.x, y: pos.y - ap.y, }; + activeTransformersCount++; this._fire('transformstart', { evt: e.evt, target: this.getNode() }); this._nodes.forEach((target) => { target._fire('transformstart', { evt: e.evt, target }); @@ -955,6 +960,7 @@ export class Transformer extends Group { window.removeEventListener('touchend', this._handleMouseUp, true); } var node = this.getNode(); + activeTransformersCount--; this._fire('transformend', { evt: e, target: node }); if (node) { diff --git a/test/unit/Transformer-test.ts b/test/unit/Transformer-test.ts index 4d1ef8293..af3321a90 100644 --- a/test/unit/Transformer-test.ts +++ b/test/unit/Transformer-test.ts @@ -4967,40 +4967,46 @@ describe('Transformer', function () { simulateMouseUp(tr, { x: 110, y: 2 }); }); - // it('skip render on hit graph while transforming', function () { - // var stage = addStage(); - // var layer = new Konva.Layer(); - // stage.add(layer); - - // var rect = new Konva.Rect({ - // x: 55, - // y: 55, - // draggable: true, - // width: 100, - // height: 100, - // fill: 'yellow', - // }); - // layer.add(rect); - - // var tr = new Konva.Transformer({ - // nodes: [rect], - // }); - // layer.add(tr); - // layer.draw(); - - // simulateMouseDown(tr, { - // x: 100, - // y: 2, - // }); - // simulateMouseMove(tr, { - // x: 110, - // y: 2, - // }); - // const shape = layer.getIntersection({ - // x: 100, - // y: 100, - // }); - // assert.equal(shape, null); - // simulateMouseUp(tr, { x: 110, y: 2 }); - // }); + it('skip render on hit graph while transforming', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + var rect = new Konva.Rect({ + x: 55, + y: 55, + draggable: true, + width: 100, + height: 100, + fill: 'yellow', + }); + layer.add(rect); + + var tr = new Konva.Transformer({ + nodes: [rect], + }); + layer.add(tr); + layer.draw(); + + simulateMouseDown(tr, { + x: 100, + y: 2, + }); + simulateMouseMove(tr, { + x: 110, + y: 2, + }); + let shape = layer.getIntersection({ + x: 100, + y: 100, + }); + assert.equal(shape, null); + simulateMouseUp(tr, { x: 110, y: 2 }); + layer.draw(); + shape = layer.getIntersection({ + x: 100, + y: 100, + }); + assert.equal(shape, rect); + }); }); From ab224d5b85958cb4871432ea086ecdfe0ccc0ea2 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 4 Mar 2024 05:18:38 +0700 Subject: [PATCH 23/80] update CHANGELOG with new version --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b132d728..af9ea6e3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.5 (2024-03-04) + +- `tranformer` event will be triggered AFTER all data of transformer is updated +- Improve performance of transformer + ### 9.3.4 (2024-03-03) - Fix clipping with zero size From b0b8347810ee6ae4338736a6f0ab907d908419a7 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 4 Mar 2024 05:18:52 +0700 Subject: [PATCH 24/80] build for 9.3.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 85f0f0ba0..9c7ee251c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.4", + "version": "9.3.5", "author": "Anton Lavrenov", "files": [ "README.md", From 613493eb210b7261ddf44d57a3d95516147f1820 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 4 Mar 2024 05:18:52 +0700 Subject: [PATCH 25/80] update cdn link From 4f29c6d365fe1030a66369f8986599bf3a9eb91e Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 7 Mar 2024 06:53:45 +0700 Subject: [PATCH 26/80] fix trasnformer bug --- src/Layer.ts | 5 ++- src/shapes/Transformer.ts | 4 ++ test/unit/Transformer-test.ts | 81 ++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/Layer.ts b/src/Layer.ts index 5a0871b10..9766ec213 100644 --- a/src/Layer.ts +++ b/src/Layer.ts @@ -469,7 +469,10 @@ export class Layer extends Container { } destroy(): this { - Util.releaseCanvas(this.getNativeCanvasElement(), this.getHitCanvas()._canvas); + Util.releaseCanvas( + this.getNativeCanvasElement(), + this.getHitCanvas()._canvas + ); return super.destroy(); } diff --git a/src/shapes/Transformer.ts b/src/shapes/Transformer.ts index 0c9796204..6cec4a831 100644 --- a/src/shapes/Transformer.ts +++ b/src/shapes/Transformer.ts @@ -962,10 +962,14 @@ export class Transformer extends Group { var node = this.getNode(); activeTransformersCount--; this._fire('transformend', { evt: e, target: node }); + // redraw layer to restore hit graph + this.getLayer()?.batchDraw(); if (node) { this._nodes.forEach((target) => { target._fire('transformend', { evt: e, target }); + // redraw layer to restore hit graph + target.getLayer()?.batchDraw(); }); } this._movingAnchorName = null; diff --git a/test/unit/Transformer-test.ts b/test/unit/Transformer-test.ts index af3321a90..af6782df1 100644 --- a/test/unit/Transformer-test.ts +++ b/test/unit/Transformer-test.ts @@ -4967,7 +4967,7 @@ describe('Transformer', function () { simulateMouseUp(tr, { x: 110, y: 2 }); }); - it('skip render on hit graph while transforming', function () { + it('skip render on hit graph while transforming', function (done) { var stage = addStage(); var layer = new Konva.Layer(); stage.add(layer); @@ -5008,5 +5008,84 @@ describe('Transformer', function () { y: 100, }); assert.equal(shape, rect); + // reset position + rect.setAttrs({ + x: 50, + y: 50, + draggable: true, + width: 100, + height: 100, + }); + + tr.nodes([rect]); + layer.draw(); + // now check if graph is visible back when we moved a bit + simulateMouseDown(tr, { + x: 100, + y: 2, + }); + simulateMouseMove(tr, { + x: 110, + y: 2, + }); + setTimeout(() => { + shape = layer.getIntersection({ + x: 100, + y: 100, + }); + assert.equal(shape, null); + simulateMouseUp(tr, { x: 110, y: 2 }); + setTimeout(() => { + shape = layer.getIntersection({ + x: 100, + y: 100, + }); + assert.equal(shape, rect); + done(); + }, 100); + }, 100); + }); + + it('enable hit graph back on transformer destroy', function (done) { + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + var rect = new Konva.Rect({ + x: 55, + y: 55, + draggable: true, + width: 100, + height: 100, + fill: 'yellow', + }); + layer.add(rect); + + var tr = new Konva.Transformer({ + nodes: [rect], + }); + layer.add(tr); + layer.draw(); + + // now check if graph is visible back when we moved a bit + simulateMouseDown(tr, { + x: 100, + y: 2, + }); + simulateMouseMove(tr, { + x: 110, + y: 2, + }); + setTimeout(() => { + tr.destroy(); + setTimeout(() => { + var shape = layer.getIntersection({ + x: 100, + y: 100, + }); + assert.equal(shape, rect); + done(); + }, 100); + }, 100); }); }); From ef8710fd4823c3b94581a86a92ef19b6f8b65bc1 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 7 Mar 2024 06:54:29 +0700 Subject: [PATCH 27/80] note --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af9ea6e3c..80c8b1200 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.6 (2024-03-04) + +- Fix transformer bug to enable hit graph back + ### 9.3.5 (2024-03-04) - `tranformer` event will be triggered AFTER all data of transformer is updated From 7f607b1b7e32b0505e2115819afab1c7d6ead64d Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 7 Mar 2024 06:54:58 +0700 Subject: [PATCH 28/80] update CHANGELOG with new version From 03ad744ab7d1312e8574ebd5dde207f1338712fd Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 7 Mar 2024 06:55:12 +0700 Subject: [PATCH 29/80] build for 9.3.6 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c7ee251c..b25b9f5eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.5", + "version": "9.3.6", "author": "Anton Lavrenov", "files": [ "README.md", From 6d34326084bba32704da676e39621e2574942cc1 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 7 Mar 2024 06:55:13 +0700 Subject: [PATCH 30/80] update cdn link From 70f57d2a95de438fcc367b60b53cfe1708e88c3e Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 13:45:07 -0500 Subject: [PATCH 31/80] ignore node_modules in ts --- tsconfig.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index a9c5df04c..da4622615 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,9 +14,11 @@ "noImplicitAny": false, "noImplicitThis": false, "useUnknownInCatchVariables": false, + "skipLibCheck": true, // probably we would never enable this one // because it's too strict, konva generates many functions on the runtime "strictPropertyInitialization": false, + }, - "include": ["./src/**/*.ts"] + "include": ["./src/**/*.ts"], } From 88861b3ec62bae413bb6a0b09cf366ce85c19aa1 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 14:10:24 -0500 Subject: [PATCH 32/80] fix click event flow a little. close #1755 --- src/Stage.ts | 1 + test/unit/MouseEvents-test.ts | 63 +++++++++++++++++++++++++++++++++++ test/unit/TouchEvents-test.ts | 6 ++-- 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/Stage.ts b/src/Stage.ts index 6b4d8b264..48bbeb14d 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -551,6 +551,7 @@ export class Stage extends Container { // no shape detected? do nothing if (!shape || !shape.isListening()) { + this[eventType + 'ClickStartShape'] = undefined; return; } diff --git a/test/unit/MouseEvents-test.ts b/test/unit/MouseEvents-test.ts index ecc978a87..ed08d1441 100644 --- a/test/unit/MouseEvents-test.ts +++ b/test/unit/MouseEvents-test.ts @@ -2377,4 +2377,67 @@ describe('MouseEvents', function () { }); assert.deepEqual(stage.getPointerPosition(), { x: 60, y: 60 }); }); + + it('mousedown on empty then mouseup on shape', function () { + if (isNode) { + return; + } + var stage = addStage(); + var layer = new Konva.Layer(); + stage.add(layer); + + stage.on('mousedown mousemove mouseup click', function (e) { + console.log('state', e.type); + }); + + var rect = new Konva.Rect({ + width: 50, + height: 50, + fill: 'red', + draggable: true, + }); + layer.add(rect); + + layer.draw(); + + var clicks = 0; + rect.on('click', function () { + console.log('click'); + clicks += 1; + if (clicks === 2) { + debugger; + } + }); + + simulateMouseDown(stage, { + x: 40, + y: 40, + }); + + simulateMouseUp(stage, { + x: 40, + y: 40, + }); + + // trigger click + assert.equal(clicks, 1, 'clicks not triggered'); + + // mousedown outside + simulateMouseDown(stage, { + x: 60, + y: 6, + }); + // move into rect + simulateMouseMove(stage, { + x: 40, + y: 40, + }); + // mouseup inside rect + simulateMouseUp(stage, { + x: 40, + y: 40, + }); + // it shouldn't trigger the click event!!! + assert.equal(clicks, 1, 'clicks not triggered'); + }); }); diff --git a/test/unit/TouchEvents-test.ts b/test/unit/TouchEvents-test.ts index f79449994..5d8fa7701 100644 --- a/test/unit/TouchEvents-test.ts +++ b/test/unit/TouchEvents-test.ts @@ -460,11 +460,11 @@ describe('TouchEvents', function () { ); assert.equal(touchEnd, 1); assert.equal(stageTouchEnd, 1); - assert.equal(stageTap, 2, 'one tap should be fired'); + assert.equal(stageTap, 1, 'one tap should be fired'); assert.equal( stageEventStack.join(' '), - 'touchstart touchstart touchstart touchend tap tap', + 'touchstart touchstart touchstart touchend tap', 'should fire tap after touchend' ); @@ -481,7 +481,7 @@ describe('TouchEvents', function () { assert.equal(touchEnd, 2); assert.equal(touchEnd2, 1); assert.equal(stageTouchEnd, 3); - assert.equal(stageTap, 2, 'still one tap should be fired'); + assert.equal(stageTap, 1, 'still one tap should be fired'); // Don't need to check event stack here, the pointers moved so no tap is fired }); From fdd0e64aad9c0168d97ba8106231df146e71d55e Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 15:36:03 -0500 Subject: [PATCH 33/80] add failing test --- test/unit/DragAndDropEvents-test.ts | 59 +++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/test/unit/DragAndDropEvents-test.ts b/test/unit/DragAndDropEvents-test.ts index 8219e7d1c..2eb0474d6 100644 --- a/test/unit/DragAndDropEvents-test.ts +++ b/test/unit/DragAndDropEvents-test.ts @@ -6,6 +6,9 @@ import { simulateMouseDown, simulateMouseMove, simulateMouseUp, + simulatePointerDown, + simulatePointerMove, + simulatePointerUp, } from './test-utils'; describe('DragAndDropEvents', function () { @@ -219,10 +222,6 @@ describe('DragAndDropEvents', function () { clicked = true; }); - circle.on('dblclick', function () { - //console.log('dblclick'); - }); - simulateMouseDown(stage, { x: 40, y: 40, @@ -245,6 +244,58 @@ describe('DragAndDropEvents', function () { }, 20); }); + // TODO: how to solve it? + // hint: every shape has pointerId that indicates which pointer is dragging it + // but "pointer" event and mouse event has different pointerId + // so we need to find a way to match them + // should we save several pointers per shape? + // doesn't sound good + // switch to pointer only event handling? + it.skip('click should not occur after drag and drop', function (done) { + var stage = addStage(); + var layer = new Konva.Layer(); + + var circle = new Konva.Circle({ + x: 40, + y: 40, + radius: 20, + strokeWidth: 4, + fill: 'green', + stroke: 'black', + draggable: true, + }); + + layer.add(circle); + stage.add(layer); + + var clicked = false; + + stage.on('pointerclick', function () { + clicked = true; + }); + + simulatePointerDown(stage, { + x: 40, + y: 40, + }); + + setTimeout(function () { + simulatePointerMove(stage, { + x: 100, + y: 100, + }); + + simulatePointerUp(stage, { + x: 100, + y: 100, + }); + + assert(!clicked, 'click event should not have been fired'); + + done(); + }, 20); + }); + // ====================================================== it('drag and drop distance', function (done) { var stage = addStage(); From 0ec3425d991954438727c778ce6aa39be741d02c Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 20:35:26 -0500 Subject: [PATCH 34/80] possible fix for all our text problems --- src/shapes/Text.ts | 30 ++++++++++++++--- test/sandbox.html | 81 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 81 insertions(+), 30 deletions(-) diff --git a/src/shapes/Text.ts b/src/shapes/Text.ts index 20eefa7e4..1ecdedb5e 100644 --- a/src/shapes/Text.ts +++ b/src/shapes/Text.ts @@ -201,11 +201,18 @@ export class Text extends Shape { shouldUnderline = textDecoration.indexOf('underline') !== -1, shouldLineThrough = textDecoration.indexOf('line-through') !== -1, n; - + direction = direction === INHERIT ? context.direction : direction; - var translateY = 0; var translateY = lineHeightPx / 2; + const baseline = this.textBaseline(); + if (baseline === 'alphabetic') { + var metrics = this.measureSize('M'); // Use a sample character to get the ascent + + translateY = + (metrics.fontBoundingBoxAscent - metrics.fontBoundingBoxDescent) / 2 + + lineHeightPx / 2; + } var lineTranslateX = 0; var lineTranslateY = 0; @@ -216,11 +223,10 @@ export class Text extends Shape { context.setAttr('font', this._getContextFont()); - context.setAttr('textBaseline', MIDDLE); + context.setAttr('textBaseline', baseline); context.setAttr('textAlign', LEFT); - // handle vertical alignment if (verticalAlign === MIDDLE) { alignY = (this.getHeight() - textArrLen * lineHeightPx - padding * 2) / 2; @@ -399,6 +405,18 @@ export class Text extends Shape { metrics = _context.measureText(text); _context.restore(); return { + // copy all text metrics data: + actualBoundingBoxAscent: metrics.actualBoundingBoxAscent, + actualBoundingBoxDescent: metrics.actualBoundingBoxDescent, + actualBoundingBoxLeft: metrics.actualBoundingBoxLeft, + actualBoundingBoxRight: metrics.actualBoundingBoxRight, + alphabeticBaseline: metrics.alphabeticBaseline, + emHeightAscent: metrics.emHeightAscent, + emHeightDescent: metrics.emHeightDescent, + fontBoundingBoxAscent: metrics.fontBoundingBoxAscent, + fontBoundingBoxDescent: metrics.fontBoundingBoxDescent, + hangingBaseline: metrics.hangingBaseline, + ideographicBaseline: metrics.ideographicBaseline, width: metrics.width, height: fontSize, }; @@ -637,6 +655,7 @@ export class Text extends Shape { direction: GetSet; fontFamily: GetSet; + textBaseline: GetSet; fontSize: GetSet; fontStyle: GetSet; fontVariant: GetSet; @@ -703,7 +722,6 @@ Factory.overWriteSetter(Text, 'width', getNumberOrAutoValidator()); Factory.overWriteSetter(Text, 'height', getNumberOrAutoValidator()); - /** * get/set direction * @name Konva.Text#direction @@ -734,6 +752,8 @@ Factory.addGetterSetter(Text, 'direction', INHERIT); */ Factory.addGetterSetter(Text, 'fontFamily', 'Arial'); +Factory.addGetterSetter(Text, 'textBaseline', MIDDLE); + /** * get/set font size in pixels * @name Konva.Text#fontSize diff --git a/test/sandbox.html b/test/sandbox.html index 674c2c187..db4dda12d 100644 --- a/test/sandbox.html +++ b/test/sandbox.html @@ -30,46 +30,77 @@ From 8f2e9f8793ffd7e3cf0ca98680d35c422fa5b687 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 20:36:00 -0500 Subject: [PATCH 35/80] update CHANGELOG with new version From 5143154d97ccdbff2e8c45163209316d71085525 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 20:36:12 -0500 Subject: [PATCH 36/80] build for 9.3.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b25b9f5eb..91702deae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.6", + "version": "9.3.7", "author": "Anton Lavrenov", "files": [ "README.md", From 2587e0708fbfefb8a902db02c3da700f105c3557 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 20:36:12 -0500 Subject: [PATCH 37/80] update cdn link From 7d5ba3e42973962258e3895700125b971db4702d Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 15 May 2024 21:10:03 -0500 Subject: [PATCH 38/80] rename fix apply --- src/Global.ts | 1 + src/shapes/Text.ts | 8 +++----- test/sandbox.html | 2 ++ 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Global.ts b/src/Global.ts index 48e5f6865..9996e3981 100644 --- a/src/Global.ts +++ b/src/Global.ts @@ -90,6 +90,7 @@ export const Konva = { _mouseDblClickPointerId: null, _touchDblClickPointerId: null, _pointerDblClickPointerId: null, + _fixTextRendering: false, /** * Global pixel ratio configuration. KonvaJS automatically detect pixel ratio of current device. diff --git a/src/shapes/Text.ts b/src/shapes/Text.ts index 1ecdedb5e..4703fd333 100644 --- a/src/shapes/Text.ts +++ b/src/shapes/Text.ts @@ -205,10 +205,11 @@ export class Text extends Shape { direction = direction === INHERIT ? context.direction : direction; var translateY = lineHeightPx / 2; - const baseline = this.textBaseline(); - if (baseline === 'alphabetic') { + var baseline = MIDDLE; + if (Konva._fixTextRendering) { var metrics = this.measureSize('M'); // Use a sample character to get the ascent + baseline = 'alphabetic'; translateY = (metrics.fontBoundingBoxAscent - metrics.fontBoundingBoxDescent) / 2 + lineHeightPx / 2; @@ -655,7 +656,6 @@ export class Text extends Shape { direction: GetSet; fontFamily: GetSet; - textBaseline: GetSet; fontSize: GetSet; fontStyle: GetSet; fontVariant: GetSet; @@ -752,8 +752,6 @@ Factory.addGetterSetter(Text, 'direction', INHERIT); */ Factory.addGetterSetter(Text, 'fontFamily', 'Arial'); -Factory.addGetterSetter(Text, 'textBaseline', MIDDLE); - /** * get/set font size in pixels * @name Konva.Text#fontSize diff --git a/test/sandbox.html b/test/sandbox.html index db4dda12d..6bdd52560 100644 --- a/test/sandbox.html +++ b/test/sandbox.html @@ -30,6 +30,8 @@ From 60aefdfeaafa27f412e306d4dfc880c32fdab89c Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 20 May 2024 19:25:09 -0500 Subject: [PATCH 44/80] changes --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b060619ed..3a35e8332 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -### 9.3.8 (2024-03-04) +### 9.3.9 (2024-05-20) + +- Fix underline and line-through for `Konva.Text` when `Konva._fixTextRendering = true` + +### 9.3.8 (2024-05-15) - Fix click events fires on stage - Temporary `Konva._fixTextRendering = true` flag to fix inconsistent text From bbf945b219f7ab6d1301429ac5af870e68567a63 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 20 May 2024 19:25:25 -0500 Subject: [PATCH 45/80] update CHANGELOG with new version From e2009f58ff51ed50616bac00c5fb588eecef0b28 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 20 May 2024 19:25:36 -0500 Subject: [PATCH 46/80] build for 9.3.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ddbfc153..ca6c1e8ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.8", + "version": "9.3.9", "author": "Anton Lavrenov", "files": [ "README.md", From e30a16cb3601c0590777b987d81faa708a65a9f9 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 20 May 2024 19:25:36 -0500 Subject: [PATCH 47/80] update cdn link From a5cd67261f7354bb971d0017f34e4986af64cab3 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:20:00 -0500 Subject: [PATCH 48/80] update CHANGELOG with new version --- CHANGELOG.md | 5 +++++ src/Stage.ts | 12 ++++++++++++ src/shapes/Transformer.ts | 2 +- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a35e8332..a592f32a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,11 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.10 (2024-05-23) + +- Fix chrome clear canvas issue +- Typescript fixes + ### 9.3.9 (2024-05-20) - Fix underline and line-through for `Konva.Text` when `Konva._fixTextRendering = true` diff --git a/src/Stage.ts b/src/Stage.ts index 48bbeb14d..d06cb19a7 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -965,3 +965,15 @@ _registerNode(Stage); * stage.container(container); */ Factory.addGetterSetter(Stage, 'container'); + +// chrome is clearing canvas in inactive browser window, causing layer content to be erased +// so let's redraw layers as soon as window becomes active +// TODO: any other way to solve this issue? +// TODO: should we remove it if chrome fixes the issue? +if (Konva.isBrowser) { + window.addEventListener('focus', () => { + stages.forEach((stage) => { + stage.batchDraw(); + }); + }); +} diff --git a/src/shapes/Transformer.ts b/src/shapes/Transformer.ts index 6cec4a831..b96d94338 100644 --- a/src/shapes/Transformer.ts +++ b/src/shapes/Transformer.ts @@ -47,7 +47,7 @@ export interface TransformerConfig extends ContainerConfig { newPos: Vector2d, evt: any ) => Vector2d; - anchorStyleFunc?: (anchor: Shape) => void; + anchorStyleFunc?: (anchor: Rect) => void; } var EVENTS_NAME = 'tr-konva'; From f2a37285fc2f2383e06e5ec175a04f5fc8501bed Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:20:11 -0500 Subject: [PATCH 49/80] build for 9.3.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ca6c1e8ee..30f21838a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.9", + "version": "9.3.10", "author": "Anton Lavrenov", "files": [ "README.md", From 9083dfbbe7e51d55e972d964395d9590aeabb523 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:20:11 -0500 Subject: [PATCH 50/80] update cdn link From f0a7924949ce347545e7ca8790a6de25d46219b3 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:40:59 -0500 Subject: [PATCH 51/80] try to fix again --- CHANGELOG.md | 2 +- src/Stage.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a592f32a8..3373e292b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). -### 9.3.10 (2024-05-23) +### 9.3.11 (2024-05-23) - Fix chrome clear canvas issue - Typescript fixes diff --git a/src/Stage.ts b/src/Stage.ts index d06cb19a7..4fe8a567f 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -971,7 +971,7 @@ Factory.addGetterSetter(Stage, 'container'); // TODO: any other way to solve this issue? // TODO: should we remove it if chrome fixes the issue? if (Konva.isBrowser) { - window.addEventListener('focus', () => { + document.addEventListener('visibilitychange', () => { stages.forEach((stage) => { stage.batchDraw(); }); From 10487e99e495408b4536d438a2b439f46d3a9afa Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:41:22 -0500 Subject: [PATCH 52/80] update CHANGELOG with new version From ad01e860d93eb6ae1243cefb9bc252d1d4248426 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:41:37 -0500 Subject: [PATCH 53/80] build for 9.3.11 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30f21838a..160b1eda7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.10", + "version": "9.3.11", "author": "Anton Lavrenov", "files": [ "README.md", From 68b4ea3cb65f7ebd838f7e420958d26b59088f0f Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 23 May 2024 12:41:37 -0500 Subject: [PATCH 54/80] update cdn link From b54f3888e3a4ca7d46ee825e08ec3912070f7f26 Mon Sep 17 00:00:00 2001 From: Tac Tacelosky Date: Thu, 30 May 2024 13:40:04 -0600 Subject: [PATCH 55/80] add link to konva-dev This extension is invaluable for debugging. --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index f60a2363d..48eb3c938 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,10 @@ Konva works in all modern mobile and desktop browsers. A browser need to be capa At the current moment `Konva` doesn't work in IE11 directly. To make it work you just need to provide some polyfills such as `Array.prototype.find`, `String.prototype.trimLeft`, `String.prototype.trimRight`, `Array.from`. +# Debugging + +The Chrome inspector simply shows the canvas element. To see the Konva objects and their details, install the konva-dev extension at https://github.com/konvajs/konva-devtool. + # Loading and installing Konva Konva supports UMD loading. So you can use all possible variants to load the framework into your project: From 01f4bb605e1cee8c68cbfc1474c5b920a6a9c33b Mon Sep 17 00:00:00 2001 From: Elazar Kopyrin Date: Mon, 3 Jun 2024 20:20:05 +0300 Subject: [PATCH 56/80] Update `fill` type to accpet `CanvasGradient` --- src/Shape.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Shape.ts b/src/Shape.ts index 6f403878c..8d5a27ffb 100644 --- a/src/Shape.ts +++ b/src/Shape.ts @@ -26,7 +26,7 @@ export type LineJoin = 'round' | 'bevel' | 'miter'; export type LineCap = 'butt' | 'round' | 'square'; export interface ShapeConfig extends NodeConfig { - fill?: string; + fill?: string | CanvasGradient; fillPatternImage?: HTMLImageElement; fillPatternX?: number; fillPatternY?: number; From 52977b5c0c98007ee890555ed58aaa8f9f47cc5a Mon Sep 17 00:00:00 2001 From: Elazar Kopyrin Date: Mon, 3 Jun 2024 22:18:08 +0300 Subject: [PATCH 57/80] Update `fill` and `stroke` GetSet type to accept `CanvasGradient` --- src/Shape.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Shape.ts b/src/Shape.ts index 8d5a27ffb..de9ef0708 100644 --- a/src/Shape.ts +++ b/src/Shape.ts @@ -766,7 +766,7 @@ export class Shape< dash: GetSet; dashEnabled: GetSet; dashOffset: GetSet; - fill: GetSet; + fill: GetSet; fillEnabled: GetSet; fillLinearGradientColorStops: GetSet, this>; fillLinearGradientStartPoint: GetSet; @@ -815,7 +815,7 @@ export class Shape< shadowOffsetY: GetSet; shadowOpacity: GetSet; shadowBlur: GetSet; - stroke: GetSet; + stroke: GetSet; strokeEnabled: GetSet; fillAfterStrokeEnabled: GetSet; strokeScaleEnabled: GetSet; From d95ff799644a43fd734609a8f106e28afc402195 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 12 Jun 2024 12:21:10 -0500 Subject: [PATCH 58/80] fix shape.getClientRect() when a parent is cached, fix #1759` --- CHANGELOG.md | 2 ++ src/Shape.ts | 15 ++++++++++++++- test/unit/Shape-test.ts | 29 +++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3373e292b..7ece64959 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +- Fix `shape.getClientRect()` when any of parents is cached + ### 9.3.11 (2024-05-23) - Fix chrome clear canvas issue diff --git a/src/Shape.ts b/src/Shape.ts index 6f403878c..e85aa8df6 100644 --- a/src/Shape.ts +++ b/src/Shape.ts @@ -528,9 +528,22 @@ export class Shape< }; } getClientRect(config: ShapeGetClientRectConfig = {}) { + // if we have a cached parent, it will use cached transform matrix + // but we don't want to that + let hasCachedParent = false; + let parent = this.getParent(); + while (parent) { + if (parent.isCached()) { + hasCachedParent = true; + break; + } + parent = parent.getParent(); + } const skipTransform = config.skipTransform; - const relativeTo = config.relativeTo; + // force relative to stage if we have a cached parent + const relativeTo = + config.relativeTo || (hasCachedParent && this.getStage()) || undefined; const fillRect = this.getSelfRect(); diff --git a/test/unit/Shape-test.ts b/test/unit/Shape-test.ts index 8f023462b..79d2e2d64 100644 --- a/test/unit/Shape-test.ts +++ b/test/unit/Shape-test.ts @@ -1653,6 +1653,35 @@ describe('Shape', function () { assert.equal(rect.height, 100, 'should not effect width'); }); + it('getClientRect should not use cached values', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + + var shape = new Konva.Rect({ + x: 100, + y: 100, + width: 100, + height: 100, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + strokeEnabled: false, + shadowOffsetX: 10, + shadowEnabled: false, + }); + + layer.add(shape); + stage.add(layer); + + layer.cache(); + + layer.scaleX(2); + + const rect = shape.getClientRect(); + + assert.equal(rect.x, 200); + }); + it('getClientRect for shape in transformed parent', function () { var stage = addStage(); var layer = new Konva.Layer(); From 8be222e80ec3cb85cea35344b6d41cf2fd00b6bd Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Wed, 12 Jun 2024 16:12:20 -0500 Subject: [PATCH 59/80] Fix svg `path.getPointAtLength()`. fix #1766 --- CHANGELOG.md | 1 + src/shapes/Path.ts | 75 +++++++++++++++--------------------------- test/unit/Path-test.ts | 58 ++++++++++++++++++++++++++++---- 3 files changed, 78 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ece64959..0913d35e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +- Fix svg `path.getPointAtLength()` calculations in some cases - Fix `shape.getClientRect()` when any of parents is cached ### 9.3.11 (2024-05-23) diff --git a/src/shapes/Path.ts b/src/shapes/Path.ts index 1c8e08410..e91f54005 100644 --- a/src/shapes/Path.ts +++ b/src/shapes/Path.ts @@ -320,61 +320,38 @@ export class Path extends Shape { } static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) { - if (fromX === undefined) { - fromX = P1x; - } - if (fromY === undefined) { - fromY = P1y; - } + fromX = fromX ?? P1x; + fromY = fromY ?? P1y; - var m = (P2y - P1y) / (P2x - P1x + 0.00000001); - var run = Math.sqrt((dist * dist) / (1 + m * m)); - if (P2x < P1x) { - run *= -1; + const len = this.getLineLength(P1x, P1y, P2x, P2y); + if (len < 1e-10) { + return { x: P1x, y: P1y }; } - var rise = m * run; - var pt; if (P2x === P1x) { - // vertical line - pt = { - x: fromX, - y: fromY + rise, - }; - } else if ((fromY - P1y) / (fromX - P1x + 0.00000001) === m) { - pt = { - x: fromX + run, - y: fromY + rise, - }; - } else { - var ix, iy; - - var len = this.getLineLength(P1x, P1y, P2x, P2y); - // if (len < 0.00000001) { - // return { - // x: P1x, - // y: P1y, - // }; - // } - var u = (fromX - P1x) * (P2x - P1x) + (fromY - P1y) * (P2y - P1y); - u = u / (len * len); - ix = P1x + u * (P2x - P1x); - iy = P1y + u * (P2y - P1y); - - var pRise = this.getLineLength(fromX, fromY, ix, iy); - var pRun = Math.sqrt(dist * dist - pRise * pRise); - run = Math.sqrt((pRun * pRun) / (1 + m * m)); - if (P2x < P1x) { - run *= -1; - } - rise = m * run; - pt = { - x: ix + run, - y: iy + rise, - }; + // Vertical line + return { x: fromX, y: fromY + (P2y > P1y ? dist : -dist) }; + } + + const m = (P2y - P1y) / (P2x - P1x); + const run = Math.sqrt((dist * dist) / (1 + m * m)) * (P2x < P1x ? -1 : 1); + const rise = m * run; + + if (Math.abs(fromY - P1y - m * (fromX - P1x)) < 1e-10) { + return { x: fromX + run, y: fromY + rise }; } - return pt; + const u = + ((fromX - P1x) * (P2x - P1x) + (fromY - P1y) * (P2y - P1y)) / (len * len); + const ix = P1x + u * (P2x - P1x); + const iy = P1y + u * (P2y - P1y); + const pRise = this.getLineLength(fromX, fromY, ix, iy); + const pRun = Math.sqrt(dist * dist - pRise * pRise); + const adjustedRun = + Math.sqrt((pRun * pRun) / (1 + m * m)) * (P2x < P1x ? -1 : 1); + const adjustedRise = m * adjustedRun; + + return { x: ix + adjustedRun, y: iy + adjustedRise }; } static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) { diff --git a/test/unit/Path-test.ts b/test/unit/Path-test.ts index e8cdff824..4b3501f67 100644 --- a/test/unit/Path-test.ts +++ b/test/unit/Path-test.ts @@ -1134,11 +1134,11 @@ describe('Path', function () { assert.deepEqual(points, [ { x: 300, y: 10 }, - { x: 290.2871413779118, y: 27.48314552325543 }, - { x: 280.57428275582356, y: 44.96629104651086 }, - { x: 270.86142413373534, y: 62.4494365697663 }, - { x: 261.1485655116471, y: 79.93258209302172 }, - { x: 251.43570688955887, y: 97.41572761627717 }, + { x: 290.28714137642737, y: 27.483145522430753 }, + { x: 280.57428275285474, y: 44.96629104486151 }, + { x: 270.86142412928206, y: 62.44943656729226 }, + { x: 261.1485655057094, y: 79.93258208972301 }, + { x: 251.4357068821368, y: 97.41572761215377 }, { x: 230.89220826660141, y: 87.23996356219386 }, { x: 207.0639321224534, y: 74.08466390481559 }, { x: 182.87529785963875, y: 63.52674972743341 }, @@ -1168,6 +1168,47 @@ describe('Path', function () { stage.add(layer); }); + it('get point at path with float attrs', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + + const data = + 'M419.0000314094981 342.88624187900973 L419.00003140949804 577.0038889378335 L465.014001082264 577.0038889378336 Z'; + var path = new Konva.Path({ + stroke: 'red', + strokeWidth: 3, + data, + }); + layer.add(path); + if (isBrowser) { + const SVGPath = document.createElementNS( + 'http://www.w3.org/2000/svg', + 'path' + ) as SVGPathElement; + SVGPath.setAttribute('d', data); + for (var i = 0; i < path.getLength(); i += 1) { + var p = path.getPointAtLength(i); + var circle = new Konva.Circle({ + x: p.x, + y: p.y, + radius: 2, + fill: 'black', + stroke: 'black', + }); + layer.add(circle); + const position = SVGPath.getPointAtLength(i); + assert( + Math.abs(p.x - position.x) <= 1, + 'error for x should be smaller than 10% for i = ' + i + ); + assert( + Math.abs(p.y - position.y) <= 1, + 'error for y should be smaller than 10% for i = ' + i + ); + } + } + }); + it('get point at path - bezier', function () { var stage = addStage(); var layer = new Konva.Layer(); @@ -1618,8 +1659,11 @@ describe('Path', function () { layer.add(path); stage.add(layer); - const trace = layer.getContext().getTrace() + const trace = layer.getContext().getTrace(); - assert.equal(trace, 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(200,100);lineTo(300,100);lineTo(300,150);closePath();fillStyle=#ccc;fill(evenodd);restore();'); + assert.equal( + trace, + 'clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();moveTo(200,100);lineTo(300,100);lineTo(300,150);closePath();fillStyle=#ccc;fill(evenodd);restore();' + ); }); }); From 83523ecc6f749217747803b75393b8a419766de8 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 20 Jun 2024 09:59:21 -0500 Subject: [PATCH 60/80] fix transform on double touch, fix #1767 --- src/shapes/Transformer.ts | 5 +++++ test/sandbox.html | 15 ++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/shapes/Transformer.ts b/src/shapes/Transformer.ts index b96d94338..859608875 100644 --- a/src/shapes/Transformer.ts +++ b/src/shapes/Transformer.ts @@ -670,6 +670,11 @@ export class Transformer extends Group { }); } _handleMouseDown(e) { + // do nothing if we already transforming + // that is possible to trigger with multitouch + if (this._transforming) { + return; + } this._movingAnchorName = e.target.name().split(' ')[0]; var attrs = this._getNodeRect(); diff --git a/test/sandbox.html b/test/sandbox.html index 0fc8756ad..a1d11e272 100644 --- a/test/sandbox.html +++ b/test/sandbox.html @@ -48,12 +48,25 @@ x: 10, y: 10, text: 'Simple Text', - fontSize: 300, + fontSize: 100, fontFamily: 'Calibri', fill: 'green', textDecoration: 'underline line-through', + draggable: true, }); layer.add(text); + + var tr = new Konva.Transformer({ + nodes: [text], + }); + layer.add(tr); + + tr.on('transformstart', () => { + console.log('transform start'); + }); + tr.on('transformend', () => { + console.log('transform end'); + }); From addbb98328366af898125d716956b155af030675 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 20 Jun 2024 10:00:27 -0500 Subject: [PATCH 61/80] update CHANGELOG with new version --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0913d35e2..619024a66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.12 (2024-06-20) + +- Fix stopped transforming when it was triggered by multi-touch - Fix svg `path.getPointAtLength()` calculations in some cases - Fix `shape.getClientRect()` when any of parents is cached From e86f2222532023250c769457478982437af5ffd2 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 20 Jun 2024 10:00:41 -0500 Subject: [PATCH 62/80] build for 9.3.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 160b1eda7..f228fd61c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.11", + "version": "9.3.12", "author": "Anton Lavrenov", "files": [ "README.md", From cb69ff92239af8c2bc1b106e01426d816120d066 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 20 Jun 2024 10:00:41 -0500 Subject: [PATCH 63/80] update cdn link From bb5275f9d14d2b6473a6bd78de92b722460e2694 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 5 Jul 2024 13:24:38 -0500 Subject: [PATCH 64/80] measureText fallback --- CHANGELOG.md | 4 ++++ src/shapes/Text.ts | 35 ++++++++++++++++++++++------------- test/unit/Text-test.ts | 27 ++++++++++++++++++++++----- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 619024a66..61fe3279f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,10 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.13 (2024-07-05) + +- Fallback for `Konva.Text.measureSize()` when 2d context doesn't return full data + ### 9.3.12 (2024-06-20) - Fix stopped transforming when it was triggered by multi-touch diff --git a/src/shapes/Text.ts b/src/shapes/Text.ts index d9dfb3218..07418fa0e 100644 --- a/src/shapes/Text.ts +++ b/src/shapes/Text.ts @@ -405,21 +405,30 @@ export class Text extends Shape { metrics = _context.measureText(text); _context.restore(); + + // Scale the fallback values based on the provided fontSize compared to the sample size (100 in your new case) + const scaleFactor = fontSize / 100; + + // Note, fallback values are from chrome browser with 100px font size and font-family "Arial" return { - // copy all text metrics data: - actualBoundingBoxAscent: metrics.actualBoundingBoxAscent, - actualBoundingBoxDescent: metrics.actualBoundingBoxDescent, - actualBoundingBoxLeft: metrics.actualBoundingBoxLeft, - actualBoundingBoxRight: metrics.actualBoundingBoxRight, - alphabeticBaseline: metrics.alphabeticBaseline, - emHeightAscent: metrics.emHeightAscent, - emHeightDescent: metrics.emHeightDescent, - fontBoundingBoxAscent: metrics.fontBoundingBoxAscent, - fontBoundingBoxDescent: metrics.fontBoundingBoxDescent, - hangingBaseline: metrics.hangingBaseline, - ideographicBaseline: metrics.ideographicBaseline, + actualBoundingBoxAscent: + metrics.actualBoundingBoxAscent ?? 71.58203125 * scaleFactor, + actualBoundingBoxDescent: metrics.actualBoundingBoxDescent ?? 0, // Remains zero as there is no descent in the provided metrics + actualBoundingBoxLeft: + metrics.actualBoundingBoxLeft ?? -7.421875 * scaleFactor, + actualBoundingBoxRight: + metrics.actualBoundingBoxRight ?? 75.732421875 * scaleFactor, + alphabeticBaseline: metrics.alphabeticBaseline ?? 0, // Remains zero as it's typically relative to the baseline itself + emHeightAscent: metrics.emHeightAscent ?? 100 * scaleFactor, + emHeightDescent: metrics.emHeightDescent ?? -20 * scaleFactor, + fontBoundingBoxAscent: metrics.fontBoundingBoxAscent ?? 91 * scaleFactor, + fontBoundingBoxDescent: + metrics.fontBoundingBoxDescent ?? 21 * scaleFactor, + hangingBaseline: + metrics.hangingBaseline ?? 72.80000305175781 * scaleFactor, + ideographicBaseline: metrics.ideographicBaseline ?? -21 * scaleFactor, width: metrics.width, - height: fontSize, + height: fontSize, // Typically set to the font size }; } _getContextFont() { diff --git a/test/unit/Text-test.ts b/test/unit/Text-test.ts index f8b127aa9..f95cb8046 100644 --- a/test/unit/Text-test.ts +++ b/test/unit/Text-test.ts @@ -1654,7 +1654,7 @@ describe('Text', function () { assert.equal(layer.getContext().getTrace(), trace); }); - + it('sets ltr text direction', function () { var stage = addStage(); var layer = new Konva.Layer(); @@ -1673,9 +1673,8 @@ describe('Text', function () { assert.equal(layer.getContext().getTrace(), trace); }); - - - it('sets rtl text direction', function () { + + it('sets rtl text direction', function () { var stage = addStage(); var layer = new Konva.Layer(); @@ -1693,7 +1692,7 @@ describe('Text', function () { assert.equal(layer.getContext().getTrace(), trace); }); - + it('sets rtl text direction with letterSpacing', function () { var stage = addStage(); var layer = new Konva.Layer(); @@ -1713,4 +1712,22 @@ describe('Text', function () { assert.equal(layer.getContext().getTrace(), trace); }); + + it('try fixed render', () => { + Konva._fixTextRendering = true; + var stage = addStage(); + var layer = new Konva.Layer(); + + stage.add(layer); + var text = new Konva.Text({ text: 'hello', fontSize: 100 }); + + layer.add(text); + layer.draw(); + Konva._fixTextRendering = false; + + const trace = + 'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);font=normal normal 100px Arial;textBaseline=alphabetic;textAlign=left;translate(0,0);save();fillStyle=black;fillText(hello,0,85);restore();restore();'; + + assert.equal(layer.getContext().getTrace(), trace); + }); }); From d9e6f11e42bc35b77472b606bf1610255f7808bd Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 5 Jul 2024 13:25:10 -0500 Subject: [PATCH 65/80] update CHANGELOG with new version From 5ac40635e4e6ab5c4fb42e3ef98b5b182062cded Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 5 Jul 2024 13:25:23 -0500 Subject: [PATCH 66/80] build for 9.3.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f228fd61c..59e4e9fd7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.12", + "version": "9.3.13", "author": "Anton Lavrenov", "files": [ "README.md", From 00997bc22587ec24cf24bec579afe4b8754e5be3 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Fri, 5 Jul 2024 13:25:23 -0500 Subject: [PATCH 67/80] update cdn link From ac1587fac8141665611fade44cc581b80a0804f1 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Mon, 15 Jul 2024 12:40:00 -0500 Subject: [PATCH 68/80] update docs, fix fullRule for hit graph, close #1787 --- CHANGELOG.md | 2 ++ src/Container.ts | 1 + src/Layer.ts | 1 + src/Node.ts | 2 ++ src/Shape.ts | 9 +++++++-- src/Stage.ts | 1 + test/unit/Shape-test.ts | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 46 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61fe3279f..c69223e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +- Support `fillRule` for `Konva.Shape` on hit graph + ### 9.3.13 (2024-07-05) - Fallback for `Konva.Text.measureSize()` when 2d context doesn't return full data diff --git a/src/Container.ts b/src/Container.ts index efd4c2f53..d7bb54940 100644 --- a/src/Container.ts +++ b/src/Container.ts @@ -307,6 +307,7 @@ export abstract class Container< * canvas and redraw every shape inside the container, it should only be used for special situations * because it performs very poorly. Please use the {@link Konva.Stage#getIntersection} method if at all possible * because it performs much better + * nodes with listening set to false will not be detected * @method * @name Konva.Container#getAllIntersections * @param {Object} pos diff --git a/src/Layer.ts b/src/Layer.ts index 9766ec213..4e5ff9612 100644 --- a/src/Layer.ts +++ b/src/Layer.ts @@ -309,6 +309,7 @@ export class Layer extends Container { * get visible intersection shape. This is the preferred * method for determining if a point intersects a shape or not * also you may pass optional selector parameter to return ancestor of intersected shape + * nodes with listening set to false will not be detected * @method * @name Konva.Layer#getIntersection * @param {Object} pos diff --git a/src/Node.ts b/src/Node.ts index 281601c74..a26ce37bb 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -3155,6 +3155,8 @@ addGetterSetter(Node, 'listening', true, getBooleanValidator()); /** * get/set listening attr. If you need to determine if a node is listening or not * by taking into account its parents, use the isListening() method + * nodes with listening set to false will not be detected in hit graph + * so they will be ignored in container.getIntersection() method * @name Konva.Node#listening * @method * @param {Boolean} listening Can be true, or false. The default is true. diff --git a/src/Shape.ts b/src/Shape.ts index 4d77de823..e34abbfd6 100644 --- a/src/Shape.ts +++ b/src/Shape.ts @@ -128,8 +128,13 @@ function _fillFunc(this: Node, context) { function _strokeFunc(context) { context.stroke(); } -function _fillFuncHit(context) { - context.fill(); +function _fillFuncHit(this: Node, context) { + const fillRule = this.attrs.fillRule; + if (fillRule) { + context.fill(fillRule); + } else { + context.fill(); + } } function _strokeFuncHit(context) { context.stroke(); diff --git a/src/Stage.ts b/src/Stage.ts index 4fe8a567f..b5ef16953 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -353,6 +353,7 @@ export class Stage extends Container { /** * get visible intersection shape. This is the preferred * method for determining if a point intersects a shape or not + * nodes with listening set to false will not be detected * @method * @name Konva.Stage#getIntersection * @param {Object} pos diff --git a/test/unit/Shape-test.ts b/test/unit/Shape-test.ts index 79d2e2d64..26758dda7 100644 --- a/test/unit/Shape-test.ts +++ b/test/unit/Shape-test.ts @@ -2303,4 +2303,36 @@ describe('Shape', function () { assert.equal(callCount, 0); Konva.Util.warn = oldWarn; }); + + it('fill rule on hit graph', function () { + var stage = addStage(); + + var layer = new Konva.Layer(); + stage.add(layer); + + var mask = new Konva.Shape({ + sceneFunc: function (ctx, shape) { + ctx.beginPath(); + ctx.rect(0, 0, 500, 500); + ctx.rect(100, 100, 100, 100); + ctx.closePath(); + ctx.fillShape(shape); + }, + draggable: true, + fill: 'red', + fillRule: 'evenodd', + }); + + layer.add(mask); + layer.draw(); + const trace = layer.getContext().getTrace(); + + assert.equal( + trace, + 'clearRect(0,0,578,200);clearRect(0,0,578,200);save();transform(1,0,0,1,0,0);beginPath();rect(0,0,500,500);rect(100,100,100,100);closePath();fillStyle=red;fill(evenodd);restore();' + ); + + const hitShape = layer.getIntersection({ x: 150, y: 150 }); + assert.equal(hitShape, null); + }); }); From 3f6f9f93651211e4f7ab2f9492cbb46dee09e00d Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Tue, 16 Jul 2024 20:19:26 -0500 Subject: [PATCH 69/80] fix shadow + corner radius for images, close #1734 --- src/shapes/Image.ts | 5 +++++ test/unit/Image-test.ts | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/shapes/Image.ts b/src/shapes/Image.ts index b5791cc12..a17cc8787 100644 --- a/src/shapes/Image.ts +++ b/src/shapes/Image.ts @@ -65,6 +65,11 @@ export class Image extends Shape { } } _useBufferCanvas() { + const hasCornerRadius = !!this.cornerRadius(); + const hasShadow = this.hasShadow(); + if (hasCornerRadius && hasShadow) { + return true; + } return super._useBufferCanvas(true); } _sceneFunc(context: Context) { diff --git a/test/unit/Image-test.ts b/test/unit/Image-test.ts index 1f666ed36..be9c95168 100644 --- a/test/unit/Image-test.ts +++ b/test/unit/Image-test.ts @@ -413,4 +413,39 @@ describe('Image', function () { done(); }); }); + + it('corner radius with shadow', function (done) { + // that will trigger buffer canvas + loadImage('darth-vader.jpg', (imageObj) => { + var stage = addStage(); + + var layer = new Konva.Layer(); + var darth = new Konva.Image({ + x: 20, + y: 20, + image: imageObj, + cornerRadius: 10, + draggable: true, + stroke: 'red', + strokeWidth: 100, + strokeEnabled: false, + shadowColor: 'black', + shadowBlur: 10, + shadowOffsetX: 10, + shadowOffsetY: 10, + scaleX: 0.5, + scaleY: 0.5, + }); + + layer.add(darth); + stage.add(layer); + + assert.equal( + layer.getContext().getTrace(true), + 'clearRect();save();shadowColor;shadowBlur;shadowOffsetX;shadowOffsetY;drawImage();restore();' + ); + + done(); + }); + }); }); From 459606b637911279400dc48906198c2be27e62b2 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Tue, 16 Jul 2024 20:20:01 -0500 Subject: [PATCH 70/80] changes --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c69223e03..c8eccdad9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +### 9.3.14 (2024-07-16) + +- Fix shadow + corner radius for images - Support `fillRule` for `Konva.Shape` on hit graph ### 9.3.13 (2024-07-05) From 72d92d8bccb64df38bac797821f09287822fe1de Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Tue, 16 Jul 2024 20:20:23 -0500 Subject: [PATCH 71/80] update CHANGELOG with new version From 331bd9bb64df0cfbd1c95942c3a248b2220f6218 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Tue, 16 Jul 2024 20:20:35 -0500 Subject: [PATCH 72/80] build for 9.3.14 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 59e4e9fd7..4f0d123cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "konva", - "version": "9.3.13", + "version": "9.3.14", "author": "Anton Lavrenov", "files": [ "README.md", From 7b99aa9813dc00ce90804538f0eb0c22b7d0151f Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Tue, 16 Jul 2024 20:20:35 -0500 Subject: [PATCH 73/80] update cdn link From ffc58d248bbb9351066546d15e703f64b274ac2a Mon Sep 17 00:00:00 2001 From: kyechan99 Date: Thu, 18 Jul 2024 18:46:56 +0900 Subject: [PATCH 74/80] fix: specify type Text.measureSize --- src/shapes/Text.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shapes/Text.ts b/src/shapes/Text.ts index 07418fa0e..ddd655596 100644 --- a/src/shapes/Text.ts +++ b/src/shapes/Text.ts @@ -392,13 +392,13 @@ export class Text extends Shape { * That method can't handle multiline text. * @method * @name Konva.Text#measureSize - * @param {String} [text] text to measure - * @returns {Object} { width , height} of measured text + * @param {String} text text to measure + * @returns {Object} { width , height } of measured text */ - measureSize(text) { + measureSize(text: string) { var _context = getDummyContext(), fontSize = this.fontSize(), - metrics; + metrics: TextMetrics; _context.save(); _context.font = this._getContextFont(); From e7dfe86a394283420377cdf2db99a412f1b4bf06 Mon Sep 17 00:00:00 2001 From: kyechan99 Date: Thu, 18 Jul 2024 18:59:33 +0900 Subject: [PATCH 75/80] fix: specify return type Path.getPoint static methods --- src/shapes/Path.ts | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/shapes/Path.ts b/src/shapes/Path.ts index e91f54005..d860b853d 100644 --- a/src/shapes/Path.ts +++ b/src/shapes/Path.ts @@ -2,7 +2,7 @@ import { Factory } from '../Factory'; import { Shape, ShapeConfig } from '../Shape'; import { _registerNode } from '../Global'; -import { GetSet, PathSegment } from '../types'; +import { GetSet, PathSegment, Vector2d } from '../types'; import { getCubicArcLength, getQuadraticArcLength, @@ -235,7 +235,10 @@ export class Path extends Shape { return pathLength; } - static getPointAtLengthOfDataArray(length: number, dataArray) { + static getPointAtLengthOfDataArray( + length: number, + dataArray + ): Vector2d | null { var point, i = 0, ii = dataArray.length; @@ -319,7 +322,7 @@ export class Path extends Shape { return null; } - static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) { + static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?): Vector2d { fromX = fromX ?? P1x; fromY = fromY ?? P1y; @@ -354,7 +357,17 @@ export class Path extends Shape { return { x: ix + adjustedRun, y: iy + adjustedRise }; } - static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) { + static getPointOnCubicBezier( + pct, + P1x, + P1y, + P2x, + P2y, + P3x, + P3y, + P4x, + P4y + ): Vector2d { function CB1(t) { return t * t * t; } @@ -375,7 +388,15 @@ export class Path extends Shape { y: y, }; } - static getPointOnQuadraticBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y) { + static getPointOnQuadraticBezier( + pct, + P1x, + P1y, + P2x, + P2y, + P3x, + P3y + ): Vector2d { function QB1(t) { return t * t; } From e6cb27fc64e4e240590b50836e7eb8675d1bde19 Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 18 Jul 2024 13:48:45 -0500 Subject: [PATCH 76/80] better types, fix #1794 --- src/Node.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Node.ts b/src/Node.ts index a26ce37bb..98a2f1eeb 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -116,19 +116,19 @@ type NodeEventMap = GlobalEventHandlersEventMap & { [index: string]: any; }; -export interface KonvaEventObject { +export interface KonvaEventObject { type: string; target: Shape | Stage; evt: EventType; pointerId: number; - currentTarget: Node; + currentTarget: This; cancelBubble: boolean; child?: Node; } export type KonvaEventListener = ( this: This, - ev: KonvaEventObject + ev: KonvaEventObject ) => void; /** @@ -814,7 +814,7 @@ export abstract class Node { var targets = evt.target.findAncestors(selector, true, stopNode); for (var i = 0; i < targets.length; i++) { evt = Util.cloneObject(evt); - evt.currentTarget = targets[i]; + evt.currentTarget = targets[i] as any; handler.call(targets[i], evt as any); } }); From 45889f9327584539c39de62b54f25ccf27eba67d Mon Sep 17 00:00:00 2001 From: Anton Lavrenov Date: Thu, 18 Jul 2024 13:49:01 -0500 Subject: [PATCH 77/80] changes --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8eccdad9..ab3d4e082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +- ts fixes + ### 9.3.14 (2024-07-16) - Fix shadow + corner radius for images From c6a09c885754e82fd03e5e307829359765c0fd09 Mon Sep 17 00:00:00 2001 From: kyechan99 Date: Fri, 19 Jul 2024 10:15:51 +0900 Subject: [PATCH 78/80] fix: revert changes Path.gitPoint static methods --- src/shapes/Path.ts | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/src/shapes/Path.ts b/src/shapes/Path.ts index d860b853d..e91f54005 100644 --- a/src/shapes/Path.ts +++ b/src/shapes/Path.ts @@ -2,7 +2,7 @@ import { Factory } from '../Factory'; import { Shape, ShapeConfig } from '../Shape'; import { _registerNode } from '../Global'; -import { GetSet, PathSegment, Vector2d } from '../types'; +import { GetSet, PathSegment } from '../types'; import { getCubicArcLength, getQuadraticArcLength, @@ -235,10 +235,7 @@ export class Path extends Shape { return pathLength; } - static getPointAtLengthOfDataArray( - length: number, - dataArray - ): Vector2d | null { + static getPointAtLengthOfDataArray(length: number, dataArray) { var point, i = 0, ii = dataArray.length; @@ -322,7 +319,7 @@ export class Path extends Shape { return null; } - static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?): Vector2d { + static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) { fromX = fromX ?? P1x; fromY = fromY ?? P1y; @@ -357,17 +354,7 @@ export class Path extends Shape { return { x: ix + adjustedRun, y: iy + adjustedRise }; } - static getPointOnCubicBezier( - pct, - P1x, - P1y, - P2x, - P2y, - P3x, - P3y, - P4x, - P4y - ): Vector2d { + static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) { function CB1(t) { return t * t * t; } @@ -388,15 +375,7 @@ export class Path extends Shape { y: y, }; } - static getPointOnQuadraticBezier( - pct, - P1x, - P1y, - P2x, - P2y, - P3x, - P3y - ): Vector2d { + static getPointOnQuadraticBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y) { function QB1(t) { return t * t; } From ad0c15a3ac7322ec89c3bae2b1a3a4b982f00cd7 Mon Sep 17 00:00:00 2001 From: kyechan99 Date: Fri, 19 Jul 2024 23:47:56 +0900 Subject: [PATCH 79/80] fix: specify return type Path.getPoint* methods --- src/shapes/Path.ts | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/shapes/Path.ts b/src/shapes/Path.ts index e91f54005..67a905e25 100644 --- a/src/shapes/Path.ts +++ b/src/shapes/Path.ts @@ -235,8 +235,8 @@ export class Path extends Shape { return pathLength; } - static getPointAtLengthOfDataArray(length: number, dataArray) { - var point, + static getPointAtLengthOfDataArray(length: number, dataArray: PathSegment[]) { + var points: number[], i = 0, ii = dataArray.length; @@ -250,18 +250,18 @@ export class Path extends Shape { } if (i === ii) { - point = dataArray[i - 1].points.slice(-2); + points = dataArray[i - 1].points.slice(-2); return { - x: point[0], - y: point[1], + x: points[0], + y: points[1], }; } if (length < 0.01) { - point = dataArray[i].points.slice(0, 2); + points = dataArray[i].points.slice(0, 2); return { - x: point[0], - y: point[1], + x: points[0], + y: points[1], }; } @@ -319,7 +319,15 @@ export class Path extends Shape { return null; } - static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX?, fromY?) { + static getPointOnLine( + dist: number, + P1x: number, + P1y: number, + P2x: number, + P2y: number, + fromX?: number, + fromY?: number + ) { fromX = fromX ?? P1x; fromY = fromY ?? P1y; From 0d977a1b8ce129f2f58cb86376124b951eab651a Mon Sep 17 00:00:00 2001 From: Daniel Kleis Date: Wed, 31 Jul 2024 22:50:17 +0200 Subject: [PATCH 80/80] #1797 StageConfig: container optional --- src/Stage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Stage.ts b/src/Stage.ts index b5ef16953..a2eb87c3e 100644 --- a/src/Stage.ts +++ b/src/Stage.ts @@ -11,7 +11,7 @@ import { _registerNode } from './Global'; import * as PointerEvents from './PointerEvents'; export interface StageConfig extends ContainerConfig { - container: HTMLDivElement | string; + container?: HTMLDivElement | string; } // CONSTANTS