目录
框架实现
基于 vue的动画渐隐实现
基于 react的动画渐隐实现
原生实现
visibility 代替 display
setTimeOut
transitionend
首页 web前端 js教程 如何实现元素显隐切换的过渡效果

如何实现元素显隐切换的过渡效果

Oct 06, 2017 am 10:41 AM
元素 切换 过渡

近来看到 饿了么 App和 h5站上,在商家详情页点餐之后,底部放置了一个点击之后能够弹出模态框查看点餐详情的元素,其中有个背景遮罩层的渐进显隐的效果。

 、

凭着我少许的经验,第一时间的想法是觉得这个遮罩层应该是使用 display:none;来控制隐藏和显示的,但是这个属性会破坏 transition动画,也就是说如果遮罩层是使用了这个属性来控制显示与隐藏,那么渐进显隐的效果似乎很难达到,效果应该是瞬间显示与隐藏才对。

使用 Chrome 模拟移动端,查看了一下 饿了么的实现方式,这才想到 饿了么用到了 vue,此动画效果其实是利用了 vue自带的过渡动画和钩子函数实现的。


框架实现

基于 vue的动画渐隐实现

利用框架实现这种效果真的是 so easy,不逼逼上代码。

// HTML<p id="app">
  <button class="btn" @click="show = !show">click</button>
  <transition name=&#39;fade&#39;>
    <p class="box1" v-if="show"></p>
  </transition>
</p>// CSS.box1 {
 width: 200px;
 height: 200px;
 background-color: green;
}

.fade-enter-active, .fade-leave-active {
 transition: opacity .5s
}
.fade-enter, .fade-leave-to{
 opacity: 0;
}
登录后复制

无图无真相,看看效果助助兴:

简直不能更简单

基于 react的动画渐隐实现

react本身的单独库没有自带过渡动画,不过有个 Animation Add-Ons: react-addons-css-transition-group



import React, {Component} from &#39;react&#39;import ReactDOM from &#39;react-dom&#39;import ReactCSSTransitionGroup from &#39;react-addons-css-transition-group&#39;class TodoList extends React.Component {
 constructor(props) {
super(props)this.state = {
     show: true}
}

 render() {return (<p>
  <button onClick={this.changeShow.bind(this)}>click</button>
  <ReactCSSTransitionGroup
         component="p"
         transitionName="fade"
         transitionEnterTimeout={500}
         transitionLeaveTimeout={300}>
    {      this.state.show &&
      <p className="box1">
      </p>    }  </ReactCSSTransitionGroup>
</p>)
}

 changeShow() {this.setState({
     show: !this.state.show
})
}
}
登录后复制

样式如下:

.box1 {
 width: 100px;
 height: 100px;
 background-color: green;
 transition: opacity .5s;
}
.fade-leave.fade-leave-active, .fade-enter {
 opacity: 0;
}

.fade-enter.fade-enter-active, .fade-leave {
 opacity: 1;
}
登录后复制

依旧是很 easy


原生实现

以上都是框架实现,但如果项目历史悠久,根本就没用到这些亮瞎人眼的框架,充其量用了个 1.2版本的 jquery,那么上面方法可都用不到了,我希望找到一种通用的原生方式,不利用任何框架。

visibility 代替 display

其中一种方案如题所示,因为 visibility这个属性同样能够控制元素的显隐,而且, visibility属性在值 visible 与 hidden的来回切换中,不会破坏元素的 transition 动画。

不过 visibility与 display 之间控制元素显隐的最终效果还是有些差别的。

设置了 visibility:hidden; 的元素,视觉上确实是不可见了,但是元素仍然占据该占据的位置,仍然会存在于文档流中,影响页面的布局,只不过设置了此属性的元素在视觉上看不到,在页面的原位置上留下一片空白而已(如果此元素具有宽高并且使用默认定位)。

而设置了 display:none;的元素,其既视觉上不可见,同时也不会占据空间,也就是说已经从文档流中消失了。

