Fix transformer behaviour on shapes with shadow. fix #481

This commit is contained in:
Anton Lavrenov 2018-10-22 12:16:30 -05:00
parent 2ccc9a7fdd
commit 5136e29d6a
8 changed files with 127 additions and 34 deletions

View File

@ -2,7 +2,7 @@
* Konva JavaScript Framework v2.4.2
* http://konvajs.github.io/
* Licensed under the MIT
* Date: Thu Oct 18 2018
* Date: Mon Oct 22 2018
*
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
@ -2796,6 +2796,7 @@
* @memberof Konva.Node.prototype
* @param {Object} config
* @param {Boolean} [config.skipTransform] should we apply transform to node for calculating rect?
* @param {Boolean} [config.skipShadow] should we apply shadow to the node for calculating bound box?
* @param {Object} [config.relativeTo] calculate client rect relative to one of the parents
* @returns {Object} rect with {x, y, width, height} properties
* @example
@ -8409,7 +8410,10 @@
return;
}
var rect = child.getClientRect({ relativeTo: that });
var rect = child.getClientRect({
relativeTo: that,
skipShadow: attrs.skipShadow
});
// skip invisible children (like empty groups)
if (rect.width === 0 && rect.height === 0) {
@ -8929,6 +8933,7 @@
getClientRect: function(attrs) {
attrs = attrs || {};
var skipTransform = attrs.skipTransform;
var relativeTo = attrs.relativeTo;
var fillRect = this.getSelfRect();
@ -8937,13 +8942,14 @@
var fillAndStrokeWidth = fillRect.width + strokeWidth;
var fillAndStrokeHeight = fillRect.height + strokeWidth;
var shadowOffsetX = this.hasShadow() ? this.shadowOffsetX() : 0;
var shadowOffsetY = this.hasShadow() ? this.shadowOffsetY() : 0;
var applyShadow = !attrs.skipShadow && this.hasShadow();
var shadowOffsetX = applyShadow ? this.shadowOffsetX() : 0;
var shadowOffsetY = applyShadow ? this.shadowOffsetY() : 0;
var preWidth = fillAndStrokeWidth + Math.abs(shadowOffsetX);
var preHeight = fillAndStrokeHeight + Math.abs(shadowOffsetY);
var blurRadius = (this.hasShadow() && this.shadowBlur()) || 0;
var blurRadius = (applyShadow && this.shadowBlur()) || 0;
var width = preWidth + blurRadius * 2;
var height = preHeight + blurRadius * 2;
@ -19731,7 +19737,7 @@
rotation: 0
};
}
var rect = node.getClientRect({ skipTransform: true });
var rect = node.getClientRect({ skipTransform: true, skipShadow: true });
var rotation = Konva.getAngle(node.rotation());
var dx = rect.x * node.scaleX() - node.offsetX() * node.scaleX();
@ -20058,7 +20064,7 @@
var bottomOffsetX = this.getWidth() - bottomRight.x();
var bottomOffsetY = this.getHeight() - bottomRight.y();
console.log(topOffsetX, topOffsetY, bottomOffsetX, bottomOffsetY);
// console.log(topOffsetX, topOffsetY, bottomOffsetX, bottomOffsetY);
bottomRight.move({
x: -topOffsetX,
@ -20125,7 +20131,7 @@
if (newAttrs.rotation !== undefined) {
this.getNode().rotation(newAttrs.rotation);
}
var pure = node.getClientRect({ skipTransform: true });
var pure = node.getClientRect({ skipTransform: true, skipShadow: true });
var padding = this.getPadding();
var scaleX = (newAttrs.width - padding * 2) / pure.width;
var scaleY = (newAttrs.height - padding * 2) / pure.height;

4
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@ -2,13 +2,7 @@
"name": "konva",
"version": "2.4.2",
"author": "Anton Lavrenov",
"files": [
"README.md",
"konva.js",
"konva.min.js",
"src",
"konva.d.ts"
],
"files": ["README.md", "konva.js", "konva.min.js", "src", "konva.d.ts"],
"main": "konva.js",
"typings": "./konva.d.ts",
"scripts": {
@ -16,8 +10,11 @@
"lint": "gulp lint",
"build": "gulp build",
"full-build": "gulp lint && npm t && gulp build",
"test": "mocha-headless-chrome -f ./test/runner.html -a disable-web-security",
"prettier": "prettier --write \"src/**/*.js\" \"test/**/*.js\" --single-quote"
"test":
"mocha-headless-chrome -f ./test/runner.html -a disable-web-security",
"prettier":
"prettier --write \"src/**/*.js\" \"test/**/*.js\" --single-quote",
"typescript": "tsc"
},
"devDependencies": {
"chai": "4.1.2",
@ -33,14 +30,10 @@
"gulp-util": "^3.0.8",
"mocha": "4.0.1",
"prettier": "^1.9.2",
"mocha-headless-chrome": "^2.0.0"
"mocha-headless-chrome": "^2.0.0",
"typescript": "^3.1.3"
},
"keywords": [
"canvas",
"animations",
"graphic",
"html5"
],
"keywords": ["canvas", "animations", "graphic", "html5"],
"prettier": {
"singleQuote": true
},
@ -57,6 +50,5 @@
"type": "git",
"url": "git://github.com/konvajs/konva.git"
},
"license": "MIT",
"dependencies": {}
"license": "MIT"
}

