1# Scroll 2 3可滚动的容器组件,当子组件的布局尺寸超过父组件的尺寸时,内容可以滚动。 4 5> **说明:** 6> - 该组件从API version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 7> - 该组件嵌套List子组件滚动时,若List不设置宽高,则默认全部加载,在对性能有要求的场景下建议指定List的宽高。 8> - 该组件滚动的前提是主轴方向大小小于内容大小。 9> - 该组件回弹的前提是要有滚动。内容小于一屏时,没有回弹效果。 10 11 12## 子组件 13 14支持单个子组件。 15 16 17## 接口 18 19Scroll(scroller?: Scroller) 20 21**参数:** 22 23| 参数名 | 参数类型 | 必填 | 参数描述 | 24| -------- | -------- | -------- | -------- | 25| scroller | [Scroller](#scroller) | 否 | 可滚动组件的控制器。用于与可滚动组件进行绑定。 | 26 27## 属性 28 29除支持[通用属性](ts-universal-attributes-size.md)外,还支持以下属性: 30 31| 名称 | 参数类型 | 描述 | 32| -------------- | ---------------------------------------- | --------- | 33| scrollable | [ScrollDirection](#scrolldirection枚举说明) | 设置滚动方向。<br/>默认值:ScrollDirection.Vertical | 34| scrollBar | [BarState](ts-appendix-enums.md#barstate) | 设置滚动条状态。<br/>默认值:BarState.Auto<br/>**说明:** <br/>如果容器组件无法滚动,则滚动条不显示。如果容器组件的子组件大小为无穷大,则滚动条不支持拖动和伴随滚动。 | 35| scrollBarColor | string \| number \| [Color](ts-appendix-enums.md#color) | 设置滚动条的颜色。 | 36| scrollBarWidth | string \| number | 设置滚动条的宽度,不支持百分比设置。<br/>默认值:4<br/>单位:vp<br/>**说明:** <br/>如果滚动条的宽度超过其高度,则滚动条的宽度会变为默认值。 | 37| scrollSnap<sup>10+</sup> | [ScrollSnapOptions](#scrollsnapoptions10) | 设置Scroll组件的限位滚动模式。 | 38| edgeEffect | [EdgeEffect](ts-appendix-enums.md#edgeeffect) | 设置滑动效果,目前支持的滑动效果参见EdgeEffect的枚举说明。<br/>默认值:EdgeEffect.None | 39| enableScrollInteraction<sup>10+</sup> | boolean | 设置是否支持滚动手势,当设置为false时,无法通过手指或者鼠标滚动,但不影响控制器的滚动接口。<br/>默认值:true | 40| nestedScroll<sup>10+</sup> | [NestedScrollOptions](#nestedscrolloptions10对象说明) | 嵌套滚动选项。设置向前向后两个方向上的嵌套滚动模式,实现与父组件的滚动联动。 | 41| friction<sup>10+</sup> | number \| [Resource](ts-types.md#resource) | 设置摩擦系数,手动划动滚动区域时生效,只对惯性滚动过程有影响,对惯性滚动过程中的链式效果有间接影响。<br/>默认值:非可穿戴设备为0.6,可穿戴设备为0.9<br/>**说明:** <br/>设置为小于等于0的值时,按默认值处理 | 42 43## ScrollDirection枚举说明 44| 名称 | 描述 | 45| ---------- | ------------------------ | 46| Horizontal | 仅支持水平方向滚动。 | 47| Vertical | 仅支持竖直方向滚动。 | 48| None | 不可滚动。 | 49| Free<sup>(deprecated) </sup> | 支持竖直或水平方向滚动<br/> 从API version 9开始废弃| 50 51## ScrollSnapOptions<sup>10+</sup> 52| 名称 | 参数类型 | 描述 | 53| ---------- | ---------------------------------------- | -------- | 54| snapAlign | [ScrollSnapAlign](ts-container-list.md#scrollsnapalign10枚举说明) | 设置Scroll组件限位滚动时的对齐方式。<br/>**说明:** <br/>1.该属性默认值为ScrollSnapAlign.NONE。<br/>2.该接口仅当snapPagination属性为Dimension时生效,不支持Array\<Dimension\>。 | 55| snapPagination | [Dimension](ts-types.md#dimension10) \| Array\<Dimension\> | 设置Scroll组件限位滚动时的限位点,限位点即为Scroll组件能滑动停靠的偏移量。<br/>**说明:** <br/>1.当属性为Dimension时,表示每页的大小,系统会按照该大小来自动计算每个限位点的位置:如当Dimension为500时,实际的限位点即为[0,500,1000,1500,...]。<br/>2.当属性为Array\<Dimension\>时,每个Dimension代表限位点的位置。每个Dimension的范围为[0,可滑动距离],0和可滑动距离的底部自动成为限位点。<br/>3.当该属性不填或者Dimension为小于等于0的输入时,按异常值,无限位滚动处理。当该属性值为Array\<Dimension\>数组时,数组中的数值必须为单调递增。<br/>4.当输入为百分比时,实际的大小为Scroll组件的视口与百分比数值之积。 | 56| enableSnapToStart | boolean | 在Scroll组件限位滚动模式下,该属性设置为false后,运行Scroll在开头和第一个限位点间自由滑动。<br/>**说明:** <br/>1.该属性值默认为true。<br/>2.该属性仅当snapPagination属性为Array\<Dimension\>时生效,不支持Dimension。 | 57| enableSnapToEnd | boolean | 在Scroll组件限位滚动模式下,该属性设置为false后,运行Scroll在最后一个限位点和末尾间自由滑动。<br/>**说明:** <br/>1.该属性值默认为true。<br/>2.该属性仅当snapPagination属性为Array\<Dimension\>时生效,不支持Dimension。 | 58 59## 事件 60 61| 名称 | 功能描述 | 62| ------------------------------------------------------------ | ------------------------------------------------------------ | 63| onScrollFrameBegin<sup>9+</sup>(event: (offset: number, state: [ScrollState](ts-container-list.md#scrollstate枚举说明)) => { offsetRemain: number; }) | 每帧开始滚动时触发,事件参数传入即将发生的滚动量,事件处理函数中可根据应用场景计算实际需要的滚动量并作为事件处理函数的返回值返回,Scroll将按照返回值的实际滚动量进行滚动。<br/>\- offset:即将发生的滚动量,单位vp。<br/>\- state:当前滚动状态。<br/>- offsetRemain:实际滚动量,单位vp。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动时触发,包括键鼠操作等其他触发滚动的输入设置。<br/>2、调用控制器接口时不触发。<br/>3、越界回弹不触发。<br/>4、拖动滚动条不触发。<br/>**说明:** <br/>支持offsetRemain为负值。<br/>若通过onScrollFrameBegin事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None。 | 64| onScroll(event: (xOffset: number, yOffset: number) => void) | 滚动事件回调, 返回滚动时水平、竖直方向偏移量,单位vp。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用。<br/>3、越界回弹。 | 65| onScrollEdge(event: (side: Edge) => void) | 滚动到边缘事件回调。<br/>触发该事件的条件 :<br/>1、滚动组件滚动到边缘时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用。<br/>3、越界回弹。 | 66| onScrollEnd<sup>(deprecated) </sup>(event: () => void) | 滚动停止事件回调。<br>该事件从API version 9开始废弃,使用onScrollStop事件替代。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后停止,带过渡动效。 | 67| onScrollStart<sup>9+</sup>(event: () => void) | 滚动开始时触发。手指拖动Scroll或拖动Scroll的滚动条触发的滚动开始时,会触发该事件。使用[Scroller](#scroller)滚动控制器触发的带动画的滚动,动画开始时会触发该事件。<br/>触发该事件的条件 :<br/>1、滚动组件开始滚动时触发,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后开始,带过渡动效。 | 68| onScrollStop<sup>9+</sup>(event: () => void) | 滚动停止时触发。手拖动Scroll或拖动Scroll的滚动条触发的滚动,手离开屏幕并且滚动停止时会触发该事件。使用[Scroller](#scroller)滚动控制器触发的带动画的滚动,动画停止时会触发该事件。<br/>触发该事件的条件 :<br/>1、滚动组件触发滚动后停止,支持键鼠操作等其他触发滚动的输入设置。<br/>2、通过滚动控制器API接口调用后开始,带过渡动效。 | 69 70> **说明:** 71> 72> 若通过onScrollFrameBegin事件和scrollBy方法实现容器嵌套滚动,需设置子滚动节点的EdgeEffect为None。如Scroll嵌套List滚动时,List组件的edgeEffect属性需设置为EdgeEffect.None。 73 74## Scroller 75 76可滚动容器组件的控制器,可以将此组件绑定至容器组件,然后通过它控制容器组件的滚动,同一个控制器不可以控制多个容器组件,目前支持绑定到List、Scroll、ScrollBar、Grid、WaterFlow上。 77 78 79### 导入对象 80 81``` 82scroller: Scroller = new Scroller() 83``` 84 85 86### scrollTo 87 88scrollTo(value: { xOffset: number | string, yOffset: number | string, animation?: { duration?: number, curve?: Curve | ICurve } | boolean }): void 89 90 91滑动到指定位置。 92 93**参数:** 94 95| 参数名 | 参数类型 | 必填 | 参数描述 | 96| --------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ | 97| xOffset | number \| string | 是 | 水平滑动偏移。<br/>**说明:** <br/>该参数值不支持设置百分比。<br/>该参数值不支持设置百分比。<br/>当值小于0时,不带动画的滚动,按0处理。带动画的滚动,滚动到起始位置后停止。<br/>仅滚动轴为x轴时生效。 | 98| yOffset | number \| string | 是 | 垂直滑动偏移。<br/>**说明:** <br/>该参数值不支持设置百分比。<br/>该参数值不支持设置百分比。<br/>当值小于0时,不带动画的滚动,按0处理。带动画的滚动,滚动到起始位置后停止。<br/>仅滚动轴为y轴时生效。 | 99| animation | {duration?: number, curve?: [Curve](ts-appendix-enums.md#curve) \| [ICurve](../apis/js-apis-curve.md#icurve)<sup>10+ </sup>} \| boolean<sup>10+ </sup> | 否 | 动画配置:<br/>- duration: 滚动时长设置。<br/>- curve: 滚动曲线设置。<br/>- boolean: 使能默认弹簧动效。<br/>默认值: <br/>{<br/>duration: 1000,<br/>curve: Curve.Ease<br/>}<br/>boolean: false<br/>**说明:** <br/>设置为小于0的值时,按默认值显示。<br/>当前List、Scroll、Grid、WaterFlow均支持boolean类型和ICurve曲线。 | 100 101 102### scrollEdge 103 104scrollEdge(value: Edge): void 105 106 107滚动到容器边缘,不区分滚动轴方向,Edge.Top和Edge.Start表现相同,Edge.Bottom和Edge.End表现相同。 108 109**参数:** 110 111| 参数名 | 参数类型 | 必填 | 参数描述 | 112| ----- | ---- | ---- | --------- | 113| value | [Edge](ts-appendix-enums.md#edge) | 是 | 滚动到的边缘位置。 | 114 115 116### scrollPage 117 118scrollPage(value: { next: boolean, direction?: Axis }): void 119 120滚动到下一页或者上一页。 121 122**参数:** 123 124| 参数名 | 参数类型 | 必填 | 参数描述 | 125| --------- | ------- | ---- | ------------------------------ | 126| next | boolean | 是 | 是否向下翻页。true表示向下翻页,false表示向上翻页。 | 127| direction<sup>(deprecated) </sup> | [Axis](ts-appendix-enums.md#axis) | 否 | 设置滚动方向为水平或竖直方向。<br/> 从API version 9开始废弃 | 128 129 130### currentOffset 131 132currentOffset(): { xOffset: number, yOffset: number } 133 134 135返回当前的滚动偏移量。 136 137**返回值** 138 139| 类型 | 描述 | 140| ---------------------------------------------------------- | ------------------------------------------------------------ | 141| {<br/>xOffset: number,<br/>yOffset: number<br/>} | xOffset: 水平滑动偏移;<br/>yOffset: 竖直滑动偏移。<br/>**说明:** <br/>返回值单位为vp。 | 142 143 144### scrollToIndex 145 146scrollToIndex(value: number, smooth?: boolean, align?: ScrollAlign): void 147 148滑动到指定Index。 149 150开启smooth动效时,会对经过的所有item进行加载和布局计算,当大量加载item时会导致性能问题。 151 152 153> **说明:** 154> 155> 仅支持Grid、List、WaterFlow组件。 156 157**参数:** 158 159| 参数名 | 参数类型 | 必填 | 参数描述 | 160| --------------------- | -------- | ---- | ------------------------------------------------------------ | 161| value | number | 是 | 要滑动到的目标元素在当前容器中的索引值。 <br/>**说明:** <br/>value值设置成负值或者大于当前容器子组件的最大索引值,视为异常值,本次跳转不生效。 | 162| smooth | boolean | 否 | 设置滑动到列表项在列表中的索引值时是否有动效,true表示有动效,false表示没有动效。<br/>默认值:false。<br/>**说明:** <br/>当前仅List组件支持该参数。 | 163| align | [ScrollAlign](#scrollalign10枚举说明) | 否 | 指定滑动到的元素与当前容器的对齐方式。<br/>List中的默认值为:ScrollAlign.START。Grid中默认值为:ScrollAlign.AUTO<br/>**说明:** <br/>当前仅List、Grid组件支持该参数。 | 164 165### scrollBy<sup>9+</sup> 166 167scrollBy(dx: Length, dy: Length): void 168 169 170滑动指定距离。 171 172 173> **说明:** 174> 175> 支持Scroll、List、Grid、WaterFlow组件。 176 177**参数:** 178 179| 参数名 | 参数类型 | 必填 | 参数描述 | 180| ----- | ------ | ---- | ----------------- | 181| dx | Length | 是 | 水平方向滚动距离,不支持百分比形式。 | 182| dy | Length | 是 | 竖直方向滚动距离,不支持百分比形式。 | 183 184### isAtEnd<sup>10+</sup> 185 186isAtEnd(): boolean 187 188查询组件是否滚动到底部。 189 190> **说明:** 191> 192> 支持Scroll、List、Grid、WaterFlow组件。 193 194**返回值** 195 196| 类型 | 描述 | 197| ------- | -------- | 198| boolean | true表示组件已经滚动到底部,false表示组件还没滚动到底部。 | 199 200## ScrollAlign<sup>10+</sup>枚举说明 201 202| 名称 | 描述 | 203| ------ | ------------------------------ | 204| START | 首部对齐。指定item首部与List首部对齐。 | 205| CENTER | 居中对齐。指定item主轴方向居中对齐于List。 | 206| END | 尾部对齐。指定item尾部与List尾部对齐。 | 207| AUTO | 自动对齐。<br/>若指定item完全处于显示区,不做调整。否则依照滑动距离最短的原则,将指定item首部对齐或尾部对齐于List,使指定item完全处于显示区。| 208 209## NestedScrollOptions<sup>10+</sup>对象说明 210| 名称 | 类型 | 描述 | 211| ----- | ------ | ----------------- | 212| scrollForward | NestedScrollMode | 可滚动组件往末尾端滚动时的嵌套滚动选项。 | 213| scrollBackward | NestedScrollMode | 可滚动组件往起始端滚动时的嵌套滚动选项。 | 214 215## NestedScrollMode<sup>10+</sup>枚举说明 216| 名称 | 描述 | 217| ------ | ------------------------------ | 218| SELF_ONLY | 只自身滚动,不与父组件联动。 | 219| SELF_FIRST | 自身先滚动,自身滚动到边缘以后父组件滚动。父组件滚动到边缘以后,如果父组件有边缘效果,则父组件触发边缘效果,否则子组件触发边缘效果。 | 220| PARENT_FIRST | 父组件先滚动,父组件滚动到边缘以后自身滚动。自身滚动到边缘后,如果有边缘效果,会触发自身的边缘效果,否则触发父组件的边缘效果。 | 221| PARALLEL | 自身和父组件同时滚动,自身和父组件都到达边缘以后,如果自身有边缘效果,则自身触发边缘效果,否则父组件触发边缘效果。| 222 223## 示例 224### 示例1 225 226```ts 227// xxx.ets 228import Curves from '@ohos.curves' 229 230@Entry 231@Component 232struct ScrollExample { 233 scroller: Scroller = new Scroller() 234 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 235 236 build() { 237 Stack({ alignContent: Alignment.TopStart }) { 238 Scroll(this.scroller) { 239 Column() { 240 ForEach(this.arr, (item: number) => { 241 Text(item.toString()) 242 .width('90%') 243 .height(150) 244 .backgroundColor(0xFFFFFF) 245 .borderRadius(15) 246 .fontSize(16) 247 .textAlign(TextAlign.Center) 248 .margin({ top: 10 }) 249 }, (item: string) => item) 250 }.width('100%') 251 } 252 .scrollable(ScrollDirection.Vertical) // 滚动方向纵向 253 .scrollBar(BarState.On) // 滚动条常驻显示 254 .scrollBarColor(Color.Gray) // 滚动条颜色 255 .scrollBarWidth(10) // 滚动条宽度 256 .friction(0.6) 257 .edgeEffect(EdgeEffect.None) 258 .onScroll((xOffset: number, yOffset: number) => { 259 console.info(xOffset + ' ' + yOffset) 260 }) 261 .onScrollEdge((side: Edge) => { 262 console.info('To the edge') 263 }) 264 .onScrollStop(() => { 265 console.info('Scroll Stop') 266 }) 267 268 Button('scroll 150') 269 .height('5%') 270 .onClick(() => { // 点击后下滑指定距离150.0vp 271 this.scroller.scrollBy(0, 150) 272 }) 273 .margin({ top: 10, left: 20 }) 274 Button('scroll 100') 275 .height('5%') 276 .onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离 277 const yOffset: number = this.scroller.currentOffset().yOffset; 278 this.scroller.scrollTo({ xOffset: 0, yOffset: yOffset + 100 }) 279 }) 280 .margin({ top: 60, left: 20 }) 281 Button('scroll 100') 282 .height('5%') 283 .onClick(() => { // 点击后滑动到指定位置,即下滑100.0vp的距离,滑动过程配置有动画 284 let curve = Curves.interpolatingSpring(10, 1, 228, 30) //创建一个阶梯曲线 285 const yOffset: number = this.scroller.currentOffset().yOffset; 286 this.scroller.scrollTo({ xOffset: 0, yOffset: yOffset + 100, animation: { duration: 1000, curve: curve } }) 287 }) 288 .margin({ top: 110, left: 20 }) 289 Button('back top') 290 .height('5%') 291 .onClick(() => { // 点击后回到顶部 292 this.scroller.scrollEdge(Edge.Top) 293 }) 294 .margin({ top: 160, left: 20 }) 295 Button('next page') 296 .height('5%') 297 .onClick(() => { // 点击后滑到下一页 298 this.scroller.scrollPage({ next: true }) 299 }) 300 .margin({ top: 210, left: 20 }) 301 }.width('100%').height('100%').backgroundColor(0xDCDCDC) 302 } 303} 304``` 305 306 307 308### 示例2 309```ts 310@Entry 311@Component 312struct NestedScroll { 313 @State listPosition: number = 0; // 0代表滚动到List顶部,1代表中间值,2代表滚动到List底部。 314 private arr: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 315 private scrollerForScroll: Scroller = new Scroller() 316 private scrollerForList: Scroller = new Scroller() 317 318 build() { 319 Flex() { 320 Scroll(this.scrollerForScroll) { 321 Column() { 322 Text("Scroll Area") 323 .width("100%") 324 .height("40%") 325 .backgroundColor(0X330000FF) 326 .fontSize(16) 327 .textAlign(TextAlign.Center) 328 .onClick(() => { 329 this.scrollerForList.scrollToIndex(5) 330 }) 331 332 List({ space: 20, scroller: this.scrollerForList }) { 333 ForEach(this.arr, (item: number) => { 334 ListItem() { 335 Text("ListItem" + item) 336 .width("100%") 337 .height("100%") 338 .borderRadius(15) 339 .fontSize(16) 340 .textAlign(TextAlign.Center) 341 .backgroundColor(Color.White) 342 }.width("100%").height(100) 343 }, (item: string) => item) 344 } 345 .width("100%") 346 .height("50%") 347 .edgeEffect(EdgeEffect.None) 348 .friction(0.6) 349 .onReachStart(() => { 350 this.listPosition = 0 351 }) 352 .onReachEnd(() => { 353 this.listPosition = 2 354 }) 355 .onScrollFrameBegin((offset: number) => { 356 if ((this.listPosition == 0 && offset <= 0) || (this.listPosition == 2 && offset >= 0)) { 357 this.scrollerForScroll.scrollBy(0, offset) 358 return { offsetRemain: 0 } 359 } 360 this.listPosition = 1 361 return { offsetRemain: offset }; 362 }) 363 364 Text("Scroll Area") 365 .width("100%") 366 .height("40%") 367 .backgroundColor(0X330000FF) 368 .fontSize(16) 369 .textAlign(TextAlign.Center) 370 } 371 } 372 .width("100%").height("100%") 373 }.width('100%').height('100%').backgroundColor(0xDCDCDC).padding(20) 374 } 375} 376``` 377 378 379 380### 示例3 381```ts 382@Entry 383@Component 384struct StickyNestedScroll { 385 @State arr: number[] = [] 386 387 @Styles 388 listCard() { 389 .backgroundColor(Color.White) 390 .height(72) 391 .width("100%") 392 .borderRadius(12) 393 } 394 395 build() { 396 Scroll() { 397 Column() { 398 Text("Scroll Area") 399 .width("100%") 400 .height("40%") 401 .backgroundColor('#0080DC') 402 .textAlign(TextAlign.Center) 403 Tabs({ barPosition: BarPosition.Start }) { 404 TabContent() { 405 List({ space: 10 }) { 406 ForEach(this.arr, (item: number) => { 407 ListItem() { 408 Text("item" + item) 409 .fontSize(16) 410 }.listCard() 411 }, (item: string) => item) 412 }.width("100%") 413 .edgeEffect(EdgeEffect.Spring) 414 .nestedScroll({ 415 scrollForward: NestedScrollMode.PARENT_FIRST, 416 scrollBackward: NestedScrollMode.SELF_FIRST 417 }) 418 }.tabBar("Tab1") 419 420 TabContent() { 421 }.tabBar("Tab2") 422 } 423 .vertical(false) 424 .height("100%") 425 }.width("100%") 426 } 427 .edgeEffect(EdgeEffect.Spring) 428 .friction(0.6) 429 .backgroundColor('#DCDCDC') 430 .scrollBar(BarState.Off) 431 .width('100%') 432 .height('100%') 433 } 434 435 aboutToAppear() { 436 for (let i = 0; i < 30; i++) { 437 this.arr.push(i) 438 } 439 } 440} 441``` 442 443### 示例4 444```ts 445@Entry 446@Component 447struct Index { 448 scroller: Scroller = new Scroller; 449 private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15] 450 build() { 451 Scroll(this.scroller) { 452 Column() { 453 ForEach(this.arr, (item: number) => { 454 Text(item.toString()) 455 .width('90%') 456 .height(200) 457 .backgroundColor(0xFFFFFF) 458 .borderWidth(1) 459 .borderColor(Color.Black) 460 .borderRadius(15) 461 .fontSize(16) 462 .textAlign(TextAlign.Center) 463 }, (item: string) => item) 464 }.width('100%').backgroundColor(0xDCDCDC) 465 } 466 .backgroundColor(Color.Yellow) 467 .height('100%') 468 .edgeEffect(EdgeEffect.Spring) 469 .scrollSnap({snapAlign:ScrollSnapAlign.START, snapPagination:400, enableSnapToStart:true, enableSnapToEnd:true}) 470 } 471} 472``` 473 474