Vue图片切换过渡设计
Vue图片切换过渡效果设计Time:2021-3-26前言不要拦着我!我要先大吹一波Vue,永远的神!Vue下,不用jQuery!轻松一点代码和样式的设计就搞定了图片自然过渡的切换!是的,没有使用vegas.js,没有使用backstretch.js,没有任何jQuery插件!咳咳,总之就是非常厉害!在搭建个人博客的路上,为了搞这个图片自然过渡,可是烦扰了我三天之多啊,终于,在不断的探索与尝试之下
Vue图片切换过渡效果设计
Time:2021-3-26
前言
不要拦着我!我要先大吹一波Vue,永远的神!Vue下,不用jQuery!轻松一点代码和样式的设计就搞定了图片自然过渡的切换!是的,没有使用vegas.js,没有使用backstretch.js,没有任何jQuery插件!咳咳,总之就是非常厉害!
在搭建个人博客的路上,为了搞这个图片自然过渡,可是烦扰了我三天之多啊,终于,在不断的探索与尝试之下,找到了最优解(应该是)。
Author:雾雨霜星
欢迎来我的网站学习:
https://www.shuangxing.top/#/passage?id=17
问题的来由
对于图片的切换,通过控制src属性或者设置背景控制style的background-image属性,可以实现图片的切换。但是直接切换,会显得非常生硬而不自然。因此,我就想寻找图片切换过渡的效果。包括:淡入淡出、自然渐变过渡。
可惜啊,网上没找到好办法,查到的都是没什么通用性的方法或者根本没效果,别人告诉我的方法都是需要使用jQuery的插件的。
于是,只好再去研究Vue了。而官方文档中就要关于过渡和动画的内容。
环境:VueCLI4.5
关于环境:只要有Vue包,使用Vue的过渡和动画都是可以的,环境版本不是特别重要。
官方文档
-
Vue过渡与动画:https://cn.vuejs.org/v2/guide/transitions.html
-
Animate.css官网:http://www.animate.net.cn/
使用原生JS实现图片淡入淡出的切换效果
因为使用了Vue,我就没打算再安装jQuery了,虽然真的jQuery这么多插件库,太香了,但是为了锻炼自己,还是决定自己挑战一下,于是我首先想到的就是,使用js,定时器定时切换img的src,然后定时设置透明度,逐渐下降和逐渐提高。
基本思路就是,img的src和style使用v-bind指令绑定,然后在mounted中设置一个周期定时器,定时器中设置定时器来改变当前的透明度,直到透明度为0,改变相应的src变量切换路径,然后继续定时修改透明度,使用这种一层又一层的定时器,定时器中设置定时器的方法。
具体的代码如下:
<template>
<div class="bg">
<img class="HeadImage" :src="HeadImage" :style="ImgStyle"/>
</div>
</template>
<script>
import Wave from "@/components/Wave";
const ImageGroup_DongFang = [
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(1).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(2).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(3).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(4).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(6).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(7).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(8).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(9).png",
];
export default {
name: "HomeBackground",
data (){
return{
HeadImage:"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(9).png",
ImgStyle:"opacity:1.0",
}
},
methods:{
},
mounted() {
const HeadImageCount = 8;
let StartIntervalTime = 10000;
const ChangeBlankKeepTime = 700;
const ChangeIntervalTime = 500;
const TimeBatisPlus = 1000;
const OpticyStepSize = 0.3;
let _this = this;
let index = 0;
let OpticyIndex = 1.0;
let timer = setInterval(() => {
OpticyIndex = OpticyIndex-OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {OpticyIndex = OpticyIndex-OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {OpticyIndex = OpticyIndex-OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {OpticyIndex = 0;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {
if(index===HeadImageCount){
index = 0;
}
else{
index = index + 1;
}
setTimeout(() => {OpticyIndex = OpticyIndex+0.1;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
_this.HeadImage = ImageGroup_DongFang[index];
setTimeout(() => {OpticyIndex = OpticyIndex+OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {OpticyIndex = OpticyIndex+OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {OpticyIndex = 1;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
setTimeout(() => {
},ChangeIntervalTime);
},ChangeIntervalTime);
},ChangeIntervalTime);
},ChangeIntervalTime);
},ChangeBlankKeepTime);
},ChangeBlankKeepTime);
},ChangeIntervalTime)
},ChangeIntervalTime);
},ChangeIntervalTime+TimeBatisPlus);
}, StartIntervalTime);
},
}
</script>
<style scoped>
.bg{
position: absolute;
top: 0;
left: 0;
width:100%;
z-index: -1;
}
.HeadImage{
width:100%;
transition: all 2s 0s;
}
</style>
简称,千层饼!恐怖如斯,看到都开始瑟瑟发抖了吧。
首先使用周期定时器,基本格式如下:
setInterval(() => { ... }, "time" )
使用了箭头函数,括号里面是定时器到超时后后需要执行的操作,time是定时的时间。
然后先设置了透明度:
OpticyIndex = OpticyIndex-OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
注意,我的_this.ImgStyle就是绑定了img元素的style属性的data变量。
OpticyStepSize是每次变化透明度的步长,OpticyIndex就是计算得到的当前透明度。
然后再设置定时器,超时后再次变透明度:
setTimeout(() => {OpticyIndex = OpticyIndex-OpticyStepSize;_this.ImgStyle = "opacity:"+(OpticyIndex).toString();
... ...
注意不是周期定时器。
然后后面继续重复上述操作即可,直到透明度到了你想要的最低,切换路径:
_this.HeadImage = ImageGroup_DongFang[index];
HeadImage是我绑定了img元素的src属性的data变量,ImageGroup_DongFang是一个存放了图片路径的数组。
切换后也继续设置定时器,逐渐提高透明度就可以得到淡入淡出的效果了。
注意可以中间有段时间留白,即透明度为0的时间稍微留长,切换效果会显得更加好。
效果是有的,而且很明显,降低每次衰减和增加的透明度,就可以看起来更加连续自然。时间的设置也需要好好测试才行。
Vue过渡与动画实现图片自然切换
正题在此。上面的方法终究是效果看起来欠缺了一些,没有那么完美。于是需要寻找更好的方法了。
在Vue的官方文档中有关于过渡的部分,一开始我觉得,应该没这么有用,直到最后才发现,太强了呀!
基本思路:使用Vue的过渡功能实现淡出,使用Vue的动画功能,结合Animate.css的fadeIn效果来实现淡入功能。另外一说,Animate.css也有淡出的动画效果,fadeOut。
不得不说,Animate.css配合Vue的过渡组件,真是无敌的组合,使用方便而功能多样。
我的代码如下:
<template>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }">
<img class="img" :src="src_group[0]" v-if="ShowFlagGroup[0] === true" key="img1"/>
</transition>
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }">
<img class="img" :src="src_group[1]" v-if="ShowFlagGroup[1] === true" key="img2"/>
</transition>
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }">
<img class="img" :src="src_group[2]" v-if="ShowFlagGroup[2] === true" key="img3"/>
</transition>
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }">
<img class="img" :src="src_group[3]" v-if="ShowFlagGroup[3] === true" key="img4"/>
</transition>
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }">
<img id="headimg5" class="img" :src="src_group[4]" v-if="ShowFlagGroup[4] === true" key="img5"/>
</transition>
</template>
<script>
export default {
name: "TransBackGround",
data (){
return{
src_group:[
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(1).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(2).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(3).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(4).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png",
],
ShowFlagGroup:[true,false,false,false,false],
show_index:0,
show:true,
}
},
methods:{
},
mounted() {
const img_count=5;
let _this = this;
let index = 0;
let last_index = 0;
let timer = setInterval(() => {
last_index = index;
if(index===img_count-1){
index=0;
}
else {
index = index + 1;
}
_this.ShowFlagGroup[last_index]=false;
_this.ShowFlagGroup[index]=true;
},5000);
}
}
</script>
<style scoped>
.img{
position: absolute;
left: 0;
top: 0;
width: 100%;
}
.fade-enter-active {
transition: all 3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.fade-leave-active {
transition: all 3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
</style>
上面之所以使用如此多的img标签,是因为Vue中 transition标签的效果要求,要标签的生成与删除才可以发挥出Vue过渡的效果,因此我这里给每个图片都设置了标签,这样就每个图片元素单独设定生成和删除了。自然,机智的我已经想出来不用这么多img标签来实现的方法,将在后面记录。
-
transition标签的使用:
用途:用于实现元素的过渡效果。具体是,使用v-if指令绑定的元素,在v-if为真和v-if为假时,进行元素生成和删除的过渡效果。
使用方法:直接使用transition标签,每个里面只可以有一个元素(可以多个但是建议不要这样搞)。
例如:
<transition name="fade" mode="out-in"> <img class="img" :src="src_group[0]" v-if="ShowFlagGroup[0] === true"/> </transition>
设置:
-
通过设置过渡的类的样式来确定具体的过渡效果
包括:v-enter、v-enter-active、v-enter-to、v-leave、v-leave-active、v-leave-to,具体含义见官方文档说明。
通过在style中设置的,例如:
.fade-enter-active{ transition: opacity 5s; } .fade-leave-active { transition: opacity 3s; } .fade-leave-to { opacity: 0; }
在相应类中指定相应要使用过渡效果的css样式即可。
-
通过设置mode来确定过渡类型
有out-in和in-out两种,就是确定过渡时,新生成的元素与旧的要被删除的元素,各自过渡效果的先后。
设置如下,直接在标签中设置,例如:
<transition name="fade" mode="out-in">
注意:如果transition标签设置了name,那么相应的过渡的class就会变成这样:name–enter-active
例如,如下因为设置了transition标签的name是fade,所以相应的过渡的class是:
.fade-enter-active { transition: all 3s cubic-bezier(1.0, 0.5, 0.8, 1.0); }
其余设置详见文档。
-
-
引入Animate.css:
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
-
在过渡标签中使用Animate.css:
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn"> <img id="headimg5" class="img" :src="src_group[4]" v-if="ShowFlagGroup[4] === true" key="img5"/> </transition>
需要在其过渡类中设置,即如上的enter-active-class,然后animated fadeIn即animated + 动画效果名,该动画效果名,在Animate.css的官方网站中可以找到。
-
设置动画时间:
使用duration属性,例如:
<transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }"> <img id="headimg5" class="img" :src="src_group[4]" v-if="ShowFlagGroup[4] === true" key="img5"/> </transition>
-
使用单独一个img元素:
按照transition标签的原理,只要满足生成(v-if为真)与删除(v-if为假),就可以得到元素的出现与消失的过渡效果。
因此,只要对一个img标签不断切换v-if的值,同时切换其src即可,例如:
<template> <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css"> <transition name="fade" mode="out-in" enter-active-class="animated fadeIn" :duration="{ enter: 1000, leave: 1000 }"> <img class="img" :src="image_url" v-if="image_flag"/> </transition> </template> <script> export default { name: "TransBackGround", data (){ return{ src_group:[ "http://marisa-kirisame.gitee.io/phw/dfheadimg%20(1).png", "http://marisa-kirisame.gitee.io/phw/dfheadimg%20(2).png", "http://marisa-kirisame.gitee.io/phw/dfheadimg%20(3).png", "http://marisa-kirisame.gitee.io/phw/dfheadimg%20(4).png", "http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png", ], image_url:"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png", image_flag:true, } }, methods:{ }, mounted() { const img_count=5; let _this = this; let index = 0; let timer = setInterval(() => { if(index===img_count-1){ index=0; } else { index = index + 1; } _this.image_flag=false; setTimeout(() => { _this.image_url = _this.src_group[index]; _this.image_flag=true; },50) },5000); } } </script> <style scoped> .img{ position: absolute; left: 0; top: 0; width: 100%; } .fade-leave-active { transition: all 3s cubic-bezier(1.0, 0.5, 0.8, 1.0); } .fade-leave-to { opacity: 0; } </style>
思路:
在周期定时器中,先令v-if为假值,实现元素删除,从而引发消失的过渡效果,然后一次性定时器中设定,先改变img元素所绑定的src值,然后设置v-if为真,从而引发元素出现的过渡效果。
注意:这个两次v-if的值的切换,需要保证有一定的时间间隔差,否则会看不出过渡效果。我上述例子中使用了定时器setTimeout。
-
注意:
经过测试,如果只使用单独一个元素,那么只可以做淡入淡出的过渡效果。如果使用上述说的多个元素,那么可以做自然过渡效果。这种自然过渡效果,是一种图片的渐变效果,没有太对透明度的直接变化。
Vue动画实现图片切换过渡效果
经过测试确定,不使用transition标签的过渡,仅使用Animate.css动画的FadeIn和FadeOut动画效果,配合可以实现比较完美的淡入淡出或者自然过渡效果。
注意:以下的例子与上述的自然过渡不同,是淡入淡出,在动画的效果中,切换间,中间一小段是可能会留白的。
代码如下:
<template>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn"
:duration="{ enter: 1000, leave: 1000 }">
<img class="img" :src="image_url" v-if="image_flag"/>
</transition>
</template>
<script>
export default {
name: "TransBackGround",
data (){
return{
src_group:[
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(1).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(2).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(3).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(4).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png",
],
image_url:"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png",
image_flag:true,
}
},
methods:{
},
mounted() {
const img_count=5;
let _this = this;
let index = 0;
let last_index = 0;
let timer = setInterval(() => {
last_index = index;
if(index===img_count-1){
index=0;
}
else {
index = index + 1;
}
_this.image_flag=false;
setTimeout(() => {
_this.image_url = _this.src_group[index];
_this.image_flag=true;
},10)
},5000);
}
}
</script>
<style scoped>
.img{
position: absolute;
left: 0;
top: 0;
width: 100%;
}
</style>
-
思路:
设置transition标签的leave-active-class指定为Animate.css的fadeOut,设置enter-active-class为Animate.css的fadeIn,然后设置属性 duration来指定两个动画的产生效果时间。
即关键一步只有:
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn"
:duration="{ enter: 1000, leave: 1000 }">
... ...
同理,我这里也是只使用一个img元素,在周期定时器中间隔一小段时间,来回重置v-if实现transition标签过渡起效果。即:
_this.image_flag=false;
setTimeout(() => {
_this.image_url = _this.src_group[index];
_this.image_flag=true;
},10)
需要注意的是,duration属性的设置对效果起到非常关键的作用。时间太长会发现留白较多,时间太短会发现几乎看不出过渡效果。在上述例子中给出了较为完美的设置时间:
:duration="{ enter: 1000, leave: 1000 }"
该属性还需要花费一些时间去调整,从而达到自己想要的效果。
Vue动画自然过渡效果:
上述例子之所以是淡入淡出,是因为只使用了一个img元素来做过渡,如果使用多个img元素来做过渡,那么就可以实现自然过渡。
代码如下:
<template>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[0]" v-if="ShowFlagGroup[0] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[1]" v-if="ShowFlagGroup[1] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[2]" v-if="ShowFlagGroup[2] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[3]" v-if="ShowFlagGroup[3] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn">
<img class="img" :src="src_group[4]" v-if="ShowFlagGroup[4] === true"/>
</transition>
</template>
<script>
export default {
name: "TransBackGround",
data (){
return{
src_group:[
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(1).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(2).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(3).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(4).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png",
],
ShowFlagGroup:[true,false,false,false,false],
show_index:0,
}
},
methods:{
},
mounted() {
const img_count=5;
let _this = this;
let index = 0;
let last_index = 0;
let timer = setInterval(() => {
last_index = index;
if(index===img_count-1){
index=0;
}
else {
index = index + 1;
}
_this.ShowFlagGroup[last_index]=false;
_this.ShowFlagGroup[index]=true;
},5000);
}
}
</script>
<style scoped>
.img{
position: absolute;
left: 0;
top: 0;
width: 100%;
}
</style>
同理,使用transition标签的leave-active-class属性与enter-active-class属性绑定为fadeOut与的动画效果。
升级:因为自然过渡的速度并不一定使我们想要的,那么可以通过设置定时器,确定一个时间间隔来分开两个元素的切换。
在周期定时器的对元素进行切换时,加入定时器,代码如下:
_this.ShowFlagGroup[last_index]=false;
setTimeout(() => {
_this.ShowFlagGroup[index]=true;
},50)
通过调节setTimeout的超时时间,可以让我们有更大的调节空间来设置自然过渡的效果。
这个方法的好处是,时间间隔较大时(例如我测试的:500),就是淡入淡出了,可以说是囊括了两种图片切换过渡,只要调节定时器的超时时间,就可以设置到自己想要的图片切换的过渡效果。
最终代码如下:
<template>
<link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[0]" v-if="ShowFlagGroup[0] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[1]" v-if="ShowFlagGroup[1] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[2]" v-if="ShowFlagGroup[2] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn" >
<img class="img" :src="src_group[3]" v-if="ShowFlagGroup[3] === true"/>
</transition>
<transition name="fade" mode="out-in"
leave-active-class="animated fadeOut" enter-active-class="animated fadeIn">
<img class="img" :src="src_group[4]" v-if="ShowFlagGroup[4] === true"/>
</transition>
</template>
<script>
export default {
name: "TransBackGround",
data (){
return{
src_group:[
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(1).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(2).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(3).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(4).png",
"http://marisa-kirisame.gitee.io/phw/dfheadimg%20(5).png",
],
ShowFlagGroup:[true,false,false,false,false],
show_index:0,
}
},
methods:{
},
mounted() {
const img_count=5;
let _this = this;
let index = 0;
let last_index = 0;
let duration_time = 50;
let timer = setInterval(() => {
last_index = index;
if(index===img_count-1){
index=0;
}
else {
index = index + 1;
}
_this.ShowFlagGroup[last_index]=false;
setTimeout(() => {
_this.ShowFlagGroup[index]=true;
},duration_time)
},5000);
}
}
</script>
<style scoped>
.img{
position: absolute;
left: 0;
top: 0;
width: 100%;
}
</style>
至此,对图片切换的研究也差不多了。
存在问题
到目前为止,我还没有通过仅使用transition标签的过渡,不使用动画,来实现图片的淡入淡出或者自然过渡。只使用Vue过渡,我只实现了淡出,但是淡入一直没有成功。如果有人成功了,来教教我,填个坑!
转载请注明出处!!!
Author:雾雨霜星
欢迎来我的网站学习:
https://www.shuangxing.top/#/passage?id=17
Thanks!
PS: 毕竟,霜星酱水平有限,如果发现任何错误还请及时邮箱告知我,我会去改哦!
更多推荐
所有评论(0)