/
handler.ts
133 lines (114 loc) 路 3.88 KB
/
handler.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import * as util from '../../util'
import { Graph } from '../../graph'
import { Point } from '../../struct'
import { DomEvent, Disposable } from '../../common'
import { BaseHandler } from '../handler-base'
export class MouseWheelHandler extends BaseHandler {
private cursorPosition: Point
private wheelZoomDelay: number = 10
private wheelZoomTimer: number | null
private cumulativeZoomFactor: number = 1
private handler = (e: WheelEvent, up: boolean) => {
if (this.isZoomWheelEvent(e)) {
let source = DomEvent.getSource(e)
while (source != null) {
if (source === this.graph.container) {
this.cursorPosition = new Point(
DomEvent.getClientX(e),
DomEvent.getClientY(e),
)
this.lazyZoom(up)
DomEvent.consume(e)
return false
}
source = source.parentNode as Element
}
}
}
constructor(graph: Graph) {
super(graph)
this.setEnadled(this.graph.options.wheel.enabled)
}
enable() {
DomEvent.addWheelListener(this.handler, this.graph.container)
super.enable()
}
disable() {
DomEvent.removeWheelListener(this.handler, this.graph.container)
super.disable()
}
isZoomWheelEvent(e: MouseEvent) {
const modifiers = this.graph.options.wheel.modifiers
if (modifiers == null) {
return true
}
return (
(modifiers.includes('alt') && DomEvent.isAltDown(e)) ||
(modifiers.includes('meta') && DomEvent.isMetaDown(e)) ||
(modifiers.includes('ctrl') && DomEvent.isControlDown(e))
)
}
lazyZoom(zoomIn: boolean) {
if (this.wheelZoomTimer != null) {
window.clearTimeout(this.wheelZoomTimer)
}
const scale = this.view.scale
const scaleFactor = this.graph.scaleFactor
const container = this.graph.container
// Switches to 1% zoom steps below 15%
// Lower bound depdends on rounding below
if (zoomIn) {
if (scale * this.cumulativeZoomFactor < 0.15) {
this.cumulativeZoomFactor = (scale + 0.01) / scale
} else {
// Uses to 5% zoom steps for better grid rendering in webkit
// and to avoid rounding errors for zoom steps
this.cumulativeZoomFactor *= scaleFactor
this.cumulativeZoomFactor =
Math.round(scale * this.cumulativeZoomFactor * 20) / 20 / scale
}
} else {
if (scale * this.cumulativeZoomFactor <= 0.15) {
this.cumulativeZoomFactor = (scale - 0.01) / scale
} else {
// Uses to 5% zoom steps for better grid rendering in webkit
// and to avoid rounding errors for zoom steps
this.cumulativeZoomFactor /= scaleFactor
this.cumulativeZoomFactor =
Math.round(scale * this.cumulativeZoomFactor * 20) / 20 / scale
}
}
this.cumulativeZoomFactor = Math.max(
0.01,
Math.min(scale * this.cumulativeZoomFactor, 160) / scale,
)
this.wheelZoomTimer = window.setTimeout(() => {
const offset = util.getOffset(container)
let dx = 0
let dy = 0
if (this.cursorPosition != null) {
dx = container.offsetWidth / 2 - this.cursorPosition.x + offset.x
dy = container.offsetHeight / 2 - this.cursorPosition.y + offset.y
}
const prev = this.view.scale
this.graph.zoom(this.cumulativeZoomFactor)
const s = this.view.scale
if (s !== prev) {
// if (resize != null) {
// ui.chromelessResize(false, null, dx * (this.cumulativeZoomFactor - 1),
// dy * (this.cumulativeZoomFactor - 1))
// }
if (util.hasScrollbars(container) && (dx !== 0 || dy !== 0)) {
container.scrollLeft -= dx * (this.cumulativeZoomFactor - 1)
container.scrollTop -= dy * (this.cumulativeZoomFactor - 1)
}
}
this.cumulativeZoomFactor = 1
this.wheelZoomTimer = null
}, this.wheelZoomDelay)
}
@Disposable.aop()
dispose() {
this.disable()
}
}