问题
利用css3中的transition
实现滑入滑出效果,必须要给动画元素设定固定的宽高,并且不能设定 百分比:40% 这样的单位。
需求
我们给一个由 子元素撑起来 的容器设定滑入滑出的效果,高度不固定,由子元素盒子的高度和堆叠情况决定。
解决方案
方案一、
1、在保证元素被渲染的情况下,设置 height
为‘auto’,获取高度后,立即设置高度为0。
el.style.height = 'auto';
let height= window.getComputedStyle(el, null)['height'];
el.style.height = '0';
代码的运行速度比浏览器的渲染速度快,所以在你获取到高度之前,再设置为0,元素不会渲染。
2、设定一个延时setTimeout(),把height设定为刚刚获取到的值。
setTimeout(function () {
el.style.height = height;
el.style.paddingTop = paddingTop;
el.style.opacity = 1;
}, 0);
这里setTimeout是关键,如果不用setTimeout,就不会有动画,而是立马被渲染出高度,原因还是代码的执行速度问题,这里setTimeout就是让里面的代码进入下一个队列,这样容器的高度就像从0开始,执行transition
的动画渲染方式。
在vue中的使用,需要添加一些hack
<style>
.slide {
width: 300px;
background: blue;
padding-top: 20px;
transform-origin: left top;
transition: all 0.5s ease;
}
.slideinner {
width: 200px;
height: 200px;
background: #000;
transform-origin: left top;
}
</style>
<button @click="slideClick">showSlide</button>
<transition :css="false" @Enter="slideEnter" @Leave="slideLeave">
<div v-show="showSlide" class="slide" id="demo">
<div class="slideinner"></div>
</div>
</transition>
<script src="https://cdn.bootcss.com/vue/2.5.21/vue.min.js"></script>
new Vue({
methods:{
slideEnter(el, done) {
el.style.height = 'auto';
let height = window.getComputedStyle(el, null)['height'];
el.style.height = '0';
//不设定延迟height不会有动画
setTimeout(function () {
el.style.height = height;
el.style.opacity = 1;
}, 20);
done();
},
slideLeave(el, done) {
el.style.height = '0';
el.style.opacity = 0;
}
}
})
延迟设定为0的时候:
延迟设定为20的时候:
在vue中,使用js控制动画,setTimeout延迟需要设置为20ms以上,否则动画滑出的时候不起作用,这个原因我也不知道为什么。按理说我是直接操作的dom,应该和vue的虚拟dom还有渲染机制没有关系。
另外一种解决方案就是把高度存起来,只在第一次调用的时候计算高度,如果容器里面子元素受数据影响,在数据变更的时候,重新赋值,重新计算高度。
方案二、
将父容器设定max-height:“value”。
这个value
是你设定的一个比较大的值,1000px,2000px都可以,而且使用起来也比方案一简单容易,就是这个value值,必须要大于容器子元素盒子的堆叠高度,暂时不知道设定一个超大值会有什么影响,比如:10000px。