如何实现手风琴组件高度自适应 + 高度动画
1 功能需求
1.1 打开合上面板的动画
// template
<div
:style="{ height: height + 'rem' }"
>...</div>
// style
.animation {
...
transition: height 0.5s
}
// js
initHeight = 1
maxHeight = 2 // 经过复杂的js预计算获得,不好维护
height = initHeight
open = false
function changeHeight() {
open = !open
this.height = open ? maxHeight : initHeight
}
1.2 高度自适应,避免js计算
// template
<div
:style="divStyle"
>...</div>
// style
.animation {
...
transition: height 0.5s
}
// js
initHeight = 1
open = false
get divStyle() {
return open ? {} : { height: initHeight }
}
function changeHeight() {
open = !open
}
2 功能冲突
自适应布局时height为auto,所以能自动根据content撑开,但是于此同时,也就破坏了height动画,因为height的from和to必须为某一定值而不是auto
3 解决方案
3.1 方案1 使用maxHeight(bad)
// js
maxHeight = 999
open = false
get divStyle() {
return open ? { maxHeight } : { height: initHeight }
}
function changeHeight() {
open = !open
}
这种方案的原理是通过设置足够大的maxHeight来实现动画的,缺点是打开状态下由于maxHeight比实际的height大得多,因此在动画的前半段时间,高度动画是卡顿住的,无法与盒子内部content的动画一致,体验不好。
如果要改善这个问题,只能通过不断减小maxHeight的值;但与此同时,当maxHeight足够小是,为了保证内容不被hidden,我们又要绕回到js计算最高高度了。所以这个方案不可行。
3.2 方案2 初始化时将盒子设置为展开状态,记住最高高度然后还原展开状态(good)
// js
const currentOpen = this.operationIsOpen;
this.operationIsOpen = true;
this.$nextTick(() => {
const operationBlock = document.getElementsByClassName(
'operation-block'
)[0];
if (!operationBlock) return;
this.maxHeight = operationBlock.offsetHeight;
this.operationIsOpen = currentOpen;
});
获取了准确的maxHeight而又不用进行js计算,个人认为这是这个需求的最优解
本文探讨了手风琴组件中实现平滑动画与高度自适应的技术挑战及解决方案,对比了两种不同方法:使用maxHeight实现动画效果及其局限性,以及通过初始化时测量元素高度来达到更优体验的方法。

2841

被折叠的 条评论
为什么被折叠?



