今天测试小程序时,发现在公司两部iPhoneX上出现了不符合预期的效果,最后发现是在低版本iOS中,微信小程序的底层框架对aspect-radio的支持存在问题
异常展示
在拖拽画面中的圆圈时,会调用微信的catch:touchstart
, catch:touchmove
, catch:touchend
三个接口,动态计算圆圈的位置和两侧直线的长度,再加上一个throttle函数,限制其调用频率,以防影响低配置手机的体验。
最初的解决方案是固定圆圈的宽度为父节点的8%,再用aspect-ratio调整他的高度。
.circle-dragger {
content: "";
position: absolute;
transform-origin: 50% 50%;
transform: translateY(-50%) translateX(-50%);
width: 8%;
aspect-ratio: 1 / 1;
border-radius: 50%;
但是在这个情况中,圆圈的高度却跟着手指的拖动发生了高度的变化,所以自然而然就怀疑上了这个aspect-ratio。
针对这个问题,解决方案有三种:
方案一 将%百分比换算成vw,然后用vw表示高度
.circle-dragger {
content: "";
position: absolute;
transform-origin: 50% 50%;
transform: translateY(-50%) translateX(-50%);
width: 5.6vw;
height: 5.6vw;
border-radius: 50%;
这个方案可以解决这个问题,但是无法在不确定相对屏幕宽度的情况下使用
方案二 使用padding-top伪元素trick
.circle-dragger {
content: "";
position: absolute;
transform-origin: 50% 50%;
transform: translateY(-50%) translateX(-50%);
width: 8%;
border-radius: 50%;
}
.circle-dragger::before {
content: "";
width: 1px;
margin-left: -1px;
float: left;
height: 0;
padding-top: 100%;
}
.circle-dragger::after
content: "";
display: table;
clear: both;
}
这个方法同样可以用来防止aspect-ratio的元素内容超出限定的比例问题。通过before伪元素给circle-dragger设定了一个会浮动变化的高度,再由after伪元素消除浮动,就产生了一个可以伸缩的aspect-ratio替代方案。
方案三 使用JS动态计算高度
由于微信小程序渲染层和逻辑层分由两个线程管理,为减少线程通信产生的性能损失,小程序一直都是推荐减少使用setData,避免将不需要渲染层处理的数据在代码中频繁更新。所以这个方案在微信小程序中不是一个高效的方案。