web-component-designer icon indicating copy to clipboard operation
web-component-designer copied to clipboard

Add support for transformations and transformed resizing

Open jogibear9988 opened this issue 3 years ago • 4 comments

As a user of the designer I want be able to transform the elements. I'd like to be able to rotate & skew the elements. During rotation the current angle should be displayed. Maybe also resizing and movement via transform should be possible, but we need to decide how we differentiate it from the normal resize and move.

Also a transformed element should be resizable and movable after a transformation has been applied via the standard logic (which is not possible at the moment). Also the resizing in all directions should work, at the moment only east south and south-east is working.

When an element is transformed, it would be nice if in the selection overlay the border of the element is drawn in it's transformend shape, and not only a rectangular completely around.

  • [x] #146
  • [x] Use elements transform origin for rotation instead of hard coded center.
  • [x] Resizing of rotated element
  • [x] Implement resizing in all directions
  • [x] Pointer move event is wrongly triggered on a rotated element after pointer down
  • [x] A rotated element changes width undesirably at the start of resizing
  • [ ] #153
  • [x] #181
  • [ ] Automatically adjust overlay when margin/padding is set on element.
  • [x] Make snaplines work even with transformed elements > it works
  • [x] #180
  • [x] #90
  • [ ] #101
  • [x] #105
  • [x] Placement jumps after west and north resizing
  • [x] Show the transform origin correctly after a transformation
  • [x] #147
  • [x] #149
  • [x] South west resize circle must be in the foreground. Try to resize new div. > 0bd83f16e6546f2b2b8a4c5b5b649bbb58263484
  • [ ] #151
  • [ ] #152
  • [x] #155
  • [x] #160
  • [x] #174
  • [ ] #187
  • [x] #188
  • [x] #192

jogibear9988 avatar Jan 28 '22 22:01 jogibear9988

Info:

https://stackoverflow.com/questions/20366892/resizing-handles-on-a-rotated-element

jogibear9988 avatar Feb 22 '22 13:02 jogibear9988

What does the height of a rotated element in the Wix Editor refer to?

image

7evenk avatar Sep 08 '22 07:09 7evenk

Freeze transform origin during resizing

image

If the Transform origin is set absolute, it does not need to be moved at all during resizing Wow⚡

At the beginning of the resizing, the transform origin must be saved first.

getComputedStyle($0).transformOrigin '100px 50px‘ ⚡ Even if the transform origin is specified via %, getComputedStyle() returns px.

https://jsfiddle.net/sy0fuwL3/1/

https://user-images.githubusercontent.com/5232626/195019847-56ad84bc-689b-45eb-a16d-519109660c99.mp4

Resizing transformed elements works better than Wix now. There is no wiggle. The next step is to set the transform origin correctly for transformed elements after resizing is complete.

Set initial transform origin

let cg = this.extendedItem.openGroup("Resize Elements");         this.extendedItem.setStyle('width', (<HTMLElement>this.extendedItem.element).style.width);         this.extendedItem.setStyle('height', (<HTMLElement>this.extendedItem.element).style.height);         (<HTMLElement>this.extendedItem.element).style.transformOrigin = this._initialTransformOrigins[0];

https://user-images.githubusercontent.com/5232626/195020815-6c0a8e0d-e3bd-43fd-8185-7613c07fdb51.mp4

Restoring the original transform origins is not the solution either, since this undoes the setting of the transform trigins during the move.

Doesn't the position have to be changed via top left or translate?

Restore transform origin and translate after resizing

image

Step 1: getBoundingClientRect from the transformed element

image

let testElement = document.getElementById("testElement"); let resizedTestElement = document.getElementById("resizedTestElement"); let initialTransformOrigin = testElement.style.transformOrigin; resizedTestElement.style.transformOrigin = getComputedStyle(testElement).transformOrigin; debugger; let rectOfResizedElementWithFrozenTransformOrigin = resizedTestElement.getBoundingClientRect()

image

Step 2: Restore original transformation origin & getBoundingClientRect

image

let testElement = document.getElementById("testElement"); let resizedTestElement = document.getElementById("resizedTestElement"); let initialTransformOrigin = testElement.style.transformOrigin; resizedTestElement.style.transformOrigin = getComputedStyle(testElement).transformOrigin; debugger; let rectOfResizedElementWithFrozenTransformOrigin = resizedTestElement.getBoundingClientRect() resizedTestElement.style.transformOrigin = initialTransformOrigin; let rectOfResizedElementWithInitialTransformOrigin = resizedTestElement.getBoundingClientRect();

