由于项目需要,在一些落地页,以及专题页和首页中,需要放置单列、2列、3列以及4列的广告图。用户可以根据需要,通过在系统后端上传图片,自己搭建一些广告效果。单列的图片可以多张铺满屏幕,主要是商品或活动信息展示,多列的图片可以模拟多产品或专题选择的效果。
对于单列广告图,设置样式宽度100%、2列设置宽度50%、3列的设置为250rpx正好是1/3屏幕,4列的设为25%。在<image>标签里,设置mode='widthFix',让小程序内部自己计算高度。这样基本就可以满足需求了。
然而,情况并没有想象中简单。在一些机型的手机上(诸如iPhone12、13),有些单列图之间出现了水平缝隙,一些并排的多列图之间也出现了竖向的缝隙。
通过网上搜索和自己的实验,有了比较简单的解决方法:
1. 解决竖向排版的单列图之间的缝隙,在图片样式上加一句margin-top: -1rpx;基本就可以了。
2. 解决多列图间的缝隙,把图片放大一点点就行了,比如样式:transform: scale(1.01); 。
这2个方法十分简单,但是并不能保证效果最好。虽然在有问题的机型上消除了缝隙,但是在一些本来没有问题的机型上,仔细看,有些地方会发现拼接处少了一行或一列像素。对于拼接处细节明显,或者要求高质量视觉效果的场合,上面2个解决方法达不到最好的效果。
观察图片的绘制大小,最后猜测,缝隙出现的根源,是由于图片绘制大小宽或高数值中有带小数,导致画在屏幕上时,对小数的取舍出现问题,基于此思路,想到了最后这个方法:
3. 在Js脚本中计算图片显示宽高,并将结果调整至整数数值:
这个方法需要用到image组件的bindload事件。这个事件图片载入完毕时触发,而且返回图片(原图)的宽和高。
下面这段js代码是bindload响应函数示例,实现2列广告图,图片的显示宽与高计算:
// 广告图2列图片加载,计算显示大小,避免拼接图片间白缝
onAdImgLoad: function(e){
var imgIdx = e.currentTarget.dataset.idx;
const sw = wx.getSystemInfoSync().screenWidth, srcW = e.detail.width, srcH = e.detail.height;
var displayW = Math.floor(sw / 2), displayH = Math.floor(sw / 2 * srcH / srcW);
if(sw % 2 == 1 && imgIdx % 2 == 1) displayW += 1;
this.setData({
[`adList[${imgIdx}].imgW`]: displayW,
[`adList[${imgIdx}].imgH`]: displayH
});
},
先计算图片宽是屏幕的一半,并舍去小数(使用floor),按比例算出高度(也舍去小数)。然后如果屏幕宽为奇数,则在每行第2张图的宽上加上1个像素,补足全屏宽度。
在wxml中,用style给图片宽、高赋值即可:
(省略了image外层的for循环和其他wxml代码)
<image src='{{item.FileName}}' bindload='onAdImgLoad' data-idx="{{index}}"
style="width:{{item.imgW}}px; height:{{item.imgH}}px;"></image>
这个计算也有细小误差,但大小不超过1个像素,也不会少绘制一行或一列像素,视觉观察不到,可以忽略不计。所以相对来说,是效果最好的一个方法了。这里就列举了2列平铺广告图的处理,其他的3列、4列等,可以类推,这里不再赘述了。