场景复现
水平排列的<image>组件的空白缝隙问题,在部分手机上显示有缝隙,实际上 wxss 设置的是没有任何空间的,并且排查过并非display: inline-block; 而导致的问题。
而不一定所有的手机上都有缝隙,可能是 DeviceA 上面看起来有缝隙;DeviceB 上面完美衔接。
原因
1)先说结论:
height 出现小数而导致的,如 height: 200.87px;
2)为什么会有小数?
通过检查元素得出结论是 <image mode="widthFix"> 的时候,宽度100%,高度根据图片的宽度保持比例不变情况下自适应(自动计算高度),而计算的时候为了保持图片等比,就出现了高度有小数的情况。
3)更深入的理解
打个比方:一个设备的宽度为375px ,那么在这个设备上渲染一张 750 * 320 图片。
那么这张图片宽度 100% ,并且高度是等比缩放的时候,我们可以通过一个公式来得到这张图片的「实际渲染大小」,(750 / 2 = 375) * (320 / 2 = 160) = 375px * 160px。此时高度的最终计算结果没有小数,因此不会出现“白线”。如果再假设图片高度为 321 的时候,那么 321 / 2 = 160.5 ,这时候“白线”就来了。
其他人的解决方式
有用 display: flex; + flex-direction: column; 或者是 margin-top: -1px; ,发现这对我都不好使,治标不治本。
我目前尝试过可行的方案
封装一个 ImageBase 的基础组件,使用这个基础组件来代替原生 image 组件的渲染。
其原理是,依赖 image 组件的 load 事件来获取关于图片的基础信息,重新计算图片的高度,并且确保高度为整数。
一共四个文件:
// ImageBase.js
Component({
properties: {
src: {
type: String,
value: ''
}
},
data: {
height: 'auto'
},
methods: {
imageLoaded(e) {
const { width, height } = e.detail
const ratio = width / height
setTimeout(() => {
const query = this.createSelectorQuery()
const selector = `#imageBase`
query
.select(selector)
.boundingClientRect((rect) => {
const h = (Math.round(rect.width) / ratio) * 2
this.setData({ height: h + 'rpx' })
})
.exec()
})
}
},
lifetimes: {
attached() {},
ready() {}
}
})
ImageBase.wxml
<image src="{{src}}" id="imageBase" bindload="imageLoaded" style="height: {{height}};" class="image"
show-menu-by-longpress="true"></image>
ImageBase.less
.image {
width: 100%;
display: block;
font-size: 0;
}
ImageBase.json
{
"component": true
}