visibility控制元素显隐同样是瞬时发生的,不过这种瞬时发生的情况又和 display的那种瞬时发生不太一样, display是根本不会理会设置的 transition过渡属性,设置了也和没设置一样。

但 visibility是有可能会理会这个值的,不过只理会 过渡时间 transition-duration这个属性。

例如,从 visibility:hidden到 visibility:visible;变化时,如果设置了过渡时间为 3s,那么在事件发生后,元素并不会立即呈现出从 hidden到 visible的效果,而是会像下图那样,先等待 3s,然后再瞬间隐藏,从显示到最终消失视线中的时间确实 3s,只不过并不是逐渐过渡出现的。


上图似乎有个问题,从显示到隐藏确实是等待了 3s,但从隐藏到显示,好像还是瞬间完成的,并没有等待 3s的说法。

视觉上确实是这样,不过这也只是视觉上的感觉而已,实际上这个等待时间真实存在的,只是看不到而已,另外,这里的 等待也不是真的什么都没做纯粹的 等待。

之所以 display会破坏 transition动画,有个说法是,因为 transition对元素在整个过渡过程中的状态控制,是根据元素过渡前后起始的状态来计算得出的,例如从 opacity:0 到 opacity:1的变化,用时 3s,那么 transition会计算在这 3s内的每一帧画面中元素该有的 opacity值,从而完成过渡效果,其他的一些属性,例如 width、 scale、 color等都可以转化为数字进行计算 (说明文档参见), 但 display是个尴尬的属性,从 display:none到 display:block 该怎么计算值呢?

计算不了,所以就只能 破坏了, visibility同样如此,只不过 visibility比 display稍好一点,因为最起码 visibility不会破罐子破摔,不会搞破坏。

从 visibility:hidden到 visibility:visible的过程中。因为没办法计算过渡阶段没帧的值,所以元素就直接显示出来了,但内在的过渡操作依旧在元素显示出来后显示了 3s,而从 visibility:visible 到 visibility:hidden,元素在视觉上看起来等待的 3s内,实际在内部已经在进行 transition过渡操作,只不过还是因为没办法计算值,所以到了过渡阶段的最后一刻时,就直接将元素设置为结束状态,也就是隐藏了。

想要验证这种说法,还需要配合另外一个属性: opacity,此属性也是配合 visibility完成过渡效果的搭配属性。

实现代码如下


// HTML<button class="btn">click</button>
<p class="box1"></p>
登录后复制


// CSS.box1 {
 width: 200px;
 height: 200px;
 background-color: green;

 opacity: 0;
 visibility: hidden;
 transition: all 2s linear;
}
.show {
 opacity: .6;
 visibility: visible;
}
登录后复制

js控制显隐效果代码如下:

