vue.js 3.2.22:用useIntersectionObserver实现滑动到div可见时才运行css动画(@vueuse/core@7.0.3)
一,安装所需的库@vueuse/core
liuhongdi@lhdpc:/data/vue/lazy$ npm install --save @vueuse/core
说明:刘宏缔的架构森林是一个专注架构的博客,
网站:https://blog.imgtouch.com
本文: https://blog.imgtouch.com/index.php/2023/06/01/vue-js-3-2-22-yong-useintersectionobserver-shi-xian-hua/
对应的源码可以访问这里获取: https://github.com/liuhongdi/
或: https://gitee.com/liuhongdi
说明:作者:刘宏缔 邮箱: 371125307@qq.com
二,编写js代码
Ani.vue
<template> <div> <div> <h3 :ref="refset" class="red-bg-title animate_element" data-animate="bounceIn,0.6s,0.3s">现金表标题一 </h3> <div style="width:640px;position: relative;margin: 0 auto;"> <div class="title"> <h4 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,0.4s" >经营活动现金流入小计</h4> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,0.8s" >数值(亿元)</p> </div> <div class="data-info"> <div class="part1"> <h5 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1s">366.26</h5> <p :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1.2s">2021H1</p> </div> <div class="part2"> <h5 :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.3s">303.87</h5> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.5s">2020H1</p> </div> </div> <div class="graph"> <p :ref="refset" class="increase-charac animate_element" data-animate="fadeInUp,0.6s,1.6s" >同比增长</p> <p :ref="refset" class="increase-num animate_element increase-icon" data-animate="fadeInUp,0.6s,1.8s"><span></span>20.53%</p> </div> </div> </div> <div> <h3 :ref="refset" class="red-bg-title animate_element" data-animate="bounceIn,0.6s,0.3s">现金表标题二 </h3> <div style="width:640px;position: relative;margin: 0 auto;"> <div class="title"> <h4 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,0.4s" >经营活动现金流入小计</h4> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,0.8s" >数值(亿元)</p> </div> <div class="data-info"> <div class="part1"> <h5 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1s">366.26</h5> <p :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1.2s">2021H1</p> </div> <div class="part2"> <h5 :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.3s">303.87</h5> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.5s">2020H1</p> </div> </div> <div class="graph"> <p :ref="refset" class="increase-charac animate_element" data-animate="fadeInUp,0.6s,1.6s" >同比增长</p> <p :ref="refset" class="increase-num animate_element increase-icon" data-animate="fadeInUp,0.6s,1.8s"><span></span>20.53%</p> </div> </div> </div> <div> <h3 :ref="refset" class="red-bg-title animate_element" data-animate="bounceIn,0.6s,0.3s">现金表标题三 </h3> <div style="width:640px;position: relative;margin: 0 auto;"> <div class="title"> <h4 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,0.4s" >经营活动现金流入小计</h4> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,0.8s" >数值(亿元)</p> </div> <div class="data-info"> <div class="part1"> <h5 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1s">366.26</h5> <p :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1.2s">2021H1</p> </div> <div class="part2"> <h5 :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.3s">303.87</h5> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.5s">2020H1</p> </div> </div> <div class="graph"> <p :ref="refset" class="increase-charac animate_element" data-animate="fadeInUp,0.6s,1.6s" >同比增长</p> <p :ref="refset" class="increase-num animate_element increase-icon" data-animate="fadeInUp,0.6s,1.8s"><span></span>20.53%</p> </div> </div> </div> <div> <h3 :ref="refset" class="red-bg-title animate_element" data-animate="bounceIn,0.6s,0.3s">现金表标题四 </h3> <div style="width:640px;position: relative;margin: 0 auto;"> <div class="title"> <h4 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,0.4s" >经营活动现金流入小计</h4> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,0.8s" >数值(亿元)</p> </div> <div class="data-info"> <div class="part1"> <h5 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1s">366.26</h5> <p :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1.2s">2021H1</p> </div> <div class="part2"> <h5 :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.3s">303.87</h5> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.5s">2020H1</p> </div> </div> <div class="graph"> <p :ref="refset" class="increase-charac animate_element" data-animate="fadeInUp,0.6s,1.6s" >同比增长</p> <p :ref="refset" class="increase-num animate_element increase-icon" data-animate="fadeInUp,0.6s,1.8s"><span></span>20.53%</p> </div> </div> </div> <div> <h3 :ref="refset" class="red-bg-title animate_element" data-animate="bounceIn,0.6s,0.3s">现金表标题五 </h3> <div style="width:640px;position: relative;margin: 0 auto;"> <div class="title"> <h4 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,0.4s" >经营活动现金流入小计</h4> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,0.8s" >数值(亿元)</p> </div> <div class="data-info"> <div class="part1"> <h5 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1s">366.26</h5> <p :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1.2s">2021H1</p> </div> <div class="part2"> <h5 :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.3s">303.87</h5> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.5s">2020H1</p> </div> </div> <div class="graph"> <p :ref="refset" class="increase-charac animate_element" data-animate="fadeInUp,0.6s,1.6s" >同比增长</p> <p :ref="refset" class="increase-num animate_element increase-icon" data-animate="fadeInUp,0.6s,1.8s"><span></span>20.53%</p> </div> </div> </div> <div> <h3 :ref="refset" class="red-bg-title animate_element" data-animate="bounceIn,0.6s,0.3s">现金表标题六 </h3> <div style="width:640px;position: relative;margin: 0 auto;"> <div class="title"> <h4 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,0.4s" >经营活动现金流入小计</h4> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,0.8s" >数值(亿元)</p> </div> <div class="data-info"> <div class="part1"> <h5 :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1s">366.26</h5> <p :ref="refset" class="animate_element" data-animate="fadeInLeft,0.6s,1.2s">2021H1</p> </div> <div class="part2"> <h5 :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.3s">303.87</h5> <p :ref="refset" class="animate_element" data-animate="fadeInRight,0.6s,1.5s">2020H1</p> </div> </div> <div class="graph"> <p :ref="refset" class="increase-charac animate_element" data-animate="fadeInUp,0.6s,1.6s" >同比增长</p> <p :ref="refset" class="increase-num animate_element increase-icon" data-animate="fadeInUp,0.6s,1.8s"><span></span>20.53%</p> </div> </div> </div> </div> </template> <script> import {onMounted} from "vue"; import {useIntersectionObserver} from "@vueuse/core"; export default { name: "Ani", setup() { //初始化列表 let itemRefs = [] const refset = el => { if (el) { itemRefs.push(el) } } //添加监控 //挂载后 onMounted(()=>{ //为各个div添加监控事件 console.log("onMounted div的数量:"+itemRefs.length); for (let i=0;i<itemRefs.length;i++) { //console.log(itemRefs[i]); useIntersectionObserver(itemRefs[i], ([{ isIntersecting }]) => { // 如果target对应的DOM进入可视区,那么该回调函数就触发 if (isIntersecting) { // 被监听的DOM进入了可视区:此时调用接口获取数据;停止继续监听 stop() if (itemRefs[i].dataset.animate !== '') { console.log("第"+i+"个div已显示"); //修改背景色 let ani = itemRefs[i].dataset.animate; let arrAni = ani.split(","); console.log(arrAni[0]); console.log(arrAni[1]); console.log(arrAni[2]); let style="animation-name: "+arrAni[0]+"; animation-duration: "+arrAni[1]+"; animation-delay: "+arrAni[2]+";" //itemRefs[i].dataset.bg = 1; itemRefs[i].style = style; } } },{ threshold: 0 }) } }) return { refset, } } } </script> <style> .animate_element { margin:0px; position: inherit; opacity: 0; animation-fill-mode: forwards; animation-timing-function: linear; } .red-bg-title { position: relative; width: 612px; height: 88px; font-size: 54px; font-weight: bold; border-radius: 50px; margin: 0 auto; background: #ca312b; color: #ffffff; text-align: center; line-height: 88px; box-shadow: 0 10px 10px rgb(244 99 94 / 50%); } .red-bg-title:before { left: 25px; } .red-bg-title:before, .red-bg-title:after { content: ''; display: block; position: absolute; top: 20px; /*margin-top: 25px;*/ width: 73px; height: 49px; background: url(https://zsl.p5w.net/home/images/twelve_blade/title-triangle-icon.png) no-repeat; background-size: cover; } .red-bg-title:after { right: 25px; } @keyframes mymove { from {top:0px;} to {top:200px;} } @keyframes bounceIn { 0% { opacity: 0; transform: scale(.3); } 50% { opacity: 1; transform: scale(1.05); } 70% { transform: scale(.9); } 100% { opacity: 1; transform: scale(1); } } .title { height: 80px; line-height: 80px; padding: 0 40px; overflow: hidden; border-bottom: 1px solid #ec6941; } .title h4 { float: left; font-size: 28px; color: #333333; } .swiper-container { margin: 0 auto; position: relative; overflow: hidden; list-style: none; padding: 0; z-index: 1; } @keyframes fadeInLeft { 0% { opacity: 0; transform: translateX(-20px); } 100% { opacity: 1; transform: translateX(0); } } .title p { float: right; font-size: 26px; color: #999999; } @keyframes fadeInRight { 0% { opacity: 0; transform: translateX(20px); } 100% { opacity: 1; transform: translateX(0); } } .data-info { display: flex; text-align: center; align-items: center; height: 130px; } .data-info .part2 { width:50%; flex: 1; } .data-info .part1 { width:50%; } .data-info .part1 h5 { color: #ec6941; } .data-info h5 { font-size: 54px; font-weight: bold; } .data-info p { font-size: 28px; color: #666666; } /*--------------------------------graph--------------------------------------*/ .graph { width: 100%; height: 372px; background-color: #eeeeee; text-align: center; margin-top: 24px; /*line-height: 130px;*/ margin: 0; padding: 0; } .graph .increase-charac { font-size: 28px; color: #666666; padding-top: 20px; } @keyframes fadeInUp { 0% { opacity: 0; transform: translateY(20px); } 100% { opacity: 1; transform: translateY(0); } } .increase-icon { position: relative; font-size: 62px; color: #ea441c; } .increase-icon span { display: inline-block; width: 38px; height: 51px; background: url(https://zsl.p5w.net/home/images/twelve_blade/increase-icon@2x.png) no-repeat; background-size: cover; margin-right: 10px; } </style>
三,测试效果
四,查看vue和vueuse的版本
liuhongdi@lhdpc:/data/vue/lazy$ npm list vue lazy@0.1.0 /data/vue/lazy ├─┬ @vue/cli-plugin-babel@4.5.15 │ └─┬ @vue/babel-preset-app@4.5.15 │ └── vue@3.2.22 deduped ├─┬ @vueuse/core@7.0.3 │ ├─┬ @vueuse/shared@7.0.3 │ │ └── vue@3.2.22 deduped │ ├─┬ vue-demi@0.12.1 │ │ └── vue@3.2.22 deduped │ └── vue@3.2.22 deduped └─┬ vue@3.2.22 └─┬ @vue/server-renderer@3.2.22 └── vue@3.2.22 deduped