UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

208 lines (182 loc) 5.53 kB
import { ModifierKey } from '../types' import { Dom } from '../util' import { Base } from './base' export class PanningManager extends Base { private panning: boolean private clientX: number private clientY: number private mousewheelHandle: Dom.MouseWheelHandle protected get widgetOptions() { return this.options.panning } get pannable() { return this.widgetOptions && this.widgetOptions.enabled === true } protected init() { this.startListening() this.updateClassName() } protected startListening() { const eventTypes = this.widgetOptions.eventTypes if (!eventTypes) { return } if (eventTypes.includes('leftMouseDown')) { this.graph.on('blank:mousedown', this.preparePanning, this) this.graph.on('node:unhandled:mousedown', this.preparePanning, this) this.graph.on('edge:unhandled:mousedown', this.preparePanning, this) } if (eventTypes.includes('rightMouseDown')) { this.onRightMouseDown = this.onRightMouseDown.bind(this) this.view.$(this.graph.container).on('mousedown', this.onRightMouseDown) } if (eventTypes.includes('mouseWheel')) { this.mousewheelHandle = new Dom.MouseWheelHandle( this.graph.container, this.onMouseWheel.bind(this), this.allowMouseWheel.bind(this), ) this.mousewheelHandle.enable() } } protected stopListening() { const eventTypes = this.widgetOptions.eventTypes if (!eventTypes) { return } if (eventTypes.includes('leftMouseDown')) { this.graph.off('blank:mousedown', this.preparePanning, this) this.graph.off('node:unhandled:mousedown', this.preparePanning, this) this.graph.off('edge:unhandled:mousedown', this.preparePanning, this) } if (eventTypes.includes('rightMouseDown')) { this.view.$(this.graph.container).off('mousedown', this.onRightMouseDown) } if (eventTypes.includes('mouseWheel')) { if (this.mousewheelHandle) { this.mousewheelHandle.disable() } } } protected preparePanning({ e }: { e: JQuery.MouseDownEvent }) { if ( this.allowPanning(e, true) || (this.allowPanning(e) && !this.graph.selection.allowRubberband(e, true)) ) { this.startPanning(e) } } allowPanning(e: JQuery.MouseDownEvent, strict?: boolean) { return ( this.pannable && ModifierKey.isMatch(e, this.widgetOptions.modifiers, strict) && this.graph.hook.allowPanning(e) ) } protected startPanning(evt: JQuery.MouseDownEvent) { const e = this.view.normalizeEvent(evt) this.clientX = e.clientX this.clientY = e.clientY this.panning = true this.updateClassName() this.view.$(document.body).on({ 'mousemove.panning touchmove.panning': this.pan.bind(this), 'mouseup.panning touchend.panning': this.stopPanning.bind(this), }) this.view.$(window).on('mouseup.panning', this.stopPanning.bind(this)) } protected pan(evt: JQuery.MouseMoveEvent) { const e = this.view.normalizeEvent(evt) const dx = e.clientX - this.clientX const dy = e.clientY - this.clientY this.clientX = e.clientX this.clientY = e.clientY this.graph.translateBy(dx, dy) } // eslint-disable-next-line protected stopPanning(e: JQuery.MouseUpEvent) { this.panning = false this.updateClassName() this.view.$(document.body).off('.panning') this.view.$(window).off('.panning') } protected updateClassName() { const container = this.view.container const panning = this.view.prefixClassName('graph-panning') const pannable = this.view.prefixClassName('graph-pannable') if (this.pannable) { if (this.panning) { Dom.addClass(container, panning) Dom.removeClass(container, pannable) } else { Dom.removeClass(container, panning) Dom.addClass(container, pannable) } } else { Dom.removeClass(container, panning) Dom.removeClass(container, pannable) } } protected onRightMouseDown(e: JQuery.MouseDownEvent) { if (e.button === 2 && this.allowPanning(e, true)) { this.startPanning(e) } } protected allowMouseWheel(e: JQueryMousewheel.JQueryMousewheelEventObject) { return this.pannable && !e.ctrlKey } protected onMouseWheel( e: JQueryMousewheel.JQueryMousewheelEventObject, deltaX: number, deltaY: number, ) { if (!e.ctrlKey) { this.graph.translateBy(-deltaX, -deltaY) } } autoPanning(x: number, y: number) { const buffer = 10 const graphArea = this.graph.getGraphArea() let dx = 0 let dy = 0 if (x <= graphArea.left + buffer) { dx = -buffer } if (y <= graphArea.top + buffer) { dy = -buffer } if (x >= graphArea.right - buffer) { dx = buffer } if (y >= graphArea.bottom - buffer) { dy = buffer } if (dx !== 0 || dy !== 0) { this.graph.translateBy(-dx, -dy) } } enablePanning() { if (!this.pannable) { this.widgetOptions.enabled = true this.updateClassName() } } disablePanning() { if (this.pannable) { this.widgetOptions.enabled = false this.updateClassName() } } @Base.dispose() dispose() { this.stopListening() } } export namespace PanningManager { type EventType = 'leftMouseDown' | 'rightMouseDown' | 'mouseWheel' export interface Options { enabled?: boolean modifiers?: string | ModifierKey[] | null eventTypes?: EventType[] } }