From 704d37be2f3a208857492bc4860e55f41ce0bd11 Mon Sep 17 00:00:00 2001 From: sasensi Date: Mon, 1 Oct 2018 19:25:04 +0200 Subject: [PATCH] Fix #1503 Item#position caching issue --- src/item/Item.js | 34 +++++++++++++++++++++------------- test/tests/Item.js | 8 ++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/item/Item.js b/src/item/Item.js index 6b8183f2..87ed19ad 100644 --- a/src/item/Item.js +++ b/src/item/Item.js @@ -746,21 +746,29 @@ new function() { // Injection scope for various item event handlers getPosition: function(_dontLink) { // Cache position value. // Pass true for _dontLink in getCenter(), so receive back a normal point - var position = this._position, - ctor = _dontLink ? Point : LinkedPoint; + var ctor = _dontLink ? Point : LinkedPoint; // Do not cache LinkedPoints directly, since we would not be able to // use them to calculate the difference in #setPosition, as when it is // modified, it would hold new values already and only then cause the // calling of #setPosition. - if (!position) { - // If an pivot point is provided, use it to determine position - // based on the matrix. Otherwise use the center of the bounds. - var pivot = this._pivot; - position = this._position = pivot - ? this._matrix._transformPoint(pivot) - : this.getBounds().getCenter(true); + if (!this._position) { + // set position if needed + this._position = this._getPositionFromBounds(); } - return new ctor(position.x, position.y, this, 'setPosition'); + return new ctor(this._position.x, this._position.y, this, 'setPosition'); + }, + + /** + * Internal method used to calculate position either from pivot point or bounds. + * @param {Rectangle} bounds if provided, these bounds are used instead of + * calling getBounds() + * @returns {Point} the transformed pivot point or the center of the bounds + * @private + */ + _getPositionFromBounds: function(bounds) { + return this._pivot + ? this._matrix._transformPoint(this._pivot) + : (bounds || this.getBounds()).getCenter(true); }, setPosition: function(/* point */) { @@ -3509,10 +3517,10 @@ new function() { // Injection scope for hit-test functions shared with project this._bounds = bounds; // If we have cached bounds, try to determine _position as its // center. Use _boundsOptions do get the cached default bounds. - var cached = bounds[this._getBoundsCacheKey( - this._boundsOptions || {})]; + var cached = bounds[this._getBoundsCacheKey(this._boundsOptions || {})]; if (cached) { - this._position = cached.rect.getCenter(true); + // use this method to handle pivot case (see #1503) + this._position = this._getPositionFromBounds(cached.rect); } } else if (transform && position && this._pivot) { // If the item has a pivot defined, it means that the default diff --git a/test/tests/Item.js b/test/tests/Item.js index d19626b4..ed6be88f 100644 --- a/test/tests/Item.js +++ b/test/tests/Item.js @@ -929,3 +929,11 @@ test('Item#scaling, #rotation', function() { equals(shape2.bounds, expected, 'shape2.bounds, setting shape2.scaling before shape2.rotation'); }); + +test('Item#position cache issue with pivot point #1503', function() { + var item = Path.Rectangle(new Point(0, 0), new Size(20)); + item.pivot = new Point(0, 0); + item.getBounds(); + item.translate(5, 5); + equals(item.position, new Point(5, 5)); +});