image

Step 3: Calc difference of getBoundingClientRect

image

image

image

https://jsfiddle.net/sy0fuwL3/8/

Step 4 (1): Determine absolute displacement of transform origin

image

🤔 How can the difference be determined? It cannot be calculated on the basis of the two transform origins, since the transform origins are related to the element.

image

https://jsfiddle.net/sy0fuwL3/8/

Step 4 (2): Determine absolute displacement of transform origin

image

image

❓ How do we get P2 absolute? Only P1 and the frozen transform origin P3 are known.

image

https://jsfiddle.net/sy0fuwL3/11/

Step 4 (3): Determine absolute displacement of transform origin

image

https://jsfiddle.net/sy0fuwL3/12/ https://jsfiddle.net/sy0fuwL3/15/

Step 5: Determine Δx and Δy for translate

image

`let deltaX = p4Abs.x - p1Abs.x; let deltaY = p4Abs.y - p1Abs.y;

resizedTestElement.style.transform = new DOMMatrix(getComputedStyle(resizedTestElement).transform).translate(deltaX, deltaY) `

https://jsfiddle.net/sy0fuwL3/13/

7evenk avatar Oct 11 '22 09:10 7evenk

image

image

export function getByParentsTransformedPointRelatedToCanvas(element: HTMLElement, point: DOMPoint, designerCanvas: IDesignerCanvas) {
  const canvas = element.closest('#node-projects-designer-canvas-canvas');
  let actualElement: HTMLElement = element;
  let parentElementTransformOriginToPointVectorTransformed: DOMPointReadOnly;
  let byParentTransformedPointRelatedToCanvas: DOMPointReadOnly;
  while (actualElement != canvas) {
    const parentElement = <HTMLElement>getParentElementIncludingSlots(actualElement);
    const parentElementTransformOrigin: DOMPointReadOnly = new DOMPointReadOnly(
      getElementsWindowOffsetWithoutSelfAndParentTransformations(parentElement).offsetLeft - designerCanvas.outerRect.x + parseInt(getComputedStyle(<HTMLElement>parentElement).transformOrigin.split(' ')[0]) - extractTranslationFromDOMMatrix(new DOMMatrix(element.style.transform)).x,
      getElementsWindowOffsetWithoutSelfAndParentTransformations(parentElement).offsetTop - designerCanvas.outerRect.y + parseInt(getComputedStyle(<HTMLElement>parentElement).transformOrigin.split(' ')[1]) - extractTranslationFromDOMMatrix(new DOMMatrix(element.style.transform)).y,
    )
    const parentElementTransformOriginToPointVector: DOMPointReadOnly = new DOMPointReadOnly(
      -parentElementTransformOrigin.x + (element == actualElement ?  point.x : byParentTransformedPointRelatedToCanvas.x),
      -parentElementTransformOrigin.y + (element == actualElement ?  point.y : byParentTransformedPointRelatedToCanvas.y)
    )

    parentElementTransformOriginToPointVectorTransformed = parentElementTransformOriginToPointVector.matrixTransform(new DOMMatrix(getComputedStyle((<HTMLElement>parentElement)).transform));
    byParentTransformedPointRelatedToCanvas = new DOMPoint(parentElementTransformOrigin.x + parentElementTransformOriginToPointVectorTransformed.x, parentElementTransformOrigin.y + parentElementTransformOriginToPointVectorTransformed.y);
    actualElement = parentElement;
  }

  return byParentTransformedPointRelatedToCanvas;
}
  const designerCanvasNormalizedTransformOrigin = getByParentsTransformedPointRelatedToCanvas(element, new DOMPoint(getElementsWindowOffsetWithoutSelfAndParentTransformations(element).offsetLeft - designerCanvas.outerRect.left + parseInt(getComputedStyle(<HTMLElement>element).transformOrigin.split(' ')[0]), getElementsWindowOffsetWithoutSelfAndParentTransformations(element).offsetTop - designerCanvas.outerRect.top + parseInt(getComputedStyle(<HTMLElement>element).transformOrigin.split(' ')[1])), designerCanvas);

7evenk avatar Dec 02 '22 08:12 7evenk