('click', ()=>{
let boxClassName = box1.className
boxClassName.includes('show')
? box1.className = boxClassName.slice(0, boxClassName.length-5)
: box1.className += ' show'
效果依旧没问题:
其实 opacity
本身就能控制元素的显隐,把上面代码中的所有 visibility
全部删除,效果依旧不变。
opacity
确实能够让元素在视觉上显示和隐藏,并且和 visibility
一样,设置了 opacity:0;
的元素依旧存在于文档流中,but
,相比于 visibility: hidden
, opacity: 0
的元素并不会出现点透。
而 visibility: hidden
的元素就会出现点透,点击事件会穿透 visibility: hidden
的元素,被下面的元素接收到,元素在隐藏的时候,就不会干扰到其他元素的点击事件。
关于这个说法,似乎网上有些争论,但是我用迄今最新版的 Chrome
Firefox
以及 360浏览器
进行测试, 都是上面的结果。
如果你只是想让元素简单的渐进显隐,不用管显隐元素会不会遮挡什么点击事件之类的,那么完全可以不用加 visibility
属性,加了反而是自找麻烦,但是如果需要考虑到这一点,那么最好加上。
setTimeOut
如果不使用 visibility
的话还好,但是如果使用了此属性,那么上述的解决方案其实还有点小瑕疵,因为 visibility
从 IE10
以及 Android 4.4
才开始支持,如果你需要支持这种版本的浏览器,那么 visibility
就派不上用场了。
哎呦呦,公司网站最低要求都是 IE9
,用不了了诶。
怎么办?再回到 display
这个属性上。
为什么 display
这个属性会影响到 transition
动画呢?
网上有的说法是 因为缓动是基于数值和时间的计算(长度,百分比,角度,颜色也能转换为数值)(w3.org ),而display
是一个尴尬的属性,没办法转换。
既然问题是出在了 display
上,那么我就不用 display
作为过渡的属性,换成 opocity
,并且让opocity
与 display
分开执行不就行了吗?
你如果写成这种形式:
box1.style.display='block'
box1.style.opacity=1
其实还是没用的,尽管 display
值的设定在代码上看起来好像是在 opacity
前面,但是执行的时候却是几乎同时发生的。
我的理解是应该是浏览器对代码进行了优化,浏览器看到你分两步为同一个元素设置 CSS
属性,感觉有点浪费,为了更快地完成这两步,它帮你合并了一下,放在一帧内执行,变成一步到位了,也就是同步执行了这两句代码。
那么如何明确地让浏览器不要合并执行呢?setTimeOut
就派上了用场。
setTimeOut
一个重要功能就是延迟执行,只要将 opacity
属性的设置延迟到 display
后面执行就行了。
.box1 {
width: 200px;
height: 200px;
background-color: green;
display: none;
opacity: 0;
transition: all 2s linear;
下面是控制元素渐进显示的代码:
// JS
let box1 = document.querySelector('.box1')
let btn = document.querySelector('.btn')
btn.addEventListener('click', ()=>{
let boxDisplay = box1.style.display
if(boxDisplay === 'none') {
box1.style.display='block'
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 = 'none'
}, 2000)
隐藏时先设置 opacity
,等 opacity
过渡完了,再设置 ;
。
但是这里有点不太合理,因为虽然 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('transitionend', function(e) {
box1.style.display = 'none'
需要注意的是,transitionend
事件监听的对象是所有 CSS 中transition
属性指定的值,例如,如果你为元素设置了 transition: all 3s;
的 样式,那么元素可能无论是left top
还是 opacity
的改变,都会触发该事件,也就是说此事件可能会被触发多次,并且并不一定每次都是你想要触发的,针对这种情况,最好加一个判断。
既然是 涉及到了JS
实现的动画,那么其实可以考虑一下 把setTimeout
换成requestAnimationFrame
。
btn.addEventListener('click', ()=>{
let boxDisplay = box1.style.display
if(boxDisplay === 'none') {
box1.style.display='block'
// setTimeOut 换成 requestAnimationFrame
requestAnimationFrame(()=> {
box1.style.opacity = 0.6
} else {
box1.style.opacity = 0
box1.addEventListener('transitionend', function(e) {
box1.style.display = 'none'
文章最开始说过的 vue
和 react
这两个框架实现示例动画的方法,也利用到了这个 API
,,监听动画过渡的状态,为元素添加和删除一系列过渡类名的操作,当然,并不是全部,此事件只能监听动画结束的这个时刻,其他时间点是无法监听的。
- 以下为
transitionEnd
在react-addons-css-transition-group
源码里面出现的形式:
react-addons-css-transition-group
对 transitionend
做了兼容,如果浏览器支持此属性,则使用,如果不支持,就使用 setTimeOut
这种形式。
- 以下为
transitionEnd
在vue
源码里面出现的形式:
另外,顺带一提的是,除了 transitionend
事件,还有一个 animationend事件,此事件是对应 animation
动画,这里就不展开了。
Transition(过度)
Transition允许CSS的属性值在一定的
时间区间内平滑地过渡。这种
效果可以在鼠标单击、获得焦点、被点击或对
元素任何改变中触发,并圆滑地以
动画效果改变CSS的属性值,它的语法如下:
CSS Code复制内容到剪贴板
transition: property duration timing-function delay;
property:执行过渡的属性
duration:执行过渡的持续
时间
timing-function:执行过渡的速率模式
delay:延
时多久执行
(此图片来源于网络,如有侵权,请联系删除! )
像这样的一个带过渡
效果的小部件在我们实际开发中的应用几率还是比较大的,但是在开发微信小程序的过程中可能有的小伙伴发现
transition这个属性它不好使(下面说明)所以我们这个
时候会考虑去使用微信官方提供的wx.createAnimation API来创建
动画。
接下来我带各位小伙伴如何让
transition 属性在这种需求中好使起来,下面上代码
page({
data: {
show:false//用于
显示或
隐藏控件
chanMask:function(){
前阶段页面涉及到了一些数据的隐藏和显示,数据的新增删除等一些基本的操作,数据的隐藏和显示可以用fadeOut、fadeIn、slideDown、slideUp等动画方法来实现,而数据删除和新增的动画,可以使用transtion和transition-group来实现,之前没怎么用过这两个属性,特此来记录一下使用过程以及遇到的一些小的问题。
1、首先我们先做一些准备工作,先实现一个div的隐藏和显示:
HTML:我们使用template标签将要显示和隐藏的元素包裹起来,然后使用v-if进行判断temp值为tr
学完bootstrap3后,找了一个简单的网站进行实战练习,只实现了网站首页的效果。用上bootstrap基本的栅格布局,轮播图和几个常用的样式类,适合小白练手。
整个完整首页的实现效果是这样的:
这里粘贴两个关键文件的代码:(完整项目资源放github,文末有地址。)
1、index.html
<!DOCTYPE html>
<meta charset="utf-8">
<title>一点点官网|一点点.
使用 CSS 让元素不可见的方法很多,剪裁、定位到屏幕外、明度变化等都是可以的。虽然它们都是肉眼不可见,但背后却在多个维度上都有差别。下面是我总结的一些比较好的隐藏实践。
此时,图片 1.jpg 是不会有请求的。标签是不支持嵌套的,因此,如果希望在标签中再放置其他不渲染的模板内容,可以试试使用元素。例如:
图片 2.jpg 也是不会有请求的。另外,标签隐藏内容获取使用 ,使用。
如果希望元素不可见,同时不占据空间,辅助设备无法访问,但显隐的时候可以有淡入淡出效果,则可以使用:
如果希望元素不可见,不
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net