<style>
.transition-demo { font-family: system-ui; }
.controls { display: flex; gap: 8px; margin-bottom: 16px; flex-wrap: wrap; }
.btn { padding: 10px 20px; border: none; border-radius: 8px; cursor: pointer; font-weight: 600; transition: all 0.2s; }
.btn-toggle { background: linear-gradient(135deg, #3b82f6, #8b5cf6); color: white; }
.btn-toggle:hover { transform: scale(1.05); }
.demo-box { width: 200px; height: 100px; background: linear-gradient(135deg, #22c55e, #10b981); border-radius: 12px; display: flex; align-items: center; justify-content: center; color: white; font-size: 18px; font-weight: bold; margin: 20px 0; }
/* Fade 动画 */
.fade-enter-active, .fade-leave-active { transition: opacity 0.5s ease; }
.fade-enter-from, .fade-leave-to { opacity: 0; }
/* Slide 动画 */
.slide-enter-active, .slide-leave-active { transition: all 0.4s ease; }
.slide-enter-from { transform: translateX(-100%); opacity: 0; }
.slide-leave-to { transform: translateX(100%); opacity: 0; }
/* Scale 动画 */
.scale-enter-active, .scale-leave-active { transition: all 0.3s ease; }
.scale-enter-from, .scale-leave-to { transform: scale(0); opacity: 0; }
/* Bounce 动画 */
.bounce-enter-active { animation: bounce-in 0.5s; }
.bounce-leave-active { animation: bounce-in 0.5s reverse; }
@keyframes bounce-in {
0% { transform: scale(0); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.class-display { background: #1e293b; padding: 12px; border-radius: 8px; font-family: monospace; font-size: 12px; }
.class-tag { display: inline-block; padding: 4px 8px; margin: 2px; border-radius: 4px; background: #3b82f6; color: white; }
.animation-select { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.animation-select button { padding: 6px 12px; border: 2px solid #475569; background: transparent; color: #94a3b8; border-radius: 6px; cursor: pointer; }
.animation-select button.active { border-color: #3b82f6; color: #3b82f6; background: rgba(59, 130, 246, 0.1); }
</style>
<div class="transition-demo">
<div class="animation-select">
<button class="active" onclick="setAnimation('fade')">Fade</button>
<button onclick="setAnimation('slide')">Slide</button>
<button onclick="setAnimation('scale')">Scale</button>
<button onclick="setAnimation('bounce')">Bounce</button>
</div>
<div class="controls">
<button class="btn btn-toggle" onclick="toggle()">Toggle 切换显示</button>
</div>
<div id="boxContainer">
<div class="demo-box" id="demoBox">Hello Vue!</div>
</div>
<div class="class-display">
<div>当前类名: <span id="currentClasses"><span class="class-tag">demo-box</span></span></div>
</div>
</div>
<script>
let visible = true;
let animationType = 'fade';
const box = document.getElementById('demoBox');
const classDisplay = document.getElementById('currentClasses');
function updateClassDisplay(classes) {
classDisplay.innerHTML = classes.map(c => '<span class="class-tag">' + c + '</span>').join('');
}
function setAnimation(type) {
animationType = type;
document.querySelectorAll('.animation-select button').forEach(b => b.classList.remove('active'));
event.target.classList.add('active');
}
function toggle() {
if (visible) {
// Leave 动画
box.classList.add(animationType + '-leave-active', animationType + '-leave-from');
updateClassDisplay(['demo-box', animationType + '-leave-active', animationType + '-leave-from']);
requestAnimationFrame(() => {
box.classList.remove(animationType + '-leave-from');
box.classList.add(animationType + '-leave-to');
updateClassDisplay(['demo-box', animationType + '-leave-active', animationType + '-leave-to']);
});
setTimeout(() => {
box.style.display = 'none';
box.classList.remove(animationType + '-leave-active', animationType + '-leave-to');
updateClassDisplay(['demo-box', '(hidden)']);
visible = false;
}, 500);
} else {
// Enter 动画
box.style.display = 'flex';
box.classList.add(animationType + '-enter-active', animationType + '-enter-from');
updateClassDisplay(['demo-box', animationType + '-enter-active', animationType + '-enter-from']);
requestAnimationFrame(() => {
box.classList.remove(animationType + '-enter-from');
box.classList.add(animationType + '-enter-to');
updateClassDisplay(['demo-box', animationType + '-enter-active', animationType + '-enter-to']);
});
setTimeout(() => {
box.classList.remove(animationType + '-enter-active', animationType + '-enter-to');
updateClassDisplay(['demo-box']);
visible = true;
}, 500);
}
}
</script>