import { RESIZABLE_SECTIONS } from './../constants/BuilderConstants'; import { COMMON_DOTS_STYLE, DOTS, SECTION_DOTS, VIDEO_DOTS, } from './../constants/DragAndResize'; import { CrudAttribute } from './../cruds/CrudAttribute'; export class Resize { private _parentRect!: DOMRect; dotsElements: HTMLElement[] = []; isSection: boolean = false; minWidth: number = 5; minHeight: number = 5; constructor(private boxWrapper: HTMLElement) { this.isSection = RESIZABLE_SECTIONS.includes(boxWrapper.dataset['type']!); this._createDots(); } removeDots() { this.dotsElements.forEach((d) => { d.onmousedown = undefined!; d.remove(); }); } onMouseDown( event: MouseEvent, boxWrapper: HTMLElement, config: { left: boolean; top: boolean; xR: boolean; yR: boolean; } = { left: false, top: false, xR: false, yR: false, } ) { const { left, top, xR, yR } = config; this._parentRect = boxWrapper.parentElement!.getBoundingClientRect(); const elementRect = boxWrapper.getBoundingClientRect(); const boxRect = boxWrapper.firstElementChild!.getBoundingClientRect(); const initX = boxWrapper.offsetLeft; const initY = boxWrapper.offsetTop; const box: HTMLElement = ( (this.isSection ? boxWrapper : boxWrapper.firstElementChild) ); const initW = box.offsetWidth; const initH = box.offsetHeight; const mousePressX = event.clientX; const mousePressY = event.clientY; let saveW: number = initW, saveH: number = initH, saveX: number = initX, saveY: number = initY; const intitRotate = this.getCurrentRotation(boxWrapper); const initRadians = (intitRotate * Math.PI) / 180; const cosFraction = Math.cos(initRadians); const sinFraction = Math.sin(initRadians); window.onmousemove = (e: MouseEvent) => { let wDiff = e.clientX - mousePressX; let hDiff = e.clientY - mousePressY; let rotatedWDiff = cosFraction * wDiff + sinFraction * hDiff; let rotatedHDiff = cosFraction * hDiff - sinFraction * wDiff; let newW = initW, newH = initH, newX = initX, newY = initY; if (xR) { if (left) { newW = initW - rotatedWDiff; if (newW < this.minWidth) { newW = this.minWidth; rotatedWDiff = initW - this.minWidth; } } else { newW = initW + rotatedWDiff; if (newW < this.minWidth) { newW = this.minWidth; rotatedWDiff = this.minWidth - initW; } } newX += 0.5 * rotatedWDiff * cosFraction; newY += 0.5 * rotatedWDiff * sinFraction; } if (yR) { if (top) { newH = initH - rotatedHDiff; if (newH < this.minHeight) { newH = this.minHeight; rotatedHDiff = initH - this.minHeight; } } else { newH = initH + rotatedHDiff; if (newH < this.minHeight) { newH = this.minHeight; rotatedHDiff = this.minHeight - initH; } } newX -= 0.5 * rotatedHDiff * sinFraction; newY += 0.5 * rotatedHDiff * cosFraction; } saveW = newW; saveH = newH; saveX = newX; saveY = newY; this._resize(box, newW, newH); !this.isSection && this._repositionElement(boxWrapper, newX, newY); }; window.onmouseup = async (e: MouseEvent) => { e.stopPropagation(); e.preventDefault(); window.onmousemove = undefined!; const header = { parent: box.dataset['_id'], type: 'style', active: true, }; let payload = [ { ...header, key: 'width', value: `${saveW}px`, }, { ...header, key: 'height', value: `${saveH}px`, }, ]; if (!RESIZABLE_SECTIONS.includes(boxWrapper.dataset['type']!)) { payload = [ ...payload, ...[ { ...header, key: 'left', value: `${saveX}px`, }, { ...header, key: 'top', value: `${saveY}px`, }, ], ]; } await CrudAttribute.saveAttributes(payload); }; } getCurrentRotation(element: HTMLElement) { const st = window.getComputedStyle(element, null); const tm = st.getPropertyValue('-webkit-transform') || st.getPropertyValue('-moz-transform') || st.getPropertyValue('-ms-transform') || st.getPropertyValue('-o-transform') || st.getPropertyValue('transform') || 'none'; if (tm != 'none') { let values = tm.split('(')[1].split(')')[0].split(','); let angle = Math.round( Math.atan2(Number(values[1]), Number(values[0])) * (180 / Math.PI) ); return angle < 0 ? angle + 360 : angle; } return 0; } onMouseDownRotate(event: MouseEvent, boxWrapper: HTMLElement) { this._parentRect = boxWrapper.parentElement!.getBoundingClientRect(); const elementRect = boxWrapper.getBoundingClientRect(); const boxRect = boxWrapper.firstElementChild!.getBoundingClientRect(); const arrowX = boxRect.left + boxRect.width / 2; const arrowY = boxRect.top + boxRect.height / 2; window.onmousemove = (e: MouseEvent) => { e.stopPropagation(); this._rotateHandler(e, boxWrapper, arrowX, arrowY); }; window.onmouseup = (e: MouseEvent) => { e.stopPropagation(); let angle = this._calculateAngle(e, boxWrapper, arrowX, arrowY); CrudAttribute.saveAttribute({ parent: boxWrapper.dataset['_id'], type: 'style', active: true, key: 'transform', value: `rotate(${angle}deg)`, }); window.onmousemove = undefined!; window.onmouseup = undefined!; }; } private _rotateHandler( event: MouseEvent, element: HTMLElement, arrowX: number, arrowY: number ) { const angle = Math.atan2(event.clientY - arrowY, event.clientX - arrowX) + Math.PI / 2; this._rotate(element, (angle * 180) / Math.PI + 50); } private _calculateAngle( event: MouseEvent, element: HTMLElement, arrowX: number, arrowY: number ) { console.log(':3'); const angle = Math.atan2(event.clientY - arrowY, event.clientX - arrowX) + Math.PI / 2; return (angle * 180) / Math.PI + 50; } private _resize(element: HTMLElement, w: number, h: number) { if (element.dataset['type'] === 'image') { element.parentElement!.style.width = `${w}px`; element.parentElement!.style.height = `${h}px`; } console.log(w, h); element.style.width = `${w}px`; element.style.height = `${h}px`; } private _repositionElement(element: HTMLElement, x: number, y: number) { element.style.left = `${x}px`; element.style.top = `${y}px`; } private _rotate(element: HTMLElement, deg: number) { element.style.transform = `rotate(${deg}deg`; } private _drag(e: MouseEvent | any) { if (e.target.className.indexOf('dot') > -1) return; let initX = this.boxWrapper.offsetLeft; let initY = this.boxWrapper.offsetTop; let mousePressX = e.clientX; let mousePressY = e.clientY; this._repositionElement( this.boxWrapper, initX + (e.clientX - mousePressX), initY + (e.clientY - mousePressY) ); } private _createDots() { const dotsJson = this.isSection ? SECTION_DOTS : this.boxWrapper.dataset['type'] === 'video' ? VIDEO_DOTS : DOTS; this.minHeight = this.boxWrapper.dataset['type'] === 'video' ? 100 : 5; this.minWidth = this.boxWrapper.dataset['type'] === 'video' ? 200 : 5; this.dotsElements = dotsJson.map((d: any) => { const dot = document.createElement('div'); const { styles } = d; dot.style.cssText = COMMON_DOTS_STYLE.trim(); Object.keys(styles).forEach((key) => { dot.style.setProperty(key, styles[key]); }); dot.dataset['dot'] = d.name; dot.dataset['selectable'] = 'true'; if (d.name === 'rotate-link') return dot; if (d.name === 'rotate') { dot.onmousedown = (e) => { this.onMouseDownRotate(e, this.boxWrapper); e.stopPropagation(); }; dot.onmouseover = (e) => { e.stopPropagation(); }; } else { dot.onmousedown = (e) => { this.onMouseDown(e, this.boxWrapper, d.config); e.stopPropagation(); }; dot.onmouseover = (e) => { e.stopPropagation(); }; } return dot; }); this.isSection || this.boxWrapper.dataset['type'] === 'video' ? this.dotsElements.forEach((d) => this.boxWrapper.appendChild(d)) : this.dotsElements.forEach((d) => this.boxWrapper.firstChild!.appendChild(d) ); this.boxWrapper.style.position = 'relative'; } }