parsley/app/javascript/components/AppExpandTransition.vue
2018-09-13 14:51:41 -05:00

109 lines
3.0 KiB
Vue

<template>
<transition
name="expand"
@enter="enter"
@leave="leave"
@enter-cancel="cancel"
@leave-cancel="cancel">
<slot></slot>
</transition>
</template>
<script>
import TWEEN from '@tweenjs/tween.js';
export default {
props: {
expandTime: {
type: Number,
default: 250
}
},
data() {
return {
animation: null
}
},
methods: {
cancel () {
if (this.animation) {
this.animation.stop();
this.animation = null;
}
},
enter(element, done) {
const width = parseInt(getComputedStyle(element).width);
const paddingTop = parseInt(getComputedStyle(element).paddingTop);
const paddingBottom = parseInt(getComputedStyle(element).paddingBottom);
element.style.width = width;
element.style.position = 'absolute';
element.style.visibility = 'hidden';
element.style.height = 'auto';
const height = parseInt(getComputedStyle(element).height);
element.style.width = null;
element.style.position = null;
element.style.visibility = null;
element.style.overflow = 'hidden';
element.style.height = 0;
this.animation = new TWEEN.Tween({height: 0, paddingTop: 0, paddingBottom: 0})
.to({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom}, this.expandTime)
.onUpdate(obj => {
element.style.height = obj.height + "px";
element.style.paddingBottom = obj.paddingBottom + "px";
element.style.paddingTop = obj.paddingTop + "px";
})
.onComplete(() => {
this.animation = null;
element.removeAttribute('style');
element.style.opacity = 0.99;
setTimeout(() => {
// Fixes odd drawing bug in Chrome
element.style.opacity = 1.0;
}, 1000);
done();
})
.start();
},
leave(element, done) {
const height = parseInt(getComputedStyle(element).height);
const paddingTop = parseInt(getComputedStyle(element).paddingTop);
const paddingBottom = parseInt(getComputedStyle(element).paddingBottom);
element.style.overflow = 'hidden';
this.animation = new TWEEN.Tween({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom})
.to({height: 0, paddingTop: 0, paddingBottom: 0}, this.expandTime)
.onUpdate(obj => {
element.style.height = obj.height + "px";
element.style.paddingBottom = obj.paddingBottom + "px";
element.style.paddingTop = obj.paddingTop + "px";
})
.onComplete(() => {
this.animation = null;
element.removeAttribute('style');
done();
})
.start();
}
}
}
</script>
<style scoped>
* {
will-change: height;
transform: translateZ(0);
backface-visibility: hidden;
perspective: 1000px;
}
</style>