From d11c55e9cd2b19cb4ed01d5d244b22bd2a333def Mon Sep 17 00:00:00 2001 From: Andrea Bogazzi Date: Thu, 28 Sep 2017 23:25:20 -0400 Subject: [PATCH] Make scaleToWidth/scaleToHeight use the absolute parameter (#4350) * added absolute param to scaleToWidth * added simple tests --- src/mixins/object_geometry.mixin.js | 32 ++---- src/util/misc.js | 4 +- test/unit/object.js | 117 ------------------- test/unit/object_geometry.js | 169 +++++++++++++++++++++++++++- 4 files changed, 173 insertions(+), 149 deletions(-) diff --git a/src/mixins/object_geometry.mixin.js b/src/mixins/object_geometry.mixin.js index 5d456736..904a4f0b 100644 --- a/src/mixins/object_geometry.mixin.js +++ b/src/mixins/object_geometry.mixin.js @@ -252,24 +252,6 @@ return xcount; }, - /** - * Returns width of an object's bounding rectangle - * @deprecated since 1.0.4 - * @return {Number} width value - */ - getBoundingRectWidth: function() { - return this.getBoundingRect().width; - }, - - /** - * Returns height of an object's bounding rectangle - * @deprecated since 1.0.4 - * @return {Number} height value - */ - getBoundingRectHeight: function() { - return this.getBoundingRect().height; - }, - /** * Returns coordinates of object's bounding rectangle (left, top, width, height) * the box is intented as aligned to axis of canvas. @@ -334,24 +316,26 @@ /** * Scales an object to a given width, with respect to bounding box (scaling by x/y equally) * @param {Number} value New width value + * @param {Boolean} absolute ignore viewport * @return {fabric.Object} thisArg * @chainable */ - scaleToWidth: function(value) { + scaleToWidth: function(value, absolute) { // adjust to bounding rect factor so that rotated shapes would fit as well - var boundingRectFactor = this.getBoundingRect().width / this.getScaledWidth(); + var boundingRectFactor = this.getBoundingRect(absolute).width / this.getScaledWidth(); return this.scale(value / this.width / boundingRectFactor); }, /** * Scales an object to a given height, with respect to bounding box (scaling by x/y equally) * @param {Number} value New height value + * @param {Boolean} absolute ignore viewport * @return {fabric.Object} thisArg * @chainable */ - scaleToHeight: function(value) { + scaleToHeight: function(value, absolute) { // adjust to bounding rect factor so that rotated shapes would fit as well - var boundingRectFactor = this.getBoundingRect().height / this.getScaledHeight(); + var boundingRectFactor = this.getBoundingRect(absolute).height / this.getScaledHeight(); return this.scale(value / this.height / boundingRectFactor); }, @@ -365,8 +349,8 @@ vpt = this.getViewportTransform(), dim = absolute ? this._getTransformedDimensions() : this._calculateCurrentDimensions(), currentWidth = dim.x, currentHeight = dim.y, - sinTh = Math.sin(theta), - cosTh = Math.cos(theta), + sinTh = theta ? Math.sin(theta) : 0, + cosTh = theta ? Math.cos(theta) : 1, _angle = currentWidth > 0 ? Math.atan(currentHeight / currentWidth) : 0, _hypotenuse = (currentWidth / Math.cos(_angle)) / 2, offsetX = Math.cos(_angle + theta) * _hypotenuse, diff --git a/src/util/misc.js b/src/util/misc.js index 7567402f..37bdf631 100644 --- a/src/util/misc.js +++ b/src/util/misc.js @@ -127,11 +127,11 @@ var xPoints = [points[0].x, points[1].x, points[2].x, points[3].x], minX = fabric.util.array.min(xPoints), maxX = fabric.util.array.max(xPoints), - width = Math.abs(minX - maxX), + width = maxX - minX, yPoints = [points[0].y, points[1].y, points[2].y, points[3].y], minY = fabric.util.array.min(yPoints), maxY = fabric.util.array.max(yPoints), - height = Math.abs(minY - maxY); + height = maxY - minY; return { left: minX, diff --git a/test/unit/object.js b/test/unit/object.js index 4878976d..eb4e7598 100644 --- a/test/unit/object.js +++ b/test/unit/object.js @@ -344,93 +344,6 @@ assert.ok(typeof cObj.render === 'function'); }); - QUnit.test('getBoundingRect', function(assert) { - var cObj = new fabric.Object({ strokeWidth: 0 }), - boundingRect; - assert.ok(typeof cObj.getBoundingRect === 'function'); - - cObj.setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left, 0); - assert.equal(boundingRect.top, 0); - assert.equal(boundingRect.width, 0); - assert.equal(boundingRect.height, 0); - cObj.set('width', 123).setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left, 0); - assert.equal(boundingRect.top, 0); - assert.equal(boundingRect.width, 123); - assert.equal(boundingRect.height, 0); - - cObj.set('height', 167).setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left, 0); - assert.equal(Math.abs(boundingRect.top).toFixed(13), 0); - assert.equal(boundingRect.width, 123); - assert.equal(boundingRect.height, 167); - - cObj.scale(2).setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left, 0); - assert.equal(Math.abs(boundingRect.top).toFixed(13), 0); - assert.equal(boundingRect.width, 246); - assert.equal(boundingRect.height, 334); - }); - - QUnit.test('getBoundingRectWithStroke', function(assert) { - var cObj = new fabric.Object(), - boundingRect; - assert.ok(typeof cObj.getBoundingRect === 'function'); - - cObj.setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left.toFixed(2), 0); - assert.equal(boundingRect.top.toFixed(2), 0); - assert.equal(boundingRect.width.toFixed(2), 1); - assert.equal(boundingRect.height.toFixed(2), 1); - - cObj.set('width', 123).setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left.toFixed(2), 0); - assert.equal(boundingRect.top.toFixed(2), 0); - assert.equal(boundingRect.width.toFixed(2), 124); - assert.equal(boundingRect.height.toFixed(2), 1); - - cObj.set('height', 167).setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left.toFixed(2), 0); - assert.equal(boundingRect.top.toFixed(2), 0); - assert.equal(boundingRect.width.toFixed(2), 124); - assert.equal(boundingRect.height.toFixed(2), 168); - - cObj.scale(2).setCoords(); - boundingRect = cObj.getBoundingRect(); - assert.equal(boundingRect.left.toFixed(2), 0); - assert.equal(boundingRect.top.toFixed(2), 0); - assert.equal(boundingRect.width.toFixed(2), 248); - assert.equal(boundingRect.height.toFixed(2), 336); - }); - - QUnit.test('getScaledWidth', function(assert) { - var cObj = new fabric.Object(); - assert.ok(typeof cObj.getScaledWidth === 'function'); - assert.equal(cObj.getScaledWidth(), 0 + cObj.strokeWidth); - cObj.set('width', 123); - assert.equal(cObj.getScaledWidth(), 123 + cObj.strokeWidth); - cObj.set('scaleX', 2); - assert.equal(cObj.getScaledWidth(), 246 + cObj.strokeWidth * 2); - }); - - QUnit.test('getHeight', function(assert) { - var cObj = new fabric.Object({strokeWidth: 0}); - // assert.ok(typeof cObj.getHeight === 'function'); - assert.equal(cObj.getScaledHeight(), 0); - cObj.set('height', 123); - assert.equal(cObj.getScaledHeight(), 123); - cObj.set('scaleY', 2); - assert.equal(cObj.getScaledHeight(), 246); - }); - QUnit.test('rotate', function(assert) { var cObj = new fabric.Object(); assert.ok(typeof cObj.rotate === 'function'); @@ -450,36 +363,6 @@ assert.equal(cObj.scale(2), cObj, 'chainable'); }); - QUnit.test('scaleToWidth', function(assert) { - var cObj = new fabric.Object({ width: 560, strokeWidth: 0 }); - assert.ok(typeof cObj.scaleToWidth === 'function'); - assert.equal(cObj.scaleToWidth(100), cObj, 'chainable'); - assert.equal(cObj.getScaledWidth(), 100); - assert.equal(cObj.get('scaleX'), 100 / 560); - }); - - QUnit.test('scaleToHeight', function(assert) { - var cObj = new fabric.Object({ height: 560, strokeWidth: 0 }); - assert.ok(typeof cObj.scaleToHeight === 'function'); - assert.equal(cObj.scaleToHeight(100), cObj, 'chainable'); - assert.equal(cObj.getScaledHeight(), 100); - assert.equal(cObj.get('scaleY'), 100 / 560); - }); - - QUnit.test('scaleToWidth on rotated object', function(assert) { - var obj = new fabric.Object({ height: 100, width: 100, strokeWidth: 0 }); - obj.rotate(45); - obj.scaleToWidth(200); - assert.equal(Math.round(obj.getBoundingRect().width), 200); - }); - - QUnit.test('scaleToHeight on rotated object', function(assert) { - var obj = new fabric.Object({ height: 100, width: 100, strokeWidth: 0 }); - obj.rotate(45); - obj.scaleToHeight(300); - assert.equal(Math.round(obj.getBoundingRect().height), 300); - }); - QUnit.test('setOpacity', function(assert) { var cObj = new fabric.Object(); assert.equal(cObj.get('opacity'), 1); diff --git a/test/unit/object_geometry.js b/test/unit/object_geometry.js index aa2469b4..8bb5c375 100644 --- a/test/unit/object_geometry.js +++ b/test/unit/object_geometry.js @@ -371,14 +371,171 @@ assert.ok(typeof cObj._calcRotateMatrix === 'function', '_calcRotateMatrix should exist'); }); - QUnit.test('scaleToHeight', function(assert) { - var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 0 }); - assert.ok(typeof cObj.scaleToHeight === 'function', 'scaleToHeight should exist'); + QUnit.test('scaleToWidth', function(assert) { + var cObj = new fabric.Object({ width: 560, strokeWidth: 0 }); + assert.ok(typeof cObj.scaleToWidth === 'function', 'scaleToWidth should exist'); + assert.equal(cObj.scaleToWidth(100), cObj, 'chainable'); + assert.equal(cObj.getScaledWidth(), 100); + assert.equal(cObj.get('scaleX'), 100 / 560); }); - QUnit.test('scaleToWidth', function(assert) { - var cObj = new fabric.Object({ width: 10, height: 15, strokeWidth: 0 }); - assert.ok(typeof cObj.scaleToWidth === 'function', 'scaleToWidth should exist'); + QUnit.test('scaleToWidth with zoom', function(assert) { + var cObj = new fabric.Object({ width: 560, strokeWidth: 0 }); + cObj.canvas = { + viewportTransform: [2, 0, 0, 2, 0, 0] + }; + assert.equal(cObj.scaleToWidth(100, true), cObj, 'chainable'); + assert.equal(cObj.getScaledWidth(), 100, 'is not influenced by zoom - width'); + assert.equal(cObj.get('scaleX'), 100 / 560); + assert.equal(cObj.scaleToWidth(100), cObj, 'chainable'); + assert.equal(cObj.getScaledWidth(), 50, 'is influenced by zoom - width'); + assert.equal(cObj.get('scaleX'), 100 / 560 / 2); + }); + + + QUnit.test('scaleToHeight', function(assert) { + var cObj = new fabric.Object({ height: 560, strokeWidth: 0 }); + assert.ok(typeof cObj.scaleToHeight === 'function', 'scaleToHeight should exist'); + assert.equal(cObj.scaleToHeight(100), cObj, 'chainable'); + assert.equal(cObj.getScaledHeight(), 100); + assert.equal(cObj.get('scaleY'), 100 / 560); + }); + + QUnit.test('scaleToHeight with zoom', function(assert) { + var cObj = new fabric.Object({ height: 560, strokeWidth: 0 }); + cObj.canvas = { + viewportTransform: [2, 0, 0, 2, 0, 0] + }; + assert.equal(cObj.scaleToHeight(100, true), cObj, 'chainable'); + assert.equal(cObj.getScaledHeight(), 100, 'is not influenced by zoom - height'); + assert.equal(cObj.get('scaleY'), 100 / 560); + assert.equal(cObj.scaleToHeight(100), cObj, 'chainable'); + assert.equal(cObj.getScaledHeight(), 50, 'is influenced by zoom - height'); + assert.equal(cObj.get('scaleY'), 100 / 560 / 2); + }); + + QUnit.test('scaleToWidth on rotated object', function(assert) { + var obj = new fabric.Object({ height: 100, width: 100, strokeWidth: 0 }); + obj.rotate(45); + obj.scaleToWidth(200); + assert.equal(Math.round(obj.getBoundingRect().width), 200); + }); + + QUnit.test('scaleToHeight on rotated object', function(assert) { + var obj = new fabric.Object({ height: 100, width: 100, strokeWidth: 0 }); + obj.rotate(45); + obj.scaleToHeight(300); + assert.equal(Math.round(obj.getBoundingRect().height), 300); + }); + + QUnit.test('getBoundingRect with absolute coords', function(assert) { + var cObj = new fabric.Object({ strokeWidth: 0, width: 10, height: 10, top: 6, left: 5 }), + boundingRect; + + cObj.setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left, 5, 'gives the bounding rect left with zoom 1'); + assert.equal(boundingRect.width, 10, 'gives the bounding rect width with zoom 1'); + assert.equal(boundingRect.height, 10, 'gives the bounding rect height with zoom 1'); + cObj.canvas = { + viewportTransform: [2, 0, 0, 2, 0, 0] + }; + cObj.setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left, 10, 'gives the bounding rect left with zoom 2'); + assert.equal(boundingRect.width, 20, 'gives the bounding rect width with zoom 2'); + assert.equal(boundingRect.height, 20, 'gives the bounding rect height with zoom 2'); + boundingRect = cObj.getBoundingRect(true); + assert.equal(boundingRect.left, 5, 'gives the bounding rect left with absolute coords'); + assert.equal(boundingRect.width, 10, 'gives the bounding rect width with absolute coords'); + assert.equal(boundingRect.height, 10, 'gives the bounding rect height with absolute coords'); + }); + + QUnit.test('getBoundingRect', function(assert) { + var cObj = new fabric.Object({ strokeWidth: 0 }), + boundingRect; + assert.ok(typeof cObj.getBoundingRect === 'function'); + + cObj.setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left, 0); + assert.equal(boundingRect.top, 0); + assert.equal(boundingRect.width, 0); + assert.equal(boundingRect.height, 0); + cObj.set('width', 123).setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left, 0); + assert.equal(boundingRect.top, 0); + assert.equal(boundingRect.width, 123); + assert.equal(boundingRect.height, 0); + + cObj.set('height', 167).setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left, 0); + assert.equal(Math.abs(boundingRect.top).toFixed(13), 0); + assert.equal(boundingRect.width, 123); + assert.equal(boundingRect.height, 167); + + cObj.scale(2).setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left, 0); + assert.equal(Math.abs(boundingRect.top).toFixed(13), 0); + assert.equal(boundingRect.width, 246); + assert.equal(boundingRect.height, 334); + }); + + QUnit.test('getBoundingRectWithStroke', function(assert) { + var cObj = new fabric.Object(), + boundingRect; + assert.ok(typeof cObj.getBoundingRect === 'function'); + + cObj.setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left.toFixed(2), 0); + assert.equal(boundingRect.top.toFixed(2), 0); + assert.equal(boundingRect.width.toFixed(2), 1); + assert.equal(boundingRect.height.toFixed(2), 1); + + cObj.set('width', 123).setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left.toFixed(2), 0); + assert.equal(boundingRect.top.toFixed(2), 0); + assert.equal(boundingRect.width.toFixed(2), 124); + assert.equal(boundingRect.height.toFixed(2), 1); + + cObj.set('height', 167).setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left.toFixed(2), 0); + assert.equal(boundingRect.top.toFixed(2), 0); + assert.equal(boundingRect.width.toFixed(2), 124); + assert.equal(boundingRect.height.toFixed(2), 168); + + cObj.scale(2).setCoords(); + boundingRect = cObj.getBoundingRect(); + assert.equal(boundingRect.left.toFixed(2), 0); + assert.equal(boundingRect.top.toFixed(2), 0); + assert.equal(boundingRect.width.toFixed(2), 248); + assert.equal(boundingRect.height.toFixed(2), 336); + }); + + QUnit.test('getScaledWidth', function(assert) { + var cObj = new fabric.Object(); + assert.ok(typeof cObj.getScaledWidth === 'function'); + assert.equal(cObj.getScaledWidth(), 0 + cObj.strokeWidth); + cObj.set('width', 123); + assert.equal(cObj.getScaledWidth(), 123 + cObj.strokeWidth); + cObj.set('scaleX', 2); + assert.equal(cObj.getScaledWidth(), 246 + cObj.strokeWidth * 2); + }); + + QUnit.test('getScaledHeight', function(assert) { + var cObj = new fabric.Object({strokeWidth: 0}); + // assert.ok(typeof cObj.getHeight === 'function'); + assert.equal(cObj.getScaledHeight(), 0); + cObj.set('height', 123); + assert.equal(cObj.getScaledHeight(), 123); + cObj.set('scaleY', 2); + assert.equal(cObj.getScaledHeight(), 246); }); QUnit.test('scale', function(assert) {