HarmonyOS Next 开发小尝试——轮播图视窗图片放大效果

991 阅读4分钟

前言

这几天做案例有一个想法,使用Swiper实现当前视窗的图片缩放效果。

环境及工具

HarmonyOS 5.0.0 Release
DevEcoStudio
适用于HarmonyOS Next原生开发

效果图

轮播图缩放.gif

拓展

.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.gif
该回调函数获取索引 索引抓取1.gif

过程2

后经过波哥指导,有更加合适的解决方案,通过两个函数分别获得轮播图滑入视窗以及滑出视窗时的index值。在轮播图滑入视窗的时刻,获取该图片的索引,然后进行判断,然后在图片滑入的时刻,直接进行赋值。

onAnimationStart

切换动画开始时触发该回调。参数为动画开始前的index值(不是最终结束动画的index值),多列Swiper时,index为最左侧组件的索引。

参数名类型必填说明
indexnumber当前显示元素的索引。
targetIndex10+number切换动画目标元素的索引。
extraInfo10+SwiperAnimationEvent动画相关信息,包括主轴方向上当前显示元素和目标元素相对Swiper起始位置的位移,以及离手速度。

onAnimationEnd

切换动画结束时触发该回调。

参数名类型必填说明
indexnumber当前显示元素的索引。
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')
)

效果图

轮播图缩放.gif
打印滑入滑出时的索引 获取索引3.gif