web-component-designer
web-component-designer copied to clipboard
Draw Resize Overlay around transformed objects
Check how we could draw the resize/selection overlay around a rotated object (or otherwise transformed)
- [x] try to draw the lines without 1px x 1px helper div... use matrix transform. Consider transform origin in tx and ty. Remove helper element's 1px/1px cornerDiv if successful.
- [x] Consider scale factor > done with 9e44aeb8a29320713af3075482de64e2b7e0e999
- [ ] Redraw while scolling canvas
- [x] overlay doesn't fit perfectly in all rotation angles > Fixed with 3dc7c24ec688e655212a2798cdfffca4dd5b1e79
- [x] When an object is dragged into another, the overlay is drawn in the wrong place
- [x] Restore mouse extension over after placement > 2227ac9517054441939d0bd30888e3cd5db7bb6f
How does the helperElement / cornerDiv variant work?
A clone of the actual element for which the vertices are to be determined is also passed to the method. The visibility is set to hidden for this element. At the same time the current transform is saved and reset. Then the clone is added to the DOM (helperElement) located in designerCanvas.
The Transform Origin of the cloned element without transformation is saved. Then the cloned element is destroyed.
Calculate corner points of the untransformed element and store them in an object array
const cornerPoints: IPoint[] = [ { x: originalRect.x + cloneBoundingRect.x - untransformedCornerPointsOffset, y: originalRect.y + cloneBoundingRect.y - untransformedCornerPointsOffset }, { x: originalRect.x + cloneBoundingRect.x + cloneBoundingRect.width + untransformedCornerPointsOffset, y: originalRect.y + cloneBoundingRect.y - untransformedCornerPointsOffset }, { x: originalRect.x + cloneBoundingRect.x - untransformedCornerPointsOffset, y: originalRect.y + cloneBoundingRect.y + cloneBoundingRect.height + untransformedCornerPointsOffset }, { x: originalRect.x + cloneBoundingRect.x + cloneBoundingRect.width + untransformedCornerPointsOffset, y: originalRect.y + cloneBoundingRect.y + cloneBoundingRect.height + untransformedCornerPointsOffset } ]
Is the original rect needed at all? The element is located in the DesignerCanvas. X and y apparently always return 0 anyway.
Remove helperElements‘s children
let cornerPointsTranformOrigins = new Array(4);
Calculate transform origin of the corner points so that they are congruent with the transform origin of the element.
const transformOrigin = (parseInt(transformOriginBackup.split(' ')[0]) + untransformedCornerPointsOffset).toString() + ' ' + (parseInt(transformOriginBackup.split(' ')[1]) + untransformedCornerPointsOffset).toString(); cornerPointsTranformOrigins[0] = (parseInt(transformOrigin.split(' ')[0])).toString() + ' ' + (parseInt(transformOrigin.split(' ')[1])).toString(); cornerPointsTranformOrigins[1] = (cornerPoints[0].x - cornerPoints[1].x + parseInt(transformOrigin.split(' ')[0])).toString() + ' ' + (parseInt(transformOrigin.split(' ')[1])).toString(); cornerPointsTranformOrigins[2] = (parseInt(transformOrigin.split(' ')[0])).toString() + ' ' + (cornerPoints[0].y - cornerPoints[2].y + parseInt(transformOrigin.split(' ')[1])).toString(); cornerPointsTranformOrigins[3] = (cornerPoints[0].x - cornerPoints[1].x + parseInt(transformOrigin.split(' ')[0])).toString() + ' ' + (cornerPoints[0].y - cornerPoints[2].y + parseInt(transformOrigin.split(' ')[1])).toString();
Create 1px/1px corner divs
const cornerDivs: HTMLDivElement[] = []; let element: HTMLDivElement; for (let i = 0; i < cornerPointsTranformOrigins.length; i++) { element = document.createElement('div'); element.style.visibility = 'hidden'; element.style.position = 'absolute'; element.style.width = "1px"; element.style.height = "1px"; element.style.top = cornerPoints[i].y.toString() + 'px'; element.style.left = cornerPoints[i].x.toString() + 'px'; element.style.transformOrigin = cornerPointsTranformOrigins[i].split(' ')[0] + 'px' + ' ' + cornerPointsTranformOrigins[i].split(' ')[1] + 'px'; cornerDivs.push(helperElement.appendChild(element)); }
**Apply saved transform to the corner divs and calc their x and y values **
let transformedCornerPoints: IPoint3D[] = []; for (let i = 0; i < cornerDivs.length; i++) { //let transformedCornerDiv: HTMLElement; let transformedCornerPoint: IPoint3D = { x: null, y: null, z: null }; //transformedCornerDiv = applyMatrixToElement((<HTMLElement>this.extendedItem.element).style.transform, cornerDivs[i]); cornerDivs[i].style.transform = transformBackup; //transformedCornerDiv = applyMatrixToElement((<HTMLElement>this.extendedItem.element).style.transform, cornerDivs[i]); transformedCornerPoint.x = designerCanvas.getNormalizedElementCoordinates(cornerDivs[i]).x; transformedCornerPoint.y = designerCanvas.getNormalizedElementCoordinates(cornerDivs[i]).y; transformedCornerPoint.z = 0; transformedCornerPoints.push(transformedCornerPoint); } return transformedCornerPoints;
This is the new method without cornerDiv!
- Hide clone
- Reset transfrom
- Append clone to DOM (designerCanvas helperElement)
- Destroy clone
Calculate the corner points of the untransformed clone
` const appendedCloneWithoutTranformCornerDOMPoints: DOMPoint[] = []; appendedCloneWithoutTranformCornerDOMPoints[topleft] = DOMPoint.fromPoint( { x: appendedCloneWithoutTranformRect.x - untransformedCornerPointsOffset, y: appendedCloneWithoutTranformRect.y - untransformedCornerPointsOffset } )
...
helperElement.replaceChildren(); `
Calculate the transform origin related to the canvas
const transformOriginRelatedToCanvas: DOMPointReadOnly = DOMPointReadOnly.fromPoint( { x: appendedCloneWithoutTranformRect.x + parseInt(getComputedStyle(<HTMLElement>originalElement).transformOrigin.split(' ')[0]), y: appendedCloneWithoutTranformRect.y + parseInt(getComputedStyle(<HTMLElement>originalElement).transformOrigin.split(' ')[1]), z: 0, w: 0 } )
Calcluate the vectors (𝑻𝑶𝑷𝟎) ⃗, (𝑻𝑶𝑷𝟏) ⃗, (𝑻𝑶𝑷𝟐) ⃗, (𝑻𝑶𝑷𝟑) ⃗
let top0 = new DOMPoint(-(transformOriginRelatedToCanvas.x - appendedCloneWithoutTranformCornerDOMPoints[topleft].x), -(transformOriginRelatedToCanvas.y - appendedCloneWithoutTranformCornerDOMPoints[topleft].y)); let top1 = new DOMPoint(-(transformOriginRelatedToCanvas.x - appendedCloneWithoutTranformCornerDOMPoints[topright].x), -(transformOriginRelatedToCanvas.y - appendedCloneWithoutTranformCornerDOMPoints[topright].y)); let top2 = new DOMPoint(-(transformOriginRelatedToCanvas.x - appendedCloneWithoutTranformCornerDOMPoints[bottomleft].x), -(transformOriginRelatedToCanvas.y - appendedCloneWithoutTranformCornerDOMPoints[bottomleft].y)); let top3 = new DOMPoint(-(transformOriginRelatedToCanvas.x - appendedCloneWithoutTranformCornerDOMPoints[bottomright].x), -(transformOriginRelatedToCanvas.y - appendedCloneWithoutTranformCornerDOMPoints[bottomright].y));
Apply original element‘s transformation matrix to each point
let top0Transformed = top0.matrixTransform(originalElementMatrix); let top1Transformed = top1.matrixTransform(originalElementMatrix); let top2Transformed = top2.matrixTransform(originalElementMatrix); let top3Transformed = top3.matrixTransform(originalElementMatrix);
Calcluate the vectors (𝑪𝑶𝑷𝟎′) ⃗, (𝑪𝑶𝑷𝟏′) ⃗, (𝑪𝑶𝑷𝟐′) ⃗, (𝑪𝑶𝑷𝟑′) ⃗
let transformedCornerPoints: DOMPoint[] = []; transformedCornerPoints[0] = new DOMPoint(transformOriginRelatedToCanvas.x + top0Transformed.x, transformOriginRelatedToCanvas.y + top0Transformed.y); transformedCornerPoints[1] = new DOMPoint(transformOriginRelatedToCanvas.x + top1Transformed.x, transformOriginRelatedToCanvas.y + top1Transformed.y); transformedCornerPoints[2] = new DOMPoint(transformOriginRelatedToCanvas.x + top2Transformed.x, transformOriginRelatedToCanvas.y + top2Transformed.y); transformedCornerPoints[3] = new DOMPoint(transformOriginRelatedToCanvas.x + top3Transformed.x, transformOriginRelatedToCanvas.y + top3Transformed.y);
Get original element’s transform origin relative to canvas and add available vectors to get the transformed corner points
getDesignerCanvasNormalizedTransformedOrigin()
- Apply resulting transformation (multiplied self by all ancestors) to appendedClone.
- Calc transform origin position related to designer canvas
- Calc the element’s transform origin corner point vectors of the untransformed appendedClone
- Apply the resulting transformation to all corner point vectors
- Add these transformed vectors to original element’s transform origin that is related to the designer canvas
https://user-images.githubusercontent.com/5232626/201771139-3e0747e5-bd11-4ded-9e05-266a0360bf4b.mp4