View File

@ -506,7 +506,10 @@
return;
}
var rect = child.getClientRect({ relativeTo: that });
var rect = child.getClientRect({
relativeTo: that,
skipShadow: attrs.skipShadow
});
// skip invisible children (like empty groups)
if (rect.width === 0 && rect.height === 0) {

View File

@ -273,6 +273,7 @@
* @memberof Konva.Node.prototype
* @param {Object} config
* @param {Boolean} [config.skipTransform] should we apply transform to node for calculating rect?
* @param {Boolean} [config.skipShadow] should we apply shadow to the node for calculating bound box?
* @param {Object} [config.relativeTo] calculate client rect relative to one of the parents
* @returns {Object} rect with {x, y, width, height} properties
* @example

View File

@ -254,6 +254,7 @@
getClientRect: function(attrs) {
attrs = attrs || {};
var skipTransform = attrs.skipTransform;
var relativeTo = attrs.relativeTo;
var fillRect = this.getSelfRect();
@ -262,13 +263,14 @@
var fillAndStrokeWidth = fillRect.width + strokeWidth;
var fillAndStrokeHeight = fillRect.height + strokeWidth;
var shadowOffsetX = this.hasShadow() ? this.shadowOffsetX() : 0;
var shadowOffsetY = this.hasShadow() ? this.shadowOffsetY() : 0;
var applyShadow = !attrs.skipShadow && this.hasShadow();
var shadowOffsetX = applyShadow ? this.shadowOffsetX() : 0;
var shadowOffsetY = applyShadow ? this.shadowOffsetY() : 0;
var preWidth = fillAndStrokeWidth + Math.abs(shadowOffsetX);
var preHeight = fillAndStrokeHeight + Math.abs(shadowOffsetY);
var blurRadius = (this.hasShadow() && this.shadowBlur()) || 0;
var blurRadius = (applyShadow && this.shadowBlur()) || 0;
var width = preWidth + blurRadius * 2;
var height = preHeight + blurRadius * 2;

View File

@ -262,7 +262,7 @@
rotation: 0
};
}
var rect = node.getClientRect({ skipTransform: true });
var rect = node.getClientRect({ skipTransform: true, skipShadow: true });
var rotation = Konva.getAngle(node.rotation());
var dx = rect.x * node.scaleX() - node.offsetX() * node.scaleX();
@ -656,7 +656,7 @@
if (newAttrs.rotation !== undefined) {
this.getNode().rotation(newAttrs.rotation);
}
var pure = node.getClientRect({ skipTransform: true });
var pure = node.getClientRect({ skipTransform: true, skipShadow: true });
var padding = this.getPadding();
var scaleX = (newAttrs.width - padding * 2) / pure.width;
var scaleY = (newAttrs.height - padding * 2) / pure.height;

View File

@ -1530,4 +1530,93 @@ suite('Transformer', function() {
);
});
});
test('transformer should ignore shadow', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 50,
draggable: true,
width: 100,
height: 100,
fill: 'yellow',
shadowBlur: 10
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
assert.equal(tr.x(), 50);
assert.equal(tr.y(), 50);
assert.equal(tr.width(), 100);
assert.equal(tr.height(), 100);
tr._fitNodeInto({
x: 50,
y: 50,
width: 100,
height: 100
});
assert.equal(rect.x(), 50);
assert.equal(rect.y(), 50);
assert.equal(rect.width(), 100);
assert.equal(rect.height(), 100);
});
// TODO: current I am not sure how to better resolve that task
test.skip('transformer should skip scale on stroke if strokeScaleEnabled = false', function() {
var stage = addStage();
var layer = new Konva.Layer();
stage.add(layer);
var rect = new Konva.Rect({
x: 50,
y: 50,
draggable: true,
width: 10,
height: 10,
scaleX: 10,
scaleY: 10,
fill: 'yellow',
strokeWidth: 10,
stroke: 'red',
strokeScaleEnabled: false
});
layer.add(rect);
var tr = new Konva.Transformer({
node: rect
});
layer.add(tr);
layer.draw();
assert.equal(tr.x(), 50);
assert.equal(tr.y(), 50);
assert.equal(tr.width(), 100);
assert.equal(tr.height(), 100);
tr._fitNodeInto({
x: 50,
y: 50,
width: 100,
height: 100
});
assert.equal(rect.x(), 50);
assert.equal(rect.y(), 50);
assert.equal(rect.width(), 100);
assert.equal(rect.height(), 100);
});
});