详情切换动画与侧栏折叠动画
详情换选中:内容 out-in 淡切,容器高度从旧值滑到新值。auto 高度不可 插值,做法是离开前钉住当前高度,新内容进场时量出目标值过渡过去,结束 后清掉内联样式交还给内容。 侧栏折叠改成裁切式:只过渡外层宽度,内层内容按展开宽度定死、被 overflow 裁掉,文字用透明度淡出(比宽度动画快,先消失再收边,不露半截字)。原来 用 display: none 藏文字加居中图标,动画中途会重排跳位。折叠宽度取 60px 是因为图标中心恰好在 30px,收拢后天然居中,全程不用挪任何东西;折叠 按钮钉在右下角,跟着边缘走。
This commit is contained in:
@@ -147,6 +147,42 @@ function toggleOpen() {
|
||||
open.value = !open.value
|
||||
if (open.value) void revealBottom()
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换选中的入站时,内容淡出淡入,容器高度从旧值滑到新值。
|
||||
* 高度过渡没法纯 CSS 做:auto 不可插值。所以离开前把当前高度钉住,
|
||||
* 新内容进场时量出目标高度、过渡过去,结束后清掉内联样式让内容重新做主。
|
||||
*/
|
||||
function lockHeight() {
|
||||
const el = rootEl.value
|
||||
if (!el) return
|
||||
el.style.height = `${String(el.offsetHeight)}px`
|
||||
el.style.overflow = 'hidden'
|
||||
}
|
||||
|
||||
function settleHeight() {
|
||||
const el = rootEl.value
|
||||
if (!el || !el.style.height) return
|
||||
const from = el.style.height
|
||||
el.style.height = 'auto'
|
||||
const to = `${String(el.offsetHeight)}px`
|
||||
if (to === from) {
|
||||
el.style.height = ''
|
||||
el.style.overflow = ''
|
||||
return
|
||||
}
|
||||
el.style.height = from
|
||||
void el.offsetHeight
|
||||
el.style.transition = 'height 0.15s ease'
|
||||
el.style.height = to
|
||||
el.addEventListener('transitionend', function done(event) {
|
||||
if (event.propertyName !== 'height') return
|
||||
el.removeEventListener('transitionend', done)
|
||||
el.style.transition = ''
|
||||
el.style.height = ''
|
||||
el.style.overflow = ''
|
||||
})
|
||||
}
|
||||
const form = ref<OutboundSetup>({ proxy: { sources: [], filter: null }, chain: null })
|
||||
|
||||
/**
|
||||
@@ -338,6 +374,15 @@ const complete = computed(
|
||||
|
||||
<template>
|
||||
<aside ref="rootEl" class="detail">
|
||||
<!-- 换一路入站:淡出旧内容、淡入新内容,高度的过渡由上面两个钩子做 -->
|
||||
<Transition
|
||||
name="swap"
|
||||
mode="out-in"
|
||||
@before-leave="lockHeight"
|
||||
@enter="settleHeight"
|
||||
@after-enter="moveInk"
|
||||
>
|
||||
<div :key="inbound.id">
|
||||
<header class="top">
|
||||
<div class="title">
|
||||
<span class="port mono">{{ inbound.port }}</span>
|
||||
@@ -588,6 +633,8 @@ const complete = computed(
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
</div>
|
||||
</Transition>
|
||||
</aside>
|
||||
</template>
|
||||
|
||||
@@ -779,6 +826,17 @@ h3 {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* 切换入站的内容淡切。高度的过渡不在这里,由 lockHeight/settleHeight 用内联样式做 */
|
||||
.swap-enter-active,
|
||||
.swap-leave-active {
|
||||
transition: opacity 0.12s ease;
|
||||
}
|
||||
|
||||
.swap-enter-from,
|
||||
.swap-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
|
||||
|
||||
Reference in New Issue
Block a user