前言
这几天做案例有一个想法,使用Swiper实现当前视窗的图片缩放效果。
环境及工具
HarmonyOS 5.0.0 Release
DevEcoStudio
适用于HarmonyOS Next原生开发
效果图
拓展
.nextMargin(数值)
设置后边距,用于露出后一项的一小部分。
官方文档-->developer.huawei.com/consumer/cn…
.prevMargin(数值)
设置前边距,用于露出前一项的一小部分。
官方文档-->developer.huawei.com/consumer/cn…
当主轴方向为横向布局时,nextMargin/prevMargin中任意一个大于子组件测算的宽度,nextMargin和prevMargin均不显示。
当主轴方向为纵向布局时,nextMargin/prevMargin中任意一个大于子组件测算的高度,nextMargin和prevMargin均不显示。
过程1(错误思路)
刚开始的思路是使用动画+缩放实现这一效果,三张轮播图组成一个数组,下标分别是0,1,2 。
通过获取数组索引然后执行缩放再添加动画使过渡效果更加平滑,使用onContentDidScroll函数监听轮播图。然后通过使用三元运算符,当curIndex == index时(即抓取到视窗的索引值等于图片索引值时)使用缩放(.scale({ y: this.curIndex == 0 ? 1.2: 1 }))完成目标效果。最终发现,在获取视窗内图片的索引时,该回调函数逐帧抓取索引值,导致过程非常的长,需要进行优化。
onContentDidScroll
监听Swiper页面滑动事件。
使用说明:
1、循环场景下,设置prevMargin和nextMargin属性,使得Swiper前后端显示同一页面时,该接口不生效。
2、在页面滑动过程中,会对视窗内所有页面逐帧触发ContentDidScrollCallback回调。例如,当视窗内有下标为0、1的两个页面时,会每帧触发两次index值分别为0和1的回调。
3、设置displayCount属性的swipeByGroup参数为true时,若同组中至少有一个页面在视窗内时,则会对同组中所有页面触发回调。
官方文档=>developer.huawei.com/consumer/cn…
代码:
Swiper() {
Image(imageUrl)
.height(160)
.borderRadius(10)
.scale({ y: this.curIndex === 1 ? 1.5 : 1 })
Image(imageUrl)
.height(160)
.borderRadius(10)
.scale({ y: this.curIndex === 1 ? 1.5 : 1 })
Image(imageUrl)
.height(160)
.borderRadius(10)
.scale({ y: this.curIndex === 2 ? 1.5 : 1 })
}
.padding(10)
.onContentDidScroll(curindex => {
console.log(curindex.toString())
this.curIndex = curindex
})
.prevMargin(15)
.nextMargin(15)
.itemSpace(10)
.autoPlay(true)
.interval(5000)
.animation({})
.duration(200)
.indicator(
DotIndicator.dot()
.selectedColor('#fb6a4d')
.color('#ffbcae')
)
效果图:
解决方案1导致轮播图滑入视窗的时候没有完成动画渲染,只有在离开的时候发生动画渲染。并且,swiper组件是固定了宽高的,实现思路不应该是放大,而是将还未进入视窗的图片进行缩小。
该回调函数获取索引
过程2
后经过波哥指导,有更加合适的解决方案,通过两个函数分别获得轮播图滑入视窗以及滑出视窗时的index值。在轮播图滑入视窗的时刻,获取该图片的索引,然后进行判断,然后在图片滑入的时刻,直接进行赋值。
onAnimationStart
切换动画开始时触发该回调。参数为动画开始前的index值(不是最终结束动画的index值),多列Swiper时,index为最左侧组件的索引。
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| index | number | 是 | 当前显示元素的索引。 |
| targetIndex10+ | number | 是 | 切换动画目标元素的索引。 |
| extraInfo10+ | SwiperAnimationEvent | 是 | 动画相关信息,包括主轴方向上当前显示元素和目标元素相对Swiper起始位置的位移,以及离手速度。 |
onAnimationEnd
切换动画结束时触发该回调。
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| index | number | 是 | 当前显示元素的索引。 |
| extraInfo10+ | SwiperAnimationEvent | 是 | 动画相关信息,只返回主轴方向上当前显示元素相对于Swiper起始位置的位移。 |
实现代码
Swiper() {
Image(imageUrl)
.height(180)
.borderRadius(10)
.scale({ y: this.curIndex !== 0 ? 0.8 : 1 })
Image(imageUrl)
.height(180)
.borderRadius(10)
.scale({ y: this.curIndex !== 1 ? 0.8 : 1 })
Image(imageUrl)
.height(180)
.borderRadius(10)
.scale({ y: this.curIndex !== 2 ? 0.8 : 1 })
}
.padding(10)
// 切换动画开始时触发该回调。
.onAnimationStart(index => {
console.log('start=>', index)
console.log("start=>", this.curIndex)
this.curIndex = index + 1
})
// 切换动画结束时触发该回调。
.onAnimationEnd(index => {
console.log('end=>', index)
console.log("end=>", this.curIndex)
this.curIndex = index
})
.prevMargin(15)
.nextMargin(15)
.itemSpace(10)
.autoPlay(true)
.interval(5000)
.animation({})
.duration(200)
.indicator(
DotIndicator.dot()
.selectedColor('#fb6a4d')
.color('#ffbcae')
)
效果图
打印滑入滑出时的索引