let box1 = document.querySelector(&#39;.box1&#39;)
let btn = document.querySelector(&#39;button&#39;)
btn.addEventListener(&#39;click&#39;, ()=>{
let boxClassName = box1.className
 boxClassName.includes(&#39;show&#39;)? box1.className = boxClassName.slice(0, boxClassName.length-5)
: box1.className += &#39; show&#39;})
登录后复制


效果依旧没问题:


因为虽然 visibility没办法计算值,但 opacity可以,过渡的效果实际上是 opacity在起作用。

其实 opacity本身就能控制元素的显隐,把上面代码中的所有 visibility 全部删除,效果依旧不变,并且和 visibility 一样,设置了 opacity:0; 的元素依旧存在于文档流中, but,相比于 visibility:hidden, opacity:0 的元素并不会出现点透。

而 visibility:hidden的元素就会出现点透,点击事件会穿透 visibility:hidden的元素,被下面的元素接收到,元素在隐藏的时候,就不会干扰到其他元素的点击事件。

关于这个说法,似乎网上有些争论,但是我用迄今最新版的 Chrome Firefox 以及 360浏览器 进行测试, 都是上面的结果。

如果你只是想让元素简单的渐进显隐,不用管显隐元素会不会遮挡什么点击事件之类的,那么完全可以不用加 visibility 属性,加了反而是自找麻烦,但是如果需要考虑到这一点,那么最好加上。


setTimeOut

如果不使用 visibility的话还好,但是如果使用了此属性,那么上述的解决方案其实还有点小瑕疵,因为 visibility从 IE10以及 Android4.4才开始支持,如果你需要支持这种版本的浏览器,那么 visibility 就派不上用场了。

哎呦呦,公司网站最低要求都是 IE9,用不了了诶。

怎么办?再回到 display 这个属性上。

为什么 display 这个属性会影响到 transition 动画的原因上面已经大致说了下,既然问题是出在了 display上,那么我可以同样参考上面 visibility的做法,加个 opocity属性进行辅助,又因为考虑到 display 比起 visibility 来说破坏性较大,所以再让 opocity 与 display 分开执行不就行了吗?

你如果写成这种形式:

box1.style.display=&#39;block&#39;box1.style.opacity=1
登录后复制

其实还是没用的,尽管 display值的设定在代码上看起来好像是在 opacity前面,但是执行的时候却是几乎同时发生的。

我的理解是应该是浏览器对代码进行了优化,浏览器看到你分两步为同一个元素设置 CSS属性,感觉有点浪费,为了更快地完成这两步,它帮你合并了一下,放在一个 tick(参见 [ ( ] )内执行,变成一步到位了,也就是同步执行了这两句代码。

那么如何明确地让浏览器不要合并到一个 tick内执行呢? setTimeOut就派上了用场。

setTimeOut 一个重要功能就是延迟执行,只要将 opacity属性的设置延迟到 display后面执行就行了。


// CSS.box1 {
 width: 200px;
 height: 200px;
 background-color: green;

 display: none;
 opacity: 0;
 transition: all 2s linear;
}
登录后复制

下面是控制元素渐进显示的代码:


// JSlet box1 = document.querySelector(&#39;.box1&#39;)
let btn = document.querySelector(&#39;.btn&#39;)
btn.addEventListener(&#39;click&#39;, ()=>{
let boxDisplay = box1.style.displayif(boxDisplay === &#39;none&#39;) {
   box1.style.display=&#39;block&#39;
   setTimeout(()=> {
     box1.style.opacity = 0.4})
}
})
登录后复制

上述代码中,最关键的就是 setTimeOut 这一句,延迟元素 opacity属性的设定。

setTiomeOut的第二个可选的时间 delay参数,我在最新版的 Chrome和 360 浏览器上测试,此参数可以不写,也可以写成 0或者其他数值,但是在 firefox上,此参数必须写,不然渐进效果时灵时不灵,而且不能为 0,也不能太小,我测出来的最小数值是 14,这样才能保证渐进效果,所以为了兼容考虑,最好还是都统一加上时间。

至于为什么是 14,我就不清楚了,不过记得以前看过一篇文章,其中说 CPU能够反应过来的最低时间就是 14ms,我猜可能与这个有关吧。

显示的效果有了,那么要隐藏怎么办? setTimeOut 当然也可以,在 JS代码的 if(boxDisplay==='none')后面再加个 else

else {
  box1.style.opacity = 0
  setTimeout(()=>{
    box1.style.display = &#39;none&#39; }, 2000)
}
登录后复制

隐藏时先设置 opacity,等 opacity过渡完了,再设置 display:none;。

但是这里有点不太合理,因为虽然 setTimeOut的 delay参数 2000ms和 transition 时间 2s一样大,但因为 JS是单线程,遵循时间轮询,所以并不能保证 display属性的设置刚好是在 opacity过渡完了的同时执行,可能会有更多一点的延迟,这取决于过渡动画完成之刻, JS主线程是否繁忙。

当然,就算是延迟,一般也不会延迟多长时间的,人眼不太可能感觉得到,如果不那么计较的话其实完全可以无视,但是如果我就吹毛求疵,要想做到更完美,那怎么办?


transitionend

transition 动画结束的时候,对应着一个事件: transitionend,MDN [ ] 上关于此事件的详细如下:

transitionend 事件会在 CSS transition 结束后触发. 当 transition完成前移除 transition时,比如移除 css的 transition-property 属性,事件将不会被触发,如在 transition完成前设置 display:none,事件同样不会被触发。

如果你能够使用 transition,那么基本上也就能够使用这个事件了,只不过此事件需要加前缀的浏览器比较多(现在最新版的所有 主流浏览器,都已经不用写前缀了),大致有如下写法:


transitionend
webkitTransitionEnd
mozTransitionEnd
oTransitionEnd
登录后复制

使用此属性,就可以避免上面 setTimeOut可能出现的问题了 ,使用示例如下:

// ...else {
 box1.style.opacity = 0
 box1.addEventListener(&#39;transitionend&#39;, function(e) {
   box1.style.display = &#39;none&#39;});
}
登录后复制
需要注意的是, transitionend 事件监听的对象是所有 CSS中transition属性指定的值,例如,如果你为元素设置了 transition:all3s;的 样式,那么元素可能无论是 left top还是 opacity 的改变,都会触发该事件,也就是说此事件可能会被触发多次,并且并不一定每次都是你想要触发的,针对这种情况,最好加一个判断。

既然是 涉及到了 JS实现的动画,那么其实可以考虑一下 把 setTimeout换成 requestAnimationFrame。


btn.addEventListener(&#39;click&#39;, ()=>{
let boxDisplay = box1.style.displayif(boxDisplay === &#39;none&#39;) {
   box1.style.display=&#39;block&#39;// setTimeOut 换成 requestAnimationFrame
   requestAnimationFrame(()=> {
     box1.style.opacity = 0.6})
} else {
  box1.style.opacity = 0
  box1.addEventListener(&#39;transitionend&#39;, function(e) {
    box1.style.display = &#39;none&#39;});
}
})
登录后复制

文章最开始说过的 vue 和 react这两个框架实现示例动画的方法,也利用到了这个 API,,监听动画过渡的状态,为元素添加和删除一系列过渡类名的操作,当然,并不是全部,此事件只能监听动画结束的这个时刻,其他时间点是无法监听的。

  • 以下为 transitionEnd 在 react-addons-css-transition-group源码里面出现的形式:

react-addons-css-transition-group对 transitionend做了兼容,如果浏览器支持此属性,则使用,如果不支持,就使用 setTimeOut这种形式。

  • 以下为 transitionEnd 在 vue源码里面出现的形式:

 

另外,顺带一提的是,除了 transitionend 事件,还有一个 animationend [  ] 事件,此事件是对应 animation动画, react-addons-css-transition-group 和 vue中也都对应着 transitionend 出现了此属性的身影,这里就不展开了。

以上是如何实现元素显隐切换的过渡效果 的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解锁Myrise中的所有内容
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

CSS过渡效果:如何实现元素的淡入淡出效果 CSS过渡效果:如何实现元素的淡入淡出效果 Nov 21, 2023 am 08:03 AM

CSS过渡效果:如何实现元素的淡入淡出效果引言:在网页设计中,使元素具备过渡效果是提升用户体验的重要手段之一。而淡入淡出效果是一种常见而又简洁的过渡效果,能够使元素从无到有、由浅入深的显示。本文将介绍如何使用CSS来实现元素的淡入淡出效果,并给出具体的代码示例。一、使用transition属性实现元素的淡入淡出效果CSS的transition属性可以为元素添

小米14Ultra如何切换4g和5g? 小米14Ultra如何切换4g和5g? Feb 23, 2024 am 11:49 AM

小米14Ultra是今年小米中非常火热的机型之一,小米14Ultra不仅仅升级了处理器以及各种配置,而且还为用户们带来了很多新的功能应用,从小米14Ultra销量就可以看出来手机的火爆程度,不过有一些常用的功能可能你还没了解。那么小米14Ultra如何切换4g和5g呢?下面小编就为大家介绍一下具体的内容吧!小米14Ultra怎么切换4g和5g?1、打开手机的设置菜单。2、设置菜单中查找并选择“网络”、“移动网络”的选项。3、移动网络设置中,会看到“首选网络类型”选项。4、点击或选择该选项,会看到

win11家庭版切换专业版操作教程_win11家庭版切换专业版操作教程 win11家庭版切换专业版操作教程_win11家庭版切换专业版操作教程 Mar 20, 2024 pm 01:58 PM

Win11家庭版怎么转换成Win11专业版?在Win11系统中,分为了家庭版、专业版、企业版等,而大部分Win11笔记本都是预装Win11家庭版系统。而今天小编就给大家带来win11家庭版切换专业版操作步骤!1、首先在win11桌面此电脑上右键属性。2、点击更改产品密钥或升级windows。3、然后进入后点击更改产品密钥。4、再输入激活密钥:8G7XN-V7YWC-W8RPC-V73KB-YWRDB,选择下一步。5、接着就会提示成功,这样就可以将win11家庭版升级win11专业版了。

Win10系统如何实现双系统切换 Win10系统如何实现双系统切换 Jan 03, 2024 pm 05:41 PM

很多朋友刚接触win系统的时候可能用不习惯,电脑中存着双系统,这个时候其实是可以双系统切换的,下面就一起来看看两个系统切换的详细步骤吧。win10系统如何两个系统切换方法一、快捷键切换1、按下“win”+“R”键打开运行2、在运行框中输入“msconfig”点击“确定”3、在打开的“系统配置”界面中选择自己需要的系统点击“设为默认值”,完成后“重新启动”即可完成切换方法二、开机时选择切换1、拥有双系统时开机会出现一个选择操作界面,可以使用键盘“上下”键进行选择系统

切换苹果电脑双系统启动方式 切换苹果电脑双系统启动方式 Feb 19, 2024 pm 06:50 PM

苹果双系统开机怎么切换苹果电脑作为一款功能强大的设备,除了搭载自家的macOS操作系统外,也可以选择安装其他操作系统,比如Windows,从而实现双系统的切换。那么在开机时,我们如何切换这两个系统呢?本文就来为大家介绍一下在苹果电脑上如何实现双系统的切换。首先,在安装双系统之前,我们需要确认自己的苹果电脑是否支持双系统切换。一般来说,苹果电脑都是基于

excel切换工作簿快捷键的使用方法 excel切换工作簿快捷键的使用方法 Mar 20, 2024 pm 01:50 PM

在excel软件的应用里,我们已经习惯使用快捷键,让有些操作变得更简单和快捷,excel的多个表格之间有时候会有相关的数据,我们在查看时,要不停的切换工作簿,如果有更快捷的切换方法,就会省下很多切换浪费的时间,对工作效率的提高有很大的帮助,什么办法可以完成快速的切换呢,针对这个问题,小编今天要讲的内容是:excel切换工作簿快捷键的使用方法。1、首先在打开的excel表格的下方可以看到有多个工作簿,需要快捷切换不同的工作簿,如下图所示。  2、然后按下键盘上的Ctrl键不动,如果需要向右选择工作

无法使用win11的alt+tab切换界面,出现的原因是什么? 无法使用win11的alt+tab切换界面,出现的原因是什么? Jan 02, 2024 am 08:35 AM

win11支持用户使用alt+tab快捷键的方式来调出桌面切换工具,但是最近有朋友遇到了win11alt+tab切换不了界面的问题,不知道是什么原因也不知道怎么解决。win11alt+tab切换不了界面什么原因:答:因为快捷键功能被禁用了,下面是解决方法:1、首先我们按下键盘“win+r”打开运行。2、接着输入“regedit”并回车打开组策略。3、然后进入“HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer”

认识全角和半角:切换技巧一览 认识全角和半角:切换技巧一览 Mar 25, 2024 pm 01:36 PM

在日常生活中,我们经常会遇到全角和半角的问题,但可能很少有人深入了解它们的含义和区别。全角和半角,实际上是一种字符编码方式的概念,而在电脑输入、编辑、排版等方面都有其特殊的应用。本文将深入探讨全角和半角的区别、切换技巧以及在实际生活中的应用。首先,全角和半角在汉字文字领域中的定义是:一个全角字符占用一个字符位置,而一个半角字符占用半个字符位置。在计算机中,通

See all articles