注册
web

小程序轮播图的高度如何与图片高度保持一致


一、存在现象




  • 在原生小程序中,我们从服务器获取轮播图的数据,这些图片的数据都是有一定宽高的,我们需要去适配这些图片在不同手机上显示时的宽高,不然的话,在不同的设备上就会不同的效果,也就出现了所谓的bug,如下案例:




  • 这是在iPhone Xr上的显示效果:轮播图的指示点显示正常
    image.png




  • 这是在iPhone 5上的显示效果:轮播图的指示点就到图片下方去了
    image.png




二、解决方法


思路



  • 在图片加载完成后,获取到图片的高度,获取到之后进行赋值。这样的话,我们需要使用image标签的bindload属性,当图片加载完成时触发

image.png



  • 获取图片高度,可以当做获取这个轮播图组件的高度,这组件是小程序界面上的一个节点,可以使用获取界面上的节点信息APIwx.createSelectorQuery()来获取

const query = wx.createSelectorQuery()
query.select('#the-id').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec(function(res){
res[0].top // #the-id节点的上边界坐标
res[1].scrollTop // 显示区域的竖直滚动位置
})



  • 节点信息查询 API 可以用于获取节点属性、样式、在界面上的位置等信息。最常见的用法是使用这个接口来查询某个节点的当前位置,以及界面的滚动位置。如下图所示,里面有我们所需要的height,我们将这个height赋值给swiper组件,再令image标签mode="widthFix",即可自动适应轮播图高度和图片的高度保持一致



    • widthFix:缩放模式,宽度不变,高度自动变化,保持原图宽高比不变
    • HeightFix:缩放模式,高度不变,宽度自动变化,保持原图宽高比不变



  • 这是iPhone Xr上的数据,height:152.4375
    image.png




  • 这是iPhone 5上的数据,height:118.21875
    image.png




实现



  • wxml:轮播图

<swiper class="swiper" autoplay indicator-dots circular interval="{{4000}}" style="height: {{swiperHeight}}px;">
<block wx:for="{{banners}}" wx:key="bannerId">
<swiper-item class="swiper-item">
<image class="swiper-image" src="{{item.pic}}" mode="widthFix" bindload="getSwiperImageLoaded"></image>
</swiper-item>
</block>
</swiper>


  • js:只展示获取图片高度的代码,像获取轮播图数据代码已省略

Page({
data: {
swiperHeight: 0, // 轮播图组件初始高度
},

// 图片加载完成
getSwiperImageLoaded() {
// 获取图片高度
const query = wx.createSelectorQuery();
query.select(".swiper-image").boundingClientRect();
query.exec((res) => {
this.setData({ swiperHeight: rect.height });
});
},
})


  • 在上述代码中getSwiperImageLoaded方法也可以进行抽离到utils中成为一个工具函数,并用Promise进行返回,方便其他地方需要使用到

export default function (selector) {
return new Promise((resolve) => {
const query = wx.createSelectorQuery();
query.select(selector).boundingClientRect();
query.exec(resolve)
});
}


  • 所以在上述的实现代码中getSwiperImageLoaded方法可以进行如下的优化:

getSwiperImageLoaded() {
// 优化
queryRect(".swiper-image").then((res) => {
const rect = res[0];
this.setData({ swiperHeight: rect.height });
});
},


  • 如此一来,在iPhone 5上的轮播图组件展示也正常

image.png



  • 最后,因为获取的是轮播图,那么获取的数据就不止一条,按以上代码逻辑,获取到多少条数据就会执行多少遍setData赋值操作,所以可以考虑使用防抖或者节流进行进一步优化。

作者:晚风予星
来源:juejin.cn/post/7232625387296129080

0 个评论

要回复文章请先登录注册