UNPKG

odious

Version:

Odious fundamentally revolutionizes the software development paradigm by seamlessly integrating deployment considerations into the development process, thus empowering developers of all skill levels to create and deploy applications with unprecedented eas

109 lines (81 loc) 3.86 kB
export default class Pannable { sceneComponent; targetElement; #startPanX = 0; #startPanY = 0; #startMousePos = { x: 0, y: 0 }; #isPanning = false; constructor(sceneComponent) { this.sceneComponent = sceneComponent; // this.targetElement = sceneComponent.container; this.targetElement = this.sceneComponent.shadowRoot.querySelector(".content"); // this.targetElement.style.position = 'relative'; this.onMouseDown = this.onMouseDown.bind(this); this.onMouseMove = this.onMouseMove.bind(this); this.onMouseUp = this.onMouseUp.bind(this); this.onWheel = this.onWheel.bind(this); } start() { //console.log("Pannable start!", this.targetElement); this.sceneComponent.addEventListener("wheel", this.onWheel, { passive: false, }); this.sceneComponent.addEventListener("mousedown", this.onMouseDown); window.addEventListener("mousemove", this.onMouseMove); window.addEventListener("mouseup", this.onMouseUp); this.sceneComponent.panX.subscribe(()=>this.updateTransform()); this.sceneComponent.panY.subscribe(()=>this.updateTransform()); this.sceneComponent.scale.subscribe(()=>this.updateTransform()); return () => this.stop(); } stop() { this.targetElement.removeEventListener("wheel", this.onWheel, { passive: false, }); this.targetElement.removeEventListener("mousedown", this.onMouseDown); window.removeEventListener("mousemove", this.onMouseMove); window.removeEventListener("mouseup", this.onMouseUp); } // TODO: DO THIS VIA SIGNAL SUBSCRIPTION updateTransform() { this.targetElement.style.transform = `translate(${this.sceneComponent.panX.value}px, ${this.sceneComponent.panY.value}px) scale(${this.sceneComponent.scale.value})`; //NOTE: rotateY(0deg) rotateY(0deg) prevents blurring in certain conditions } onMouseDown(event) { //console.log("Pannable onMouseDown!", event.target); if (event.originalTarget !== this.sceneComponent) return; // const target = event .composedPath() .find((o) => o.tagName === "BUTTON" || o === this.host); // if (target !== this.host) return; this.#isPanning = true; this.#startMousePos = { x: event.clientX, y: event.clientY }; this.#startPanX = this.sceneComponent.panX.value; this.#startPanY = this.sceneComponent.panY.value; event.preventDefault(); } onMouseMove(event) { if (this.#isPanning) { this.sceneComponent.panX.value = this.#startPanX + (event.clientX - this.#startMousePos.x); this.sceneComponent.panY.value = this.#startPanY + (event.clientY - this.#startMousePos.y); // this.updateTransform(); } } onMouseUp(event) { this.#isPanning = false; } onWheel(event) { //console.log("Pannable onWheel Target", event.originalTarget.tagName, event.target.tagName); let allow = true; if (event.originalTarget !== this.sceneComponent) allow = false; if (event.target.tagName == 'X-WINDOW') allow = true; // overturn verdict; try{ // Avoid Uncaught Error: Permission denied to access property "tagName" if (event.originalTarget.tagName == 'line') allow = true; // overturn verdict; }catch(e){} if(!allow) return; const deltaScale = event.deltaY > 0 ? 0.9 : 1.1; this.sceneComponent.scale.value *= deltaScale; // IMPORTANT: offsetX and offsetY must be calculated based on the sceneComponent AND NOT targetElement const rect = this.sceneComponent.getBoundingClientRect(); const offsetX = event.clientX - rect.left; const offsetY = event.clientY - rect.top; this.sceneComponent.panX.value = offsetX * (1 - deltaScale) + deltaScale * this.sceneComponent.panX.value; this.sceneComponent.panY.value = offsetY * (1 - deltaScale) + deltaScale * this.sceneComponent.panY.value; // this.updateTransform(); event.preventDefault(); } }