前端那些花里胡哨的动画效果—手势无缝轮播
前言
这次的动效属实是眼高手低了,之前在PC端也手撸过无缝轮播图,只不过已经有一段时间了,这次想着无非是移动端,换成touch事件控制轮播而已。结果没想到费了我两个晚上都在研究原理....
实际上移动端的轮播效果swiper上有很多好看的示例,这次的效果也是其中之一,只不过抱着学习的态度还是自己手动封装一个吧,而且原博客项目的轮播更加麻烦,在图片视口展示的三张图片切换时scale也是动态计算改变的,也就是说每次轮播都要动态计算三张图片的位置,通过位移比例来计算,只能说是头皮发麻一点思路都没有,最终还是放弃了,但是整体效果出来还算是不错的。
效果
手势轮播
无缝轮播
分析
这次的无缝轮播图难点主要有两个:
- 因为我想封装成组件库一样,通过封装swipe容器组件和swipe-item组件实现轮播,那少不了的就是插槽的使用,而这里最头疼的地方就是item组件需要访问容器组件的动态数据来设置样式
- 无缝轮播时由于首页展示的是三张图片而不是单独一张占满屏幕,因此原来的无缝轮播切换方案可能不会适应,因此需要采用新的方案
首先对于移动端的手势几个事件:touchStart、touchMove、touchEnd必须要提前了解,通过其传递的TouchEvent来计算位移的距离。既然封装成组件就要功能划分清楚,swipe容器组件主要用来绑定这些touch事件并控制移动,而item组件则需要改变过渡的样式,比如上面展示的scale大小改变以及无缝轮播的位移改变
实现
首先第一大难题:插槽,容器组件怎么拿到item组件的DOM实例来计算宽度?item组件怎样拿到容器组件的数据?通过getCurrentInstance API 获取到原DOM实例,instance.slots.default()[0].children能够拿到插槽内容,但是拿到的内容上面el是空的,无法拿到真正的DOM实例。打印出来instance挨个找真的头疼,但在实例上肯定是能够找的到这是毋庸置疑的,后来突然想到了Vant组件库的实现,就去扒了扒Vant swipe的源码,虽然使用tsx写的,但还是让我找到了点东西:
可以看到在swipe和swipe-item使用到了两个hook,useChildren、useParent,很明显就是通过这两个hook实现父子组件的信息共享:
源代码这里就不展示了,感兴趣的可以自己去扒扒,我这里是直接cv过来稍微改改类型就使用了,像useChildren这里,可以看到源码写了个递归实例上的一个subTree属性,这个上面就含有想要的DOM实例,再自己进行flat平铺:
第二大难题:无缝轮播,这里是参考原博主的实现,在swipe-item上巧用定位left实现,具体实现方法如下,根据当前处于位置,比如第一张,那么你的左侧需要展示最后一张来实现无缝轮播,而最后一张就需要定位到容器左侧,最后一张同理:
为什么必须要设置两张而不是一张?实践出真知,无缝切换时效果欠佳,这里就不再语言赘述了....
其次就是关于效果问题了,比如这里设置了一个过渡延迟,主要是由于无缝衔接时牵扯到left改变,这部分的过渡效果需要定时器限制
其实还有很多细节,但是文字阐述比较困难,剩下的大部分就是轮播的基本操作,下面放下组件的源代码,代码比较堆屎山,将就着看吧,注意需要自己设置容器大小宽高等:
