104 lines
2.9 KiB
Vue
104 lines
2.9 KiB
Vue
<template>
|
|
<transition
|
|
name="expand"
|
|
@enter="enter"
|
|
@leave="leave"
|
|
@enter-cancel="cancel"
|
|
@leave-cancel="cancel">
|
|
<slot></slot>
|
|
</transition>
|
|
</template>
|
|
|
|
<script setup>
|
|
|
|
import TWEEN from '@tweenjs/tween.js';
|
|
import { useGlobalTweenGroup } from "../lib/useGlobalTweenGroup";
|
|
|
|
const props = defineProps({
|
|
expandTime: {
|
|
type: Number,
|
|
default: 250
|
|
}
|
|
});
|
|
|
|
let animation = null;
|
|
|
|
function cancel () {
|
|
if (animation) {
|
|
animation.stop();
|
|
animation = null;
|
|
}
|
|
}
|
|
|
|
function 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;
|
|
|
|
animation = new TWEEN.Tween({height: 0, paddingTop: 0, paddingBottom: 0})
|
|
.to({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom}, props.expandTime)
|
|
.onUpdate(obj => {
|
|
element.style.height = obj.height + "px";
|
|
element.style.paddingBottom = obj.paddingBottom + "px";
|
|
element.style.paddingTop = obj.paddingTop + "px";
|
|
})
|
|
.onComplete(() => {
|
|
animation = null;
|
|
element.removeAttribute('style');
|
|
element.style.opacity = 0.99;
|
|
setTimeout(() => {
|
|
// Fixes odd drawing bug in Chrome
|
|
element.style.opacity = 1.0;
|
|
}, 1000);
|
|
done();
|
|
})
|
|
.group(useGlobalTweenGroup())
|
|
.start();
|
|
}
|
|
|
|
function 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';
|
|
|
|
animation = new TWEEN.Tween({height: height, paddingTop: paddingTop, paddingBottom: paddingBottom})
|
|
.to({height: 0, paddingTop: 0, paddingBottom: 0}, props.expandTime)
|
|
.onUpdate(obj => {
|
|
element.style.height = obj.height + "px";
|
|
element.style.paddingBottom = obj.paddingBottom + "px";
|
|
element.style.paddingTop = obj.paddingTop + "px";
|
|
})
|
|
.onComplete(() => {
|
|
animation = null;
|
|
element.removeAttribute('style');
|
|
done();
|
|
})
|
|
.group(useGlobalTweenGroup())
|
|
.start();
|
|
}
|
|
|
|
</script>
|
|
|
|
<style scoped>
|
|
* {
|
|
will-change: height;
|
|
transform: translateZ(0);
|
|
backface-visibility: hidden;
|
|
perspective: 1000px;
|
|
}
|
|
</style> |