@@ -36,6 +36,7 @@ export class ScrollBar extends AbstractComponent<Required<ScrollBarAttributes>>
3636 direction : 'horizontal' ,
3737 round : true ,
3838 sliderSize : 20 ,
39+ minSliderSize : 0 ,
3940 sliderStyle : {
4041 fill : 'rgba(0, 0, 0, .5)'
4142 } ,
@@ -267,15 +268,23 @@ export class ScrollBar extends AbstractComponent<Required<ScrollBarAttributes>>
267268 return 0 ;
268269 }
269270
270- // 计算滑块在轨道的位置
271+ /**
272+ * 计算滑块在轨道的位置(像素),应用最小展示尺寸但不改变 range 语义
273+ */
271274 private _getSliderPos ( range : [ number , number ] ) {
272- const { direction } = this . attribute as ScrollBarAttributes ;
275+ const { direction, minSliderSize = 0 } = this . attribute as ScrollBarAttributes ;
273276 const { width, height, x1, y1 } = this . getSliderRenderBounds ( ) ;
274-
275- if ( direction === 'horizontal' ) {
276- return [ width * range [ 0 ] + x1 , width * range [ 1 ] + x1 ] ;
277- }
278- return [ height * range [ 0 ] + y1 , height * range [ 1 ] + y1 ] ;
277+ const track = direction === 'horizontal' ? width : height ;
278+ const origin = direction === 'horizontal' ? x1 : y1 ;
279+ const start = clamp ( range [ 0 ] , 0 , 1 ) ;
280+ const end = clamp ( range [ 1 ] , 0 , 1 ) ;
281+ const ratio = clamp ( end - start , 0 , 1 ) ;
282+ const L = Math . max ( ratio * track , minSliderSize ) ;
283+ const T = Math . max ( track - L , 0 ) ;
284+ const denom = Math . max ( 1 - ratio , 1e-12 ) ;
285+ const pStart = origin + ( start / denom ) * T ;
286+ const pEnd = pStart + L ;
287+ return [ pStart , pEnd ] ;
279288 }
280289
281290 private _getScrollRange ( ) {
@@ -349,24 +358,37 @@ export class ScrollBar extends AbstractComponent<Required<ScrollBarAttributes>>
349358 } ) ;
350359 } ;
351360
361+ /**
362+ * 将拖拽像素位移映射为逻辑 range 增量,保证最小尺寸下仍覆盖 [0,1]
363+ */
352364 private _computeScrollValue = ( e : any ) => {
353365 const { direction } = this . attribute as ScrollBarAttributes ;
354366 const { x, y } = this . stage . eventPointTransform ( e ) ;
355367
356- let currentScrollValue ;
368+ let currentScrollValue = 0 ;
357369 let currentPos ;
358370 let delta = 0 ;
359371
360372 const { width, height } = this . getSliderRenderBounds ( ) ;
373+ const track = direction === 'vertical' ? height : width ;
374+ const travel = Math . max ( track - this . _sliderSize , 0 ) ;
375+ const { range } = this . attribute as ScrollBarAttributes ;
376+ const ratio = clamp ( range [ 1 ] - range [ 0 ] , 0 , 1 ) ;
377+
361378 if ( direction === 'vertical' ) {
362379 currentPos = y ;
363380 delta = currentPos - this . _prePos ;
364- currentScrollValue = delta / height ;
365381 } else {
366382 currentPos = x ;
367383 delta = currentPos - this . _prePos ;
368- currentScrollValue = delta / width ;
369384 }
385+
386+ if ( travel > 0 && ratio < 1 ) {
387+ currentScrollValue = ( delta / travel ) * ( 1 - ratio ) ;
388+ } else {
389+ currentScrollValue = 0 ;
390+ }
391+
370392 return [ currentPos , currentScrollValue ] ;
371393 } ;
372394
0 commit comments