From 7995cf504434d98e60bfa6e240a7e14eee8372fb Mon Sep 17 00:00:00 2001 From: nichollascarter Date: Tue, 21 Dec 2021 21:44:58 +0300 Subject: [PATCH] feat(src): add setCenterPoint method #56 --- src/js/core/transform/Draggable.js | 44 ++++++++++---- src/js/core/transform/Transformable.js | 9 ++- src/js/core/transform/svg/DraggableSVG.js | 72 ++++++++++++++--------- test/subjx.test.js | 4 +- 4 files changed, 86 insertions(+), 43 deletions(-) diff --git a/src/js/core/transform/Draggable.js b/src/js/core/transform/Draggable.js index 555bef3..6cb6509 100644 --- a/src/js/core/transform/Draggable.js +++ b/src/js/core/transform/Draggable.js @@ -1300,37 +1300,55 @@ export default class Draggable extends Transformable { }); } - resetCenterPoint() { + setCenterPoint({ x, y, dx, dy } = {}, pin = true) { const { elements: [element] = [], storage: { wrapper, - handles: { center } - }, + handles: { + center: handle + }, + center + } = {}, options: { container - } + } = {} } = this; - if (!center) return; + const isRelative = isDef(dx) && isDef(dy), + isAbsolute = isDef(x) && isDef(y); - const { offsetHeight, offsetWidth } = element; - - const [offsetLeft, offsetTop] = getAbsoluteOffset(element, container); + if (!handle || !center || !(isRelative || isAbsolute)) return; const matrix = multiplyMatrix( getCurrentTransformMatrix(element, container), matrixInvert(getCurrentTransformMatrix(wrapper, wrapper.parentNode)) ); - const [x, y] = multiplyMatrixAndPoint( + let newX, newY; + + const [offsetLeft, offsetTop] = getAbsoluteOffset(element, container); + + if (isRelative) { + const { offsetHeight, offsetWidth } = element; + + newX = -dx + offsetWidth / 2; + newY = -dy + offsetHeight / 2; + } else { + newX = x; + newY = y; + } + + const [nextX, nextY] = multiplyMatrixAndPoint( matrix, - [offsetWidth / 2, offsetHeight / 2, 0, 1] + [newX, newY, 0, 1] ); - helper(center).css( - { transform: `translate(${x + offsetLeft}px, ${y + offsetTop}px)` } - ); + helper(handle).css({ + transform: `translate(${nextX + offsetLeft}px, ${nextY + offsetTop}px)` + }); + + center.isShifted = pin; } fitControlsToSize() { diff --git a/src/js/core/transform/Transformable.js b/src/js/core/transform/Transformable.js index d08ca9a..a26d053 100644 --- a/src/js/core/transform/Transformable.js +++ b/src/js/core/transform/Transformable.js @@ -722,7 +722,6 @@ export default class Transformable extends SubjectModel { } ].find((({ condition }) => condition)) || {}; - storage.doResize = false; storage.doDrag = false; storage.doRotate = false; @@ -1196,6 +1195,14 @@ export default class Transformable extends SubjectModel { this._processControlsRotate({ radians: delta }); } + setCenterPoint() { + throw Error(`'setCenterPoint()' method not implemented`); + } + + resetCenterPoint() { + this.setCenterPoint({ dx: 0, dy: 0 }, false); + } + get controls() { return this.storage.wrapper; } diff --git a/src/js/core/transform/svg/DraggableSVG.js b/src/js/core/transform/svg/DraggableSVG.js index 9b05c7f..6720683 100644 --- a/src/js/core/transform/svg/DraggableSVG.js +++ b/src/js/core/transform/svg/DraggableSVG.js @@ -439,15 +439,18 @@ export default class DraggableSVG extends Transformable { } = elementData; const getScale = (distX, distY) => { + const actualBoxWidth = boxWidth || 1; + const actualBoxHeight = boxHeight || 1; + const ratio = doW || (!doW && !doH) - ? (boxWidth + distX) / boxWidth - : (boxHeight + distY) / boxHeight; + ? (actualBoxWidth + distX) / actualBoxWidth + : (actualBoxHeight + distY) / actualBoxHeight; - const newWidth = proportions ? boxWidth * ratio : boxWidth + distX, - newHeight = proportions ? boxHeight * ratio : boxHeight + distY; + const newWidth = proportions ? actualBoxWidth * ratio : actualBoxWidth + distX, + newHeight = proportions ? actualBoxHeight * ratio : actualBoxHeight + distY; - const scaleX = newWidth / boxWidth, - scaleY = newHeight / boxHeight; + const scaleX = newWidth / actualBoxWidth, + scaleY = newHeight / actualBoxHeight; return [scaleX, scaleY, newWidth, newHeight]; }; @@ -1049,15 +1052,18 @@ export default class DraggableSVG extends Transformable { } = elementData; const getScale = (distX, distY) => { + const actualBoxWidth = boxWidth || 1; + const actualBoxHeight = boxHeight || 1; + const ratio = doW || (!doW && !doH) - ? (boxWidth + distX) / boxWidth - : (boxHeight + distY) / boxHeight; + ? (actualBoxWidth + distX) / actualBoxWidth + : (actualBoxHeight + distY) / actualBoxHeight; - const newWidth = proportions ? boxWidth * ratio : boxWidth + distX, - newHeight = proportions ? boxHeight * ratio : boxHeight + distY; + const newWidth = proportions ? actualBoxWidth * ratio : actualBoxWidth + distX, + newHeight = proportions ? actualBoxHeight * ratio : actualBoxHeight + distY; - const scaleX = newWidth / boxWidth, - scaleY = newHeight / boxHeight; + const scaleX = newWidth / actualBoxWidth, + scaleY = newHeight / actualBoxHeight; return [scaleX, scaleY, newWidth, newHeight]; }; @@ -1229,7 +1235,7 @@ export default class DraggableSVG extends Transformable { }); } - resetCenterPoint() { + setCenterPoint({ x, y, dx, dy } = {}, pin = true) { const { elements, storage: { @@ -1246,32 +1252,44 @@ export default class DraggableSVG extends Transformable { } } = this; - if (!center || !handle || !radius) return; + const isRelative = isDef(dx) && isDef(dy), + isAbsolute = isDef(x) && isDef(y); - const { x: bx, y: by, width, height } = this._getBBox(); - - const hW = width / 2, - hH = height / 2; + if (!center || !handle || !radius || !(isRelative || isAbsolute)) return; const controlsTransformMatrix = getTransformToElement(controls, controls.parentNode).inverse(); - const nextTransform = isGrouped ? controlsTransformMatrix : controlsTransformMatrix.multiply(getTransformToElement(elements[0], container)); - const { x, y } = pointTo( + let newX, newY; + + if (isRelative) { + const { x: bx, y: by, width, height } = this._getBBox(); + + const hW = width / 2, + hH = height / 2; + + newX = bx + hW + dx; + newY = by + hH + dy; + } else { + newX = x; + newY = y; + } + + const { x: nextX, y: nextY } = pointTo( nextTransform, - bx + hW, - by + hH + newX, + newY ); - handle.cx.baseVal.value = x; - handle.cy.baseVal.value = y; + handle.cx.baseVal.value = nextX; + handle.cy.baseVal.value = nextY; - radius.x2.baseVal.value = x; - radius.y2.baseVal.value = y; + radius.x2.baseVal.value = nextX; + radius.y2.baseVal.value = nextY; - center.isShifted = false; + center.isShifted = pin; } fitControlsToSize() { diff --git a/test/subjx.test.js b/test/subjx.test.js index 01fb47f..cf27e7f 100644 --- a/test/subjx.test.js +++ b/test/subjx.test.js @@ -358,8 +358,8 @@ describe('Test subjx "drag" method', () => { expect(() => { draggable.fitControlsToSize(); - draggable.resetCenterPoint(); draggable.getBoundingRect(); + draggable.setCenterPoint(); ['t', 'b', 'l', 'b', 'r', 'v', 'h'].map(align => draggable.applyAlignment(align)); }).not.toThrow(); }); @@ -511,8 +511,8 @@ describe('Test svg subjx "drag" method', () => { expect(() => { draggable.fitControlsToSize(); - draggable.resetCenterPoint(); draggable.getBoundingRect(svgElement); + draggable.setCenterPoint(); ['t', 'b', 'l', 'b', 'r', 'v', 'h'].map((align) => draggable.applyAlignment(align)); }).not.toThrow(); });