Fix rounding issues for getClientRect() for some shapes. fix #879

This commit is contained in:
Anton Lavrenov
2020-03-26 14:41:06 -05:00
parent 65e06f200e
commit 3d00d1a344
9 changed files with 105 additions and 59 deletions

View File

@@ -6,6 +6,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## Not released: ## Not released:
* Fix some issues with `mouseenter` and `mouseleave` events. * Fix some issues with `mouseenter` and `mouseleave` events.
* Deprecate `hitStrokeEnabled` property
* Fix rounding issues for `getClientRect()` for some shapes
## 4.2.0 - 2020-03-14 ## 4.2.0 - 2020-03-14

View File

@@ -8,7 +8,7 @@
* Konva JavaScript Framework v4.2.0 * Konva JavaScript Framework v4.2.0
* http://konvajs.org/ * http://konvajs.org/
* Licensed under the MIT * Licensed under the MIT
* Date: Wed Mar 18 2020 * Date: Thu Mar 26 2020
* *
* Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS) * Original work Copyright (C) 2011 - 2013 by Eric Rowell (KineticJS)
* Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva) * Modified work Copyright (C) 2014 - present by Anton Lavrenov (Konva)
@@ -7146,11 +7146,11 @@
}; };
Shape.prototype._hasShadow = function () { Shape.prototype._hasShadow = function () {
return (this.shadowEnabled() && return (this.shadowEnabled() &&
(this.shadowOpacity() !== 0 && this.shadowOpacity() !== 0 &&
!!(this.shadowColor() || !!(this.shadowColor() ||
this.shadowBlur() || this.shadowBlur() ||
this.shadowOffsetX() || this.shadowOffsetX() ||
this.shadowOffsetY()))); this.shadowOffsetY()));
}; };
Shape.prototype._getFillPattern = function () { Shape.prototype._getFillPattern = function () {
return this._getCache(patternImage, this.__getFillPattern); return this._getCache(patternImage, this.__getFillPattern);
@@ -7229,10 +7229,11 @@
* @returns {Boolean} * @returns {Boolean}
*/ */
Shape.prototype.hasFill = function () { Shape.prototype.hasFill = function () {
return this.fillEnabled() && !!(this.fill() || return (this.fillEnabled() &&
!!(this.fill() ||
this.fillPatternImage() || this.fillPatternImage() ||
this.fillLinearGradientColorStops() || this.fillLinearGradientColorStops() ||
this.fillRadialGradientColorStops()); this.fillRadialGradientColorStops()));
}; };
/** /**
* returns whether or not the shape will be stroked * returns whether or not the shape will be stroked
@@ -7252,7 +7253,7 @@
// we should enable hit stroke we stroke is enabled // we should enable hit stroke we stroke is enabled
// and we have some value from width // and we have some value from width
return (this.strokeEnabled() && return (this.strokeEnabled() &&
(width || this.strokeWidth() && width === 'auto')); (width || (this.strokeWidth() && width === 'auto')));
}; };
/** /**
* determines if point is in the shape, regardless if other shapes are on top of it. Note: because * determines if point is in the shape, regardless if other shapes are on top of it. Note: because
@@ -7291,6 +7292,7 @@
this.getStage()); this.getStage());
}; };
Shape.prototype.setStrokeHitEnabled = function (val) { Shape.prototype.setStrokeHitEnabled = function (val) {
Util.warn('strokeHitEnabled property is deprecated. Please use hitStrokeWidth instead.');
if (val) { if (val) {
this.hitStrokeWidth('auto'); this.hitStrokeWidth('auto');
} }
@@ -7321,8 +7323,8 @@
Shape.prototype.getSelfRect = function () { Shape.prototype.getSelfRect = function () {
var size = this.size(); var size = this.size();
return { return {
x: this._centroid ? Math.round(-size.width / 2) : 0, x: this._centroid ? -size.width / 2 : 0,
y: this._centroid ? Math.round(-size.height / 2) : 0, y: this._centroid ? -size.height / 2 : 0,
width: size.width, width: size.width,
height: size.height height: size.height
}; };
@@ -7619,7 +7621,7 @@
// TODO: probably we should deprecate it // TODO: probably we should deprecate it
Factory.addGetterSetter(Shape, 'strokeHitEnabled', true, getBooleanValidator()); Factory.addGetterSetter(Shape, 'strokeHitEnabled', true, getBooleanValidator());
/** /**
* get/set strokeHitEnabled property. Useful for performance optimization. * **deprecated, use hitStrokeWidth instead!** get/set strokeHitEnabled property. Useful for performance optimization.
* You may set `shape.strokeHitEnabled(false)`. In this case stroke will be no draw on hit canvas, so hit area * You may set `shape.strokeHitEnabled(false)`. In this case stroke will be no draw on hit canvas, so hit area
* of shape will be decreased (by lineWidth / 2). Remember that non closed line with `strokeHitEnabled = false` * of shape will be decreased (by lineWidth / 2). Remember that non closed line with `strokeHitEnabled = false`
* will be not drawn on hit canvas, that is mean line will no trigger pointer events (like mouseover) * will be not drawn on hit canvas, that is mean line will no trigger pointer events (like mouseover)
@@ -10259,10 +10261,10 @@
maxY = Math.max(maxY, y); maxY = Math.max(maxY, y);
} }
return { return {
x: Math.round(minX), x: minX,
y: Math.round(minY), y: minY,
width: Math.round(maxX - minX), width: maxX - minX,
height: Math.round(maxY - minY) height: maxY - minY
}; };
}; };
return Line; return Line;
@@ -13528,7 +13530,11 @@
context.fillStrokeShape(this); context.fillStrokeShape(this);
}; };
Text.prototype.setText = function (text) { Text.prototype.setText = function (text) {
var str = Util._isString(text) ? text : (text === null || text === undefined) ? '' : text + ''; var str = Util._isString(text)
? text
: text === null || text === undefined
? ''
: text + '';
this._setAttr(TEXT, str); this._setAttr(TEXT, str);
return this; return this;
}; };
@@ -14428,10 +14434,10 @@
} }
var fontSize = this.fontSize(); var fontSize = this.fontSize();
return { return {
x: Math.round(minX) - fontSize / 2, x: minX - fontSize / 2,
y: Math.round(minY) - fontSize / 2, y: minY - fontSize / 2,
width: Math.round(maxX - minX) + fontSize, width: maxX - minX + fontSize,
height: Math.round(maxY - minY) + fontSize height: maxY - minY + fontSize
}; };
}; };
return TextPath; return TextPath;

4
konva.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -246,13 +246,13 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
_hasShadow() { _hasShadow() {
return ( return (
this.shadowEnabled() && this.shadowEnabled() &&
(this.shadowOpacity() !== 0 && this.shadowOpacity() !== 0 &&
!!( !!(
this.shadowColor() || this.shadowColor() ||
this.shadowBlur() || this.shadowBlur() ||
this.shadowOffsetX() || this.shadowOffsetX() ||
this.shadowOffsetY() this.shadowOffsetY()
)) )
); );
} }
_getFillPattern() { _getFillPattern() {
@@ -349,11 +349,14 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
* @returns {Boolean} * @returns {Boolean}
*/ */
hasFill() { hasFill() {
return this.fillEnabled() && !!( return (
this.fillEnabled() &&
!!(
this.fill() || this.fill() ||
this.fillPatternImage() || this.fillPatternImage() ||
this.fillLinearGradientColorStops() || this.fillLinearGradientColorStops() ||
this.fillRadialGradientColorStops() this.fillRadialGradientColorStops()
)
); );
} }
/** /**
@@ -377,7 +380,7 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
// and we have some value from width // and we have some value from width
return ( return (
this.strokeEnabled() && this.strokeEnabled() &&
(width || this.strokeWidth() && width === 'auto') (width || (this.strokeWidth() && width === 'auto'))
); );
} }
/** /**
@@ -428,6 +431,9 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
); );
} }
setStrokeHitEnabled(val: number) { setStrokeHitEnabled(val: number) {
Util.warn(
'strokeHitEnabled property is deprecated. Please use hitStrokeWidth instead.'
);
if (val) { if (val) {
this.hitStrokeWidth('auto'); this.hitStrokeWidth('auto');
} else { } else {
@@ -456,8 +462,8 @@ export class Shape<Config extends ShapeConfig = ShapeConfig> extends Node<
getSelfRect() { getSelfRect() {
var size = this.size(); var size = this.size();
return { return {
x: this._centroid ? Math.round(-size.width / 2) : 0, x: this._centroid ? -size.width / 2 : 0,
y: this._centroid ? Math.round(-size.height / 2) : 0, y: this._centroid ? -size.height / 2 : 0,
width: size.width, width: size.width,
height: size.height height: size.height
}; };
@@ -888,7 +894,7 @@ Factory.addGetterSetter(
Factory.addGetterSetter(Shape, 'strokeHitEnabled', true, getBooleanValidator()); Factory.addGetterSetter(Shape, 'strokeHitEnabled', true, getBooleanValidator());
/** /**
* get/set strokeHitEnabled property. Useful for performance optimization. * **deprecated, use hitStrokeWidth instead!** get/set strokeHitEnabled property. Useful for performance optimization.
* You may set `shape.strokeHitEnabled(false)`. In this case stroke will be no draw on hit canvas, so hit area * You may set `shape.strokeHitEnabled(false)`. In this case stroke will be no draw on hit canvas, so hit area
* of shape will be decreased (by lineWidth / 2). Remember that non closed line with `strokeHitEnabled = false` * of shape will be decreased (by lineWidth / 2). Remember that non closed line with `strokeHitEnabled = false`
* will be not drawn on hit canvas, that is mean line will no trigger pointer events (like mouseover) * will be not drawn on hit canvas, that is mean line will no trigger pointer events (like mouseover)

View File

@@ -219,10 +219,10 @@ export class Line<Config extends LineConfig = LineConfig> extends Shape<
maxY = Math.max(maxY, y); maxY = Math.max(maxY, y);
} }
return { return {
x: Math.round(minX), x: minX,
y: Math.round(minY), y: minY,
width: Math.round(maxX - minX), width: maxX - minX,
height: Math.round(maxY - minY) height: maxY - minY
}; };
} }

View File

@@ -95,9 +95,11 @@ function checkDefaultFill(config) {
} }
// polyfill for IE11 // polyfill for IE11
const trimRight = String.prototype.trimRight || function polyfill() { const trimRight =
String.prototype.trimRight ||
function polyfill() {
return this.replace(/[\s\xa0]+$/, ''); return this.replace(/[\s\xa0]+$/, '');
} };
/** /**
* Text constructor * Text constructor
@@ -294,7 +296,11 @@ export class Text extends Shape<TextConfig> {
context.fillStrokeShape(this); context.fillStrokeShape(this);
} }
setText(text) { setText(text) {
var str = Util._isString(text) ? text : (text === null || text === undefined) ? '' : text + ''; var str = Util._isString(text)
? text
: text === null || text === undefined
? ''
: text + '';
this._setAttr(TEXT, str); this._setAttr(TEXT, str);
return this; return this;
} }

View File

@@ -531,10 +531,10 @@ export class TextPath extends Shape<TextPathConfig> {
} }
var fontSize = this.fontSize(); var fontSize = this.fontSize();
return { return {
x: Math.round(minX) - fontSize / 2, x: minX - fontSize / 2,
y: Math.round(minY) - fontSize / 2, y: minY - fontSize / 2,
width: Math.round(maxX - minX) + fontSize, width: maxX - minX + fontSize,
height: Math.round(maxY - minY) + fontSize height: maxY - minY + fontSize
}; };
} }

View File

@@ -309,10 +309,10 @@ suite('Line', function() {
stage.add(layer); stage.add(layer);
assert.equal(client.x, 56, 'check x'); assert.equal(Math.round(client.x), 56, 'check x');
assert.equal(client.y, 74, 'check y'); assert.equal(Math.round(client.y), 74, 'check y');
assert.equal(client.width, 245, 'check width'); assert.equal(Math.round(client.width), 245, 'check width');
assert.equal(client.height, 147, 'check height'); assert.equal(Math.round(client.height), 147, 'check height');
}); });
test('getClientRect with low number of points', function() { test('getClientRect with low number of points', function() {
@@ -401,4 +401,30 @@ suite('Line', function() {
'calculated points should change' 'calculated points should change'
); );
}); });
test('getClientRect with scaling', function() {
var stage = addStage();
var scale = 42;
stage.scaleX(scale);
stage.scaleY(scale);
var layer = new Konva.Layer();
stage.add(layer);
var points = [1, 1, 7, 2, 8, 7, 2, 6];
var line = new Konva.Line({
points: points.map(function(v) {
return (v * 20) / scale;
}),
closed: true,
fill: 'green'
});
layer.add(line);
var client = line.getClientRect();
assert.equal(client.x, 20, 'check x');
assert.equal(client.y, 20, 'check y');
assert.equal(client.width, 140, 'check width');
assert.equal(client.height, 120, 'check height');
});
}); });

View File

@@ -260,7 +260,7 @@ suite('TextPath', function() {
layer.add(textpath); layer.add(textpath);
stage.add(layer); stage.add(layer);
cloneAndCompareLayer(layer, 50); cloneAndCompareLayer(layer, 200);
showHit(layer); showHit(layer);
}); });
@@ -286,7 +286,7 @@ suite('TextPath', function() {
layer.add(textpath); layer.add(textpath);
stage.add(layer); stage.add(layer);
cloneAndCompareLayer(layer, 50); cloneAndCompareLayer(layer, 200);
showHit(layer); showHit(layer);
}); });