UNPKG

@inweb/viewer-visualize

Version:

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

255 lines (204 loc) 7.63 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. /////////////////////////////////////////////////////////////////////////////// /* eslint-disable no-unused-vars */ import { CANVAS_EVENTS } from "@inweb/viewer-core"; import { Viewer } from "../../Viewer"; import { Point2d } from "./Geometry"; import { OdaGeAction } from "./OdaGeAction"; const CLICK_DELTA = 5; const INTERACTIVITY_FPS = 24; export class OdBaseDragger extends OdaGeAction { protected subject: Viewer; protected needInputText: boolean; protected mouseDownPosition: Point2d; protected autoSelect: boolean; protected onmessage: (event: any) => boolean; protected canvasEvents: string[]; protected isDragging: boolean; protected press: boolean; public name: string; constructor(subject: Viewer) { super(subject.visualizeJs); this.subject = subject; this.needInputText = false; this.mouseDownPosition = { x: 0, y: 0 }; this.autoSelect = false; this.onmessage = (event) => this.subject.emitEvent(event); this.canvasEvents = CANVAS_EVENTS; } public initialize(): void { this.canvasEvents = this.canvasEvents.filter((x) => typeof this[x] === "function"); this.canvasEvents.forEach((x) => (this[x] = this[x].bind(this))); this.canvasEvents.forEach((x) => this.subject.on(x, this[x])); this.getViewer().setEnableAutoSelect(!!this.autoSelect); } public dispose(): void { this.canvasEvents.forEach((x) => this.subject.off(x, this[x])); } protected relativeCoords(event: MouseEvent): Point2d { return { x: event.offsetX * window.devicePixelRatio, y: event.offsetY * window.devicePixelRatio }; } protected pointerdown(ev: PointerEvent): void { if (!ev.isPrimary || OdBaseDragger.isGestureActive) { return; } (ev.target as HTMLElement).setPointerCapture(ev.pointerId); const relCoord = this.relativeCoords(ev); this.isDragging = true; this.mouseDownPosition = { x: relCoord.x, y: relCoord.y }; this.start(relCoord.x, relCoord.y, ev.clientX, ev.clientY); this.subject.update(); } protected pointerup(ev: PointerEvent): void { if (OdBaseDragger.needSkipPointerUp) { return; } if (!ev.isPrimary) { return; } (ev.target as HTMLElement).releasePointerCapture(ev.pointerId); const relCoord = this.relativeCoords(ev); this.end(relCoord.x, relCoord.y, ev.clientX, ev.clientY); this.isDragging = false; this.subject.update(); } protected pointercancel(ev: PointerEvent): void { if (!ev.isPrimary) { return; } this.m_module.canvas.dispatchEvent(new PointerEvent("pointerup", ev)); } protected pointermove(ev: PointerEvent): void { if (!ev.isPrimary || OdBaseDragger.isGestureActive) { return; } const relCoord = this.relativeCoords(ev); this.drag(relCoord.x, relCoord.y, ev.clientX, ev.clientY); if (this.isDragging) { this.subject.update(); } } protected click(ev: MouseEvent): void { const viewer = this.getViewer(); const relCoord = this.relativeCoords(ev); const x = relCoord.x; const y = relCoord.y; const isNotDragging = Math.abs(x - this.mouseDownPosition.x) < CLICK_DELTA && Math.abs(y - this.mouseDownPosition.y) < CLICK_DELTA; if (viewer && viewer.getEnableAutoSelect() && isNotDragging) { viewer.unselect(); viewer.select(x, y, x, y); this.subject.update(); const selectionSet = viewer.getSelected(); const handles = this.subject.getSelected(); this.onmessage({ type: "select", data: selectionSet, handles }); } } protected dblclick(ev: MouseEvent): void { const viewer = this.getViewer(); const relCoord = this.relativeCoords(ev); const x = relCoord.x; const y = relCoord.y; const device = viewer.getActiveDevice(); const clickView = device.viewAt([x, y]); if (clickView && !clickView.active) { viewer.activeView = clickView; clickView.delete(); this.subject.update(); } else { if (viewer && viewer.getEnableAutoSelect()) { const pSelected = viewer.getSelected(); if (!pSelected.isNull() && pSelected.numItems() !== 0) { const itr = pSelected.getIterator(); const entity = itr.getEntity(); viewer.zoomToEntity(entity); this.onmessage({ type: "zoomtoentity", data: entity }); this.subject.update(); this.deleteAll([itr, entity]); } } } device.delete(); } protected start(x: number, y: number, absoluteX = 0, absoluteY = 0): void {} protected drag(x: number, y: number, absoluteX = 0, absoluteY = 0): void {} protected end(x: number, y: number, absoluteX = 0, absoluteY = 0): void {} protected beginInteractivity = () => { const viewer = this.getViewer(); const view = viewer.activeView; if (view["beginInteractivity"]) { view.beginInteractivity(INTERACTIVITY_FPS); this.subject.update(); } view.delete(); }; protected endInteractivity = () => { const viewer = this.getViewer(); const view = viewer.activeView; if (view["endInteractivity"]) { view.endInteractivity(); const device = this.getViewer().getActiveDevice(); const canvas = this.m_module.canvas; device.invalidate([0, 0, canvas.width, canvas.height]); device.delete(); this.subject.update(); } view.delete(); }; protected getActiveMarkupEntity(entityName: string): any { return this.subject.addMarkupEntity(entityName); } private syncOverlayView(): any { return this.subject.syncOverlay(); } protected deleteAll(objects): void { for (const obj of objects) { obj?.delete?.(); } } public updatePreview(): void {} private static _isGestureActive = false; protected static set isGestureActive(value: boolean) { if (OdBaseDragger._isGestureActive === value) { return; } OdBaseDragger._isGestureActive = value; if (OdBaseDragger._isGestureActive) { OdBaseDragger.needSkipPointerUp = true; } } protected static get isGestureActive() { return OdBaseDragger._isGestureActive; } private static _needSkipPointerUp = false; private static get needSkipPointerUp() { if (OdBaseDragger._needSkipPointerUp) { OdBaseDragger.needSkipPointerUp = false; return true; } return false; } private static set needSkipPointerUp(value: boolean) { OdBaseDragger._needSkipPointerUp = value; } }