From 600bb7268ed235e7ad1c966c99d7af72b8f80d6f Mon Sep 17 00:00:00 2001 From: Alexander Chernoskutov Date: Wed, 28 Apr 2021 22:03:23 +0500 Subject: [PATCH] Add isClientRectOnScreen() method to Node #1086 --- package.json | 2 +- src/Node.ts | 35 +++++++++++++++++++++++++++++++++++ test/unit/Node-test.js | 26 ++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9538b1e1..157abb9b 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-sourcemaps": "^0.6.3", - "rollup-plugin-typescript2": "^0.29.0", + "rollup-plugin-typescript2": "^0.30.0", "size-limit": "^4.9.1", "typescript": "^4.1.3" }, diff --git a/src/Node.ts b/src/Node.ts index 9ab0b0a0..cb8b52aa 100644 --- a/src/Node.ts +++ b/src/Node.ts @@ -2527,6 +2527,41 @@ export abstract class Node { this.off('touchstart.konva'); } + /** + * determine if node (at least partially) is currently in user-visible area + * @method + * @param {(Number | Object)} margin optional margin in pixels + * @param {Number} margin.x + * @param {Number} margin.y + * @returns {Boolean} + * @name Konva.Node#isClientRectOnScreen + */ + isClientRectOnScreen(margin?: number | {x: number; y: number;}): boolean { + const _margin = + margin === undefined + ? {x: 0, y: 0} + : isNaN(margin as any) + ? margin as {x: number; y: number;} + : {x: margin as number, y: margin as number} + ; + type Rect = {[k in 'x'|'y'|'width'|'height']: number}; + const haveIntersection = (r1: Rect, r2: Rect) => !( + r2.x > r1.x + r1.width || + r2.x + r2.width < r1.x || + r2.y > r1.y + r1.height || + r2.y + r2.height < r1.y + ); + const stage = this.getStage(); + if(!stage) return false; + const screenRect = { + x: (-stage.x() - _margin.x) / stage.scaleX(), + y: (-stage.y() - _margin.y) / stage.scaleY(), + width: (stage.width() + _margin.x) / stage.scaleX(), + height: (stage.height() + + _margin.y) / stage.scaleY() + }; + return haveIntersection(screenRect, this.getClientRect({relativeTo: stage as any})); + } + preventDefault: GetSet; // from filters diff --git a/test/unit/Node-test.js b/test/unit/Node-test.js index c6033f1e..99d8fa5c 100644 --- a/test/unit/Node-test.js +++ b/test/unit/Node-test.js @@ -3867,4 +3867,30 @@ suite('Node', function () { assert.equal(text00.getClientRect().x, 90); assert.equal(text00.getClientRect().y, 90); }); + + // ====================================================== + test('isClientRectOnScreen() method', function () { + var stage = addStage(); + var layer = new Konva.Layer(); + var circle = new Konva.Circle({ + x: stage.getWidth() / 2, + y: stage.getHeight() / 2, + radius: 30, + fill: 'green', + stroke: 'black', + strokeWidth: 4, + }); + + layer.add(circle); + stage.add(layer); + + assert.equal(circle.isClientRectOnScreen(), true); + + circle.x(-circle.radius() - circle.strokeWidth()/2 - 1); // Move circle 1px outside of visible area + assert.equal(circle.isClientRectOnScreen(), false); + assert.equal(circle.isClientRectOnScreen(1), true); + assert.equal(circle.isClientRectOnScreen({x: 1, y: 0}), true); + assert.equal(circle.isClientRectOnScreen({x: 0, y: 1}), false); + + }); });