@@ -147,6 +147,119 @@ function tooltipPlugin({
147
147
} ;
148
148
}
149
149
150
+ // Taken from https://leeoniya.github.io/uPlot/demos/zoom-wheel.html
151
+ function wheelZoomPlugin ( opts ) {
152
+ let factor = opts . factor || 0.75 ;
153
+
154
+ let xMin , xMax , yMin , yMax , xRange , yRange ;
155
+
156
+ function clamp ( nRange , nMin , nMax , fRange , fMin , fMax ) {
157
+ if ( nRange > fRange ) {
158
+ nMin = fMin ;
159
+ nMax = fMax ;
160
+ } else if ( nMin < fMin ) {
161
+ nMin = fMin ;
162
+ nMax = fMin + nRange ;
163
+ } else if ( nMax > fMax ) {
164
+ nMax = fMax ;
165
+ nMin = fMax - nRange ;
166
+ }
167
+
168
+ return [ nMin , nMax ] ;
169
+ }
170
+
171
+ return {
172
+ hooks : {
173
+ ready : ( u ) => {
174
+ xMin = u . scales . x . min ;
175
+ xMax = u . scales . x . max ;
176
+ yMin = u . scales . y . min ;
177
+ yMax = u . scales . y . max ;
178
+
179
+ xRange = xMax - xMin ;
180
+ yRange = yMax - yMin ;
181
+
182
+ let over = u . over ;
183
+ let rect = over . getBoundingClientRect ( ) ;
184
+
185
+ // wheel drag pan
186
+ over . addEventListener ( "mousedown" , ( e ) => {
187
+ if ( e . button == 1 ) {
188
+ // plot.style.cursor = "move";
189
+ e . preventDefault ( ) ;
190
+
191
+ let left0 = e . clientX ;
192
+ // let top0 = e.clientY;
193
+
194
+ let scXMin0 = u . scales . x . min ;
195
+ let scXMax0 = u . scales . x . max ;
196
+
197
+ let xUnitsPerPx = u . posToVal ( 1 , "x" ) - u . posToVal ( 0 , "x" ) ;
198
+
199
+ function onmove ( e ) {
200
+ e . preventDefault ( ) ;
201
+
202
+ let left1 = e . clientX ;
203
+ // let top1 = e.clientY;
204
+
205
+ let dx = xUnitsPerPx * ( left1 - left0 ) ;
206
+
207
+ u . setScale ( "x" , {
208
+ min : scXMin0 - dx ,
209
+ max : scXMax0 - dx ,
210
+ } ) ;
211
+ }
212
+
213
+ function onup ( e ) {
214
+ document . removeEventListener ( "mousemove" , onmove ) ;
215
+ document . removeEventListener ( "mouseup" , onup ) ;
216
+ }
217
+
218
+ document . addEventListener ( "mousemove" , onmove ) ;
219
+ document . addEventListener ( "mouseup" , onup ) ;
220
+ }
221
+ } ) ;
222
+
223
+ // wheel scroll zoom
224
+ over . addEventListener ( "wheel" , ( e ) => {
225
+ e . preventDefault ( ) ;
226
+
227
+ let { left, top} = u . cursor ;
228
+
229
+ let leftPct = left / rect . width ;
230
+ let btmPct = 1 - top / rect . height ;
231
+ let xVal = u . posToVal ( left , "x" ) ;
232
+ let yVal = u . posToVal ( top , "y" ) ;
233
+ let oxRange = u . scales . x . max - u . scales . x . min ;
234
+ let oyRange = u . scales . y . max - u . scales . y . min ;
235
+
236
+ let nxRange = e . deltaY < 0 ? oxRange * factor : oxRange / factor ;
237
+ let nxMin = xVal - leftPct * nxRange ;
238
+ let nxMax = nxMin + nxRange ;
239
+ [ nxMin , nxMax ] = clamp ( nxRange , nxMin , nxMax , xRange , xMin , xMax ) ;
240
+
241
+ let nyRange = e . deltaY < 0 ? oyRange * factor : oyRange / factor ;
242
+ let nyMin = yVal - btmPct * nyRange ;
243
+ let nyMax = nyMin + nyRange ;
244
+ [ nyMin , nyMax ] = clamp ( nyRange , nyMin , nyMax , yRange , yMin , yMax ) ;
245
+
246
+ u . batch ( ( ) => {
247
+ u . setScale ( "x" , {
248
+ min : nxMin ,
249
+ max : nxMax ,
250
+ } ) ;
251
+
252
+ u . setScale ( "y" , {
253
+ min : nyMin ,
254
+ max : nyMax ,
255
+ } ) ;
256
+ } ) ;
257
+ } ) ;
258
+ } ,
259
+ } ,
260
+ } ;
261
+ }
262
+
150
263
function genPlotOpts ( {
151
264
width,
152
265
height,
@@ -253,6 +366,7 @@ function genPlotOpts({
253
366
isInterpolated,
254
367
absoluteMode,
255
368
} ) ,
369
+ wheelZoomPlugin ( { factor : 0.75 } ) ,
256
370
] ,
257
371
} ;
258
372
}
0 commit comments