@@ -255,7 +255,7 @@ class Slider(AxesWidget):
255
255
def __init__ (self , ax , label , valmin , valmax , valinit = 0.5 , valfmt = None ,
256
256
closedmin = True , closedmax = True , slidermin = None ,
257
257
slidermax = None , dragging = True , valstep = None ,
258
- orientation = 'horizontal' , ** kwargs ):
258
+ orientation = 'horizontal' , valsnap = None , ** kwargs ):
259
259
"""
260
260
Parameters
261
261
----------
@@ -297,10 +297,15 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
297
297
298
298
valstep : float, default: None
299
299
If given, the slider will snap to multiples of *valstep*.
300
+ If both *valsnap* and *valstep* are set an error is raised.
300
301
301
302
orientation : {'horizontal', 'vertical'}, default: 'horizontal'
302
303
The orientation of the slider.
303
304
305
+ valsnap : 1D array-like, default: None
306
+ If given, the slider will snap to nearest value in *valsnap*.
307
+ If both *valsnap* and *valstep* are set an error is raised.
308
+
304
309
Notes
305
310
-----
306
311
Additional kwargs are passed on to ``self.poly`` which is the
@@ -319,6 +324,9 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
319
324
if slidermax is not None and not hasattr (slidermax , 'val' ):
320
325
raise ValueError (
321
326
f"Argument slidermax ({ type (slidermax )} ) has no 'val'" )
327
+ if valstep is not None and valsnap is not None :
328
+ raise ValueError ("kwargs 'valsnap' and 'valstep' cannot "
329
+ "be used simultaneously. " )
322
330
_api .check_in_list (['horizontal' , 'vertical' ], orientation = orientation )
323
331
324
332
self .orientation = orientation
@@ -330,6 +338,15 @@ def __init__(self, ax, label, valmin, valmax, valinit=0.5, valfmt=None,
330
338
self .valmin = valmin
331
339
self .valmax = valmax
332
340
self .valstep = valstep
341
+ self .valsnap = valsnap
342
+ if self .valsnap is not None :
343
+ self .valsnap = np .sort (self .valsnap )
344
+ elif self .valstep is not None :
345
+ self .valsnap = np .arange (
346
+ self .valmin ,
347
+ self .valmax + self .valstep ,
348
+ self .valstep
349
+ )
333
350
valinit = self ._value_in_bounds (valinit )
334
351
if valinit is None :
335
352
valinit = valmin
@@ -401,9 +418,10 @@ def observers(self):
401
418
402
419
def _value_in_bounds (self , val ):
403
420
"""Makes sure *val* is with given bounds."""
404
- if self .valstep :
405
- val = (self .valmin
406
- + round ((val - self .valmin ) / self .valstep ) * self .valstep )
421
+ if self .valsnap is not None :
422
+ idx = np .searchsorted (self .valsnap , val , side = "left" )
423
+ candidates = self .valsnap [[idx - 1 , min (idx , self .valsnap .size - 1 )]]
424
+ val = candidates [np .argmin (np .abs (candidates - val ))]
407
425
408
426
if val <= self .valmin :
409
427
if not self .closedmin :
0 commit comments