1- import  type  {  IGroup  }  from  '@visactor/vrender-core' ; 
1+ import  {  isValidNumber ,  merge  }  from  '@visactor/vutils' ; 
2+ import  type  {  IGroup ,  IRectGraphicAttribute  }  from  '@visactor/vrender-core' ; 
23import  {  BasePlugin  }  from  '../../base/base-plugin' ; 
34import  type  {  IChartPluginService  }  from  '../interface' ; 
45import  {  registerChartPlugin  }  from  '../register' ; 
56import  type  {  IScrollPlugin ,  IScrollPluginSpec  }  from  './interface' ; 
67import  {  ScrollBar  as  ScrollBarComponent  }  from  '@visactor/vrender-components' ; 
8+ import  {  Event  }  from  '../../../event/event' ; 
9+ import  type  {  ExtendEventParam  }  from  '../../../event/interface' ; 
710
8- const  scrollBarSize  =  10 ; 
11+ // 由vrender透出, 接入新版本后需修改 
12+ const  SCROLLBAR_EVENT  =  'scrollDrag' ; 
13+ const  SCROLLBAR_END_EVENT  =  'scrollUp' ; 
914
15+ const  DefaultTheme : { 
16+   size ?: number ; 
17+   railStyle ?: Omit < IRectGraphicAttribute ,  'width'  |  'height' > ; 
18+   sliderStyle ?: Omit < IRectGraphicAttribute ,  'width'  |  'height' > ; 
19+ }  =  { 
20+   size : 10 , 
21+   railStyle : undefined , 
22+   sliderStyle : undefined 
23+ } ; 
1024/** 
1125 * ScrollPlugin 类 
1226 * @since  1.0.0 
@@ -15,26 +29,32 @@ export class ScrollPlugin extends BasePlugin implements IScrollPlugin {
1529  static  readonly  pluginType : 'chart'  =  'chart' ; 
1630  static  readonly  type : string  =  'chartScroll' ; 
1731  readonly  type : string  =  'chartScroll' ; 
32+   readonly  name : string  =  ScrollPlugin . type ; 
1833
1934  private  _service : IChartPluginService ; 
2035
2136  private  _spec : IScrollPluginSpec ; 
37+   private  _lastScrollX  =  0 ; 
38+   private  _lastScrollY  =  0 ; 
2239
2340  private  _scrollLimit  =  { 
2441    x : { 
2542      min : 0 , 
2643      max : 0 , 
44+       size : 0 , 
2745      percent : 0 
2846    } , 
2947    y : { 
3048      min : 0 , 
3149      max : 0 , 
50+       size : 0 , 
3251      percent : 0 
3352    } 
3453  } ; 
3554
3655  private  _xScrollComponent : ScrollBarComponent ; 
3756  private  _yScrollComponent : ScrollBarComponent ; 
57+   private  _event : Event ; 
3858
3959  constructor ( )  { 
4060    super ( ScrollPlugin . type ) ; 
@@ -56,18 +76,24 @@ export class ScrollPlugin extends BasePlugin implements IScrollPlugin {
5676    const  canvasSize  =  service . globalInstance . getChart ( ) . getCanvasRect ( ) ; 
5777    this . _scrollLimit . x . min  =  Math . min ( canvasSize . width  -  viewBoxSize . width ,  0 ) ; 
5878    this . _scrollLimit . x . percent  =  Math . abs ( canvasSize . width  /  viewBoxSize . width ) ; 
79+     this . _scrollLimit . x . size  =  viewBoxSize . width ; 
5980    this . _scrollLimit . y . min  =  Math . min ( canvasSize . height  -  viewBoxSize . height ,  0 ) ; 
6081    this . _scrollLimit . y . percent  =  Math . abs ( canvasSize . height  /  viewBoxSize . height ) ; 
82+     this . _scrollLimit . y . size  =  viewBoxSize . height ; 
83+ 
84+     if  ( ! this . _event )  { 
85+       this . _event  =  new  Event ( this . _service . globalInstance . getChart ( ) . getOption ( ) . eventDispatcher ,  null ) ; 
86+     } 
6187  } 
6288
6389  onAfterRender ( )  { 
6490    const  rootMark  =  this . getRootMark ( ) ; 
6591    if  ( rootMark )  { 
6692      if  ( ! this . _xScrollComponent )  { 
67-         this . _updateScrollX ( rootMark ,  0 ) ; 
93+         this . _updateScrollX ( rootMark ,  0 ,   0 ) ; 
6894      } 
6995      if  ( ! this . _yScrollComponent )  { 
70-         this . _updateScrollY ( rootMark ,  0 ) ; 
96+         this . _updateScrollY ( rootMark ,  0 ,   0 ) ; 
7197      } 
7298    } 
7399  } 
@@ -94,20 +120,57 @@ export class ScrollPlugin extends BasePlugin implements IScrollPlugin {
94120    if  ( ! rootMark )  { 
95121      return ; 
96122    } 
97-     this . _updateScrollX ( rootMark ,  rootMark . attribute . x  -  scrollX ) ; 
98-     this . _updateScrollY ( rootMark ,  rootMark . attribute . y  -  scrollY ) ; 
123+     const  {  percent : yPercent ,  y }  =  this . _computeFinalScrollY ( rootMark . attribute . y  -  scrollY )  ??  { } ; 
124+     const  {  percent : xPercent ,  x }  =  this . _computeFinalScrollX ( rootMark . attribute . x  -  scrollX )  ??  { } ; 
125+     const  eventResult : {  x ?: number ;  y ?: number  }  =  { } ; 
126+     if  ( isValidNumber ( x ) )  { 
127+       this . _updateScrollX ( rootMark ,  x ,  xPercent ) ; 
128+       eventResult . x  =  x ; 
129+     } 
130+     if  ( isValidNumber ( y ) )  { 
131+       this . _updateScrollY ( rootMark ,  y ,  yPercent ) ; 
132+       eventResult . y  =  y ; 
133+     } 
134+ 
135+     this . _event . emit ( 'chartScroll' ,  eventResult  as  ExtendEventParam ) ; 
99136  } ; 
100137
101-   private  _updateScrollY ( rootMark : IGroup ,  y : number )  { 
138+   private  _computeFinalScrollY ( y : number )  { 
139+     if  ( this . _lastScrollY  ===  y )  { 
140+       return  null ; 
141+     } 
142+     this . _lastScrollY  =  y ; 
102143    if  ( this . _spec . y ?. enable  ===  false )  { 
103-       return ; 
144+       return   null ; 
104145    } 
105146    const  finalY  =  Math . max ( this . _scrollLimit . y . min ,  Math . min ( y ,  this . _scrollLimit . y . max ) ) ; 
106-     const  percent  =  Math . abs ( finalY  /  this . _scrollLimit . y . min ) ; 
147+     const  percent  =  Math . abs ( finalY  /  this . _scrollLimit . y . size ) ; 
148+     return  { 
149+       y : finalY , 
150+       percent
151+     } ; 
152+   } 
153+   private  _computeFinalScrollX ( x : number )  { 
154+     if  ( this . _lastScrollX  ===  x )  { 
155+       return  null ; 
156+     } 
157+     this . _lastScrollX  =  x ; 
158+     if  ( this . _spec . x ?. enable  ===  false )  { 
159+       return  null ; 
160+     } 
161+     const  finalX  =  Math . max ( this . _scrollLimit . x . min ,  Math . min ( x ,  this . _scrollLimit . x . max ) ) ; 
162+     const  percent  =  Math . abs ( finalX  /  this . _scrollLimit . x . size ) ; 
163+     return  { 
164+       x : finalX , 
165+       percent
166+     } ; 
167+   } 
168+ 
169+   private  _updateScrollY ( rootMark : IGroup ,  y : number ,  percent : number )  { 
107170    const  yScrollComponent  =  this . _getYScrollComponent ( ) ; 
108171    yScrollComponent . setAttribute ( 'range' ,  [ percent ,  percent  +  this . _scrollLimit . y . percent ] ) ; 
109172    rootMark . setAttributes ( { 
110-       y : finalY 
173+       y : y 
111174    } ) ; 
112175  } 
113176
@@ -119,32 +182,44 @@ export class ScrollPlugin extends BasePlugin implements IScrollPlugin {
119182      this . _yScrollComponent  =  new  ScrollBarComponent ( { 
120183        ...rest , 
121184        zIndex : 9999 , 
122-         x : canvasSize . width  -  scrollBarSize , 
185+         x : canvasSize . width  -  DefaultTheme . size , 
123186        y : 0 , 
124-         width : scrollBarSize , 
187+         width : DefaultTheme . size , 
125188        height : canvasSize . height , 
126189        range : [ 0 ,  canvasSize . height  /  viewSize . height ] , 
127190        direction : 'vertical' , 
128191        delayTime : rest ?. delayTime  ??  30 , 
129192        realTime : rest ?. realTime  ??  true , 
130-         sliderStyle : {  fill : 'rgba(0,0,0,0.3)'  } 
193+         railStyle : DefaultTheme . railStyle , 
194+         sliderStyle : DefaultTheme . sliderStyle 
195+       } ) ; 
196+       // 绑定事件,防抖,防止频繁触发 
197+       this . _yScrollComponent . addEventListener ( SCROLLBAR_EVENT ,  ( e : any )  =>  { 
198+         const  value  =  e . detail . value ; 
199+         const  {  percent,  y }  =  this . _computeFinalScrollY ( - value [ 0 ]  *  this . _scrollLimit . y . size )  ??  { } ; 
200+         if  ( percent  !==  undefined  &&  y  !==  undefined )  { 
201+           this . _updateScrollY ( this . getRootMark ( ) ,  y ,  percent ) ; 
202+           this . _event . emit ( 'chartScroll' ,  {  y }  as  ExtendEventParam ) ; 
203+         } 
204+       } ) ; 
205+       this . _yScrollComponent . addEventListener ( SCROLLBAR_END_EVENT ,  ( e : any )  =>  { 
206+         const  value  =  e . detail . value ; 
207+         const  {  percent,  y }  =  this . _computeFinalScrollY ( - value [ 0 ]  *  this . _scrollLimit . y . size )  ??  { } ; 
208+         if  ( percent  !==  undefined  &&  y  !==  undefined )  { 
209+           this . _updateScrollY ( this . getRootMark ( ) ,  y ,  percent ) ; 
210+           this . _event . emit ( 'chartScroll' ,  {  y }  as  ExtendEventParam ) ; 
211+         } 
131212      } ) ; 
132213      this . getRootMark ( ) . parent ?. addChild ( this . _yScrollComponent ) ; 
133214    } 
134215    return  this . _yScrollComponent ; 
135216  } 
136217
137-   private  _updateScrollX ( rootMark : IGroup ,  x : number )  { 
138-     if  ( this . _spec . x ?. enable  ===  false )  { 
139-       return ; 
140-     } 
141-     const  finalX  =  Math . max ( this . _scrollLimit . x . min ,  Math . min ( x ,  this . _scrollLimit . x . max ) ) ; 
142-     const  percent  =  Math . abs ( finalX  /  this . _scrollLimit . x . min ) ; 
218+   private  _updateScrollX ( rootMark : IGroup ,  x : number ,  percent : number )  { 
143219    const  xScrollComponent  =  this . _getXScrollComponent ( ) ; 
144220    xScrollComponent . setAttribute ( 'range' ,  [ percent ,  percent  +  this . _scrollLimit . x . percent ] ) ; 
145- 
146221    rootMark . setAttributes ( { 
147-       x : finalX 
222+       x : x 
148223    } ) ; 
149224  } 
150225
@@ -157,24 +232,71 @@ export class ScrollPlugin extends BasePlugin implements IScrollPlugin {
157232        ...rest , 
158233        zIndex : 9999 , 
159234        x : 0 , 
160-         y : canvasSize . height  -  scrollBarSize , 
235+         y : canvasSize . height  -  DefaultTheme . size , 
161236        width : canvasSize . width , 
162-         height : scrollBarSize , 
237+         height : DefaultTheme . size , 
163238        range : [ 0 ,  canvasSize . width  /  viewSize . width ] , 
164239        direction : 'horizontal' , 
165240        delayTime : rest ?. delayTime  ??  30 , 
166-         realTime : rest ?. realTime  ??  true 
241+         realTime : rest ?. realTime  ??  true , 
242+         sliderStyle : DefaultTheme . sliderStyle , 
243+         railStyle : DefaultTheme . railStyle 
244+       } ) ; 
245+       // 绑定事件,防抖,防止频繁触发 
246+       this . _xScrollComponent . addEventListener ( SCROLLBAR_EVENT ,  ( e : any )  =>  { 
247+         const  value  =  e . detail . value ; 
248+         const  {  percent,  x }  =  this . _computeFinalScrollX ( - value [ 0 ]  *  this . _scrollLimit . x . size )  ??  { } ; 
249+         if  ( percent  !==  undefined  &&  x  !==  undefined )  { 
250+           this . _updateScrollX ( this . getRootMark ( ) ,  x ,  percent ) ; 
251+           this . _event . emit ( 'chartScroll' ,  {  x }  as  ExtendEventParam ) ; 
252+         } 
253+       } ) ; 
254+       this . _xScrollComponent . addEventListener ( SCROLLBAR_END_EVENT ,  ( e : any )  =>  { 
255+         const  value  =  e . detail . value ; 
256+         const  {  percent,  x }  =  this . _computeFinalScrollX ( - value [ 0 ]  *  this . _scrollLimit . x . size )  ??  { } ; 
257+         if  ( percent  !==  undefined  &&  x  !==  undefined )  { 
258+           this . _updateScrollX ( this . getRootMark ( ) ,  x ,  percent ) ; 
259+           this . _event . emit ( 'chartScroll' ,  {  x }  as  ExtendEventParam ) ; 
260+         } 
167261      } ) ; 
168262      this . getRootMark ( ) . parent ?. addChild ( this . _xScrollComponent ) ; 
169263    } 
170264    return  this . _xScrollComponent ; 
171265  } 
266+ 
267+   /** 
268+    * api 
269+    */ 
270+   scrollTo ( {  x,  y } : {  x ?: number ;  y ?: number  } )  { 
271+     const  rootMark  =  this . getRootMark ( ) ; 
272+     if  ( rootMark )  { 
273+       if  ( x  !==  undefined )  { 
274+         const  {  x : finalX ,  percent }  =  this . _computeFinalScrollX ( x )  ??  { } ; 
275+         if  ( finalX  !==  undefined  &&  percent  !==  undefined )  { 
276+           this . _updateScrollX ( rootMark ,  finalX ,  percent ) ; 
277+         } 
278+       } 
279+       if  ( y  !==  undefined )  { 
280+         const  {  y : finalY ,  percent }  =  this . _computeFinalScrollY ( y )  ??  { } ; 
281+         if  ( finalY  !==  undefined  &&  percent  !==  undefined )  { 
282+           this . _updateScrollY ( rootMark ,  finalY ,  percent ) ; 
283+         } 
284+       } 
285+     } 
286+   } 
172287} 
173288
174289/** 
175290 * 注册 ScrollPlugin 
176291 * @since  1.0.0 
177292 */ 
178- export  const  registerScrollPlugin  =  ( )  =>  { 
293+ export  const  registerScrollPlugin  =  ( theme ?: { 
294+   size ?: number ; 
295+   railStyle ?: Omit < IRectGraphicAttribute ,  'width'  |  'height' > ; 
296+   sliderStyle ?: Omit < IRectGraphicAttribute ,  'width'  |  'height' > ; 
297+ } )  =>  { 
298+   DefaultTheme . size  =  theme ?. size  ??  DefaultTheme . size ; 
299+   DefaultTheme . railStyle  =  merge ( { } ,  DefaultTheme . railStyle  ??  { } ,  theme ?. railStyle  ??  { } ) ; 
300+   DefaultTheme . sliderStyle  =  merge ( { } ,  DefaultTheme . sliderStyle  ??  { } ,  theme ?. sliderStyle  ??  { } ) ; 
179301  registerChartPlugin ( ScrollPlugin ) ; 
180302} ; 
0 commit comments