淘宝小程序开发文档江东seo做关键词优化
#技术栈Vue3+TypeScript#
相比大家没少见过这个的效果:
作为视觉效果是很不错的 同时实现也很简单,本质是封装一个Vue指令
1,创建指令文件 src / directives / vSlidenIn.ts
import type { Directive } from 'vue'const vSlideIn: Directive = {mounted(element) {// 组件记载后会触发的逻辑}
}export default vSlideIn
2,Animation API 添加入场动画
同学们可能会想到改变stye或者class类,这些都是偏麻烦的,入侵性太大的指令泛用性会很低。我们这里使用Animation API封装动画,保证复用性
const MOVE_DISTANCE = 8
const MOVE_DURATION = 1000......const vSlideIn: Directive = {mounted(element) {const animation = element.animate([{transform: `translateY(${MOVE_DISTANCE}rem)`,opacity: 0,},{transform: 'translateY(0)',opacity: 1,},], {duration: MOVE_DURATION,easing: 'ease'})animation.pause()}
}.......
这样是实现了动画,但动画会在所有组件出现时执行---那该如何让每个元素被滑动到时执行呢?请问下面
3,Intersection Observer API 判断执行时机
调用其中的IntersectionObserver去监听使用该指令的元素,通过内置返回的元素的isInterscting值判断元素是否与窗口重叠
......const ob = new IntersectionObserver(entries => {// entries是一起监听的所有元素,是数组for (const entry of entries) {if (entry.isIntersecting){const element = entry.target// 执行动画逻辑}}
})......const vSlideIn: Directive = {mounted(element) {const animation = element.animate([{transform: `translateY(${MOVE_DISTANCE}rem)`,opacity: 0,},{transform: 'translateY(0)',opacity: 1,},], {duration: MOVE_DURATION,easing: 'ease'})ob.observe(element) // 监听},unmounted(element) {ob.unobserve(element) // 记得组件销毁后取消监听}
}
但是,如何让每个元素和执行的动画对上号呢?
4,New Map存放映射
在元素初始化时 暂停后动画pause() 全局new一个WeakMap来存放元素及其对应的动画 在监听函数中调用map找到对应的animation进行执行
// 滑动入场指令
import type { Directive } from 'vue'const MOVE_DISTANCE = 8
const MOVE_DURATION = 1000
const animationMap = new WeakMap()const ob = new IntersectionObserver(entries => {// entries是一个重叠状态的一个数组for (const entry of entries) {if (entry.isIntersecting){const element = entry.targetconst animation = animationMap.get(element)if (animation) {animation.play()ob.unobserve(element)}}}
})const vSlideIn: Directive = {mounted(element) {const animation = element.animate([{transform: `translateY(${MOVE_DISTANCE}rem)`,opacity: 0,},{transform: 'translateY(0)',opacity: 1,},], {duration: MOVE_DURATION,easing: 'ease'})animation.pause()animationMap.set(element, animation)ob.observe(element)},unmounted(element) {ob.unobserve(element)}
}export default vSlideIn
5,组件的应用
开袋即食,引入后在元素内加入v-slide-in即可,Vue会自己编译的
<template><main class="space-y-10"><article v-for="i in 10" :key="i" class="w-100 h-50 bg-red-500 shadow-md text-center leading-50 mx-auto text-white text-2xl" v-slide-in><h1>测试{{ i }}</h1></article></main>
</template><script setup lang="ts">
import vSlideIn from '@/directives/vSlideIn'</script>