UNPKG

@inweb/viewer-visualize

Version:

JavaScript library for rendering CAD and BIM files in a browser using VisualizeJS

223 lines (199 loc) 7.67 kB
/////////////////////////////////////////////////////////////////////////////// // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance"). // All rights reserved. // // This software and its documentation and related materials are owned by // the Alliance. The software may only be incorporated into application // programs owned by members of the Alliance, subject to a signed // Membership Agreement and Supplemental Software License Agreement with the // Alliance. The structure and organization of this software are the valuable // trade secrets of the Alliance and its suppliers. The software is also // protected by copyright law and international treaty provisions. Application // programs incorporating this software must include the following statement // with their copyright notices: // // This application incorporates Open Design Alliance software pursuant to a // license agreement with Open Design Alliance. // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance. // All rights reserved. // // By use of this software, its documentation or related materials, you // acknowledge and accept the above terms. /////////////////////////////////////////////////////////////////////////////// // ===================== AI-CODE-FILE ====================== // Source: Claude Sonnet 4.5 // Date: 2025-10-07 // Reviewer: vitaly.ivanov@opendesign.com // Issue: CLOUD-5851 // Notes: Originally AI-generated, modified manually // ========================================================= interface JoyStickStatus { x: number; y: number; global: any; } export class OdJoyStickDragger { private onMouseDown: (event?: any) => void; private onMouseMove: (event: any) => void; private onMouseUp: (event?: any) => void; private drawExternal: () => void; private drawInternal: () => void; private canvas: HTMLCanvasElement; private onResize: () => void; private hasEventListeners: boolean = false; private container: HTMLElement; constructor( global: any, container: HTMLElement, callback: (status: JoyStickStatus) => void, canvasElement?: HTMLCanvasElement ) { const internalLineWidth = 2; const internalStrokeColor = "#003300"; const externalLineWidth = 2; const externalStrokeColor = "#35436E"; this.container = container; this.container.style.touchAction = "none"; this.canvas = document.createElement("canvas"); this.canvas.id = "odJoyStickCanvas"; this.canvas.width = 200; this.canvas.height = 200; this.container.appendChild(this.canvas); const context = this.canvas.getContext("2d")!; let pressed = 0; const circumference = 2 * Math.PI; const internalRadius = (this.canvas.width - (this.canvas.width / 2 + 10)) / 2; const maxMoveStick = internalRadius + 5; const externalRadius = internalRadius + 30; const centerX = this.canvas.width / 2; const centerY = this.canvas.height / 2; let movedX = centerX; let movedY = centerY; this.onMouseDown = () => { event.preventDefault(); pressed = 1; }; this.onMouseMove = (event) => { event.preventDefault(); if (pressed === 1) { movedX = event.pageX; movedY = event.pageY; if (this.canvas.offsetParent && (this.canvas.offsetParent as HTMLElement).tagName.toUpperCase() === "BODY") { movedX -= this.canvas.offsetLeft; movedY -= this.canvas.offsetTop; } else if (this.canvas.offsetParent) { movedX -= (this.canvas.offsetParent as HTMLElement).offsetLeft; movedY -= (this.canvas.offsetParent as HTMLElement).offsetTop; } context.clearRect(0, 0, this.canvas.width, this.canvas.height); this.drawExternal(); this.drawInternal(); callback({ x: 100 * ((movedX - centerX) / maxMoveStick), y: 100 * ((movedY - centerY) / maxMoveStick) * -1, global, }); } }; this.onMouseUp = () => { event.preventDefault(); pressed = 0; movedX = centerX; movedY = centerY; context.clearRect(0, 0, this.canvas.width, this.canvas.height); this.drawExternal(); this.drawInternal(); callback({ x: 100 * ((movedX - centerX) / maxMoveStick), y: 100 * ((movedY - centerY) / maxMoveStick) * -1, global, }); }; this.drawExternal = () => { context.beginPath(); context.arc(centerX, centerY, externalRadius, 0, circumference, false); context.lineWidth = externalLineWidth; context.strokeStyle = externalStrokeColor; context.globalAlpha = 0.5; context.stroke(); }; this.drawInternal = () => { context.beginPath(); if (movedX < internalRadius) { movedX = maxMoveStick; } if (movedX + internalRadius > this.canvas.width) { movedX = this.canvas.width - maxMoveStick; } if (movedY < internalRadius) { movedY = maxMoveStick; } if (movedY + internalRadius > this.canvas.height) { movedY = this.canvas.height - maxMoveStick; } context.arc(movedX, movedY, internalRadius, 0, circumference, false); context.fillStyle = externalStrokeColor; context.lineWidth = internalLineWidth; context.strokeStyle = internalStrokeColor; context.globalAlpha = 0.5; context.fill(); context.stroke(); }; const addEventListeners = () => { if (!this.hasEventListeners) { this.canvas.addEventListener("pointerdown", this.onMouseDown, false); document.addEventListener("pointermove", this.onMouseMove, false); document.addEventListener("pointerup", this.onMouseUp, false); this.hasEventListeners = true; } }; const removeEventListeners = () => { if (this.hasEventListeners) { this.canvas.removeEventListener("pointerdown", this.onMouseDown, false); document.removeEventListener("pointermove", this.onMouseMove, false); document.removeEventListener("pointerup", this.onMouseUp, false); this.hasEventListeners = false; } }; const updateContainerPosition = () => { if (canvasElement) { const rect = canvasElement.getBoundingClientRect(); this.container.style.top = `${rect.height - 200}px`; this.container.style.left = `${rect.left}px`; this.container.style.width = `200px`; this.container.style.height = `200px`; } }; const updateVisibility = () => { const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); const isNarrowScreen = window.innerWidth < 1024; const shouldShow = isMobile || isNarrowScreen; if (shouldShow) { this.container.style.display = "block"; addEventListeners(); } else { this.container.style.display = "none"; removeEventListeners(); } }; this.onResize = () => { updateVisibility(); setTimeout(updateContainerPosition, 500); }; updateVisibility(); updateContainerPosition(); window.addEventListener("resize", this.onResize, false); this.drawExternal(); this.drawInternal(); } cleanup(): void { window.removeEventListener("resize", this.onResize, false); if (this.hasEventListeners) { this.canvas.removeEventListener("pointerdown", this.onMouseDown, false); document.removeEventListener("pointermove", this.onMouseMove, false); document.removeEventListener("pointerup", this.onMouseUp, false); this.hasEventListeners = false; } this.canvas.remove(); } }