问题:
微信小程序系统自带的 wx.previewImage
预览大图功能很好用,用起来很顺畅丝滑,但是有一个致命问题:预览大图的时候是在新页面中打开,当前页面的生命周期会销毁,如果当前页面中没有实时的东西还好,但如果有类似 <live_player>
<live_push>
<video>
等组件,或者有计时器之类的变量的时候,你会发现当前页面的这些组件或变量就没法使用了,如果想在当前页面下打开大图,那么就无法使用官方 wx.previewImage
这个方法,这是需要我们自定义一个大图预览组件。
扫一下体验效果:
两种预览大图方式:
1、系统方法:wx.previewImage
优点:系统自带,效果好,全屏,手势顺畅丝滑,使用方便简单
缺点:在新页面中打开,预览时会调用当前页面的生命周期onHide方法,会导致当前页面的变量无法使用,具体表现形式为:live_play 没有声音,暂停播放,倒计时无法继续计时等问题
使用:
wx.previewImage({
current: imgUrl, // 当前显示图片的http链接
urls: [imgUrl] // 需要预览的图片http链接列表
})
官方文档:wx.previewImage
2、自定义组件:< previewImg >
优点:可解决 wx.previewImage
的致命缺点,调用后是在当前页面展示预览图,不会调用当前页面的生命周期方法,不会对当前页面逻辑造成影响
缺点:体验不如系统自带控件,无法隐藏胶囊,无法实现全屏。(如果想要全屏效果,只能设置当前页面的navigationStyle
来控制隐藏navigationBar
达到全屏的效果)
使用:
.json:
"usingComponents": {
"previewImg":"/components/previewImg/previewImg"
},
.wxml
<previewImg id="previewComponent" previewImgList="{{imgList}}" previewImg="{{currentImg}}" />
.js
// 点击预览大图
openpreviewImg() {
this.selectComponent("#previewComponent").showPreview();
this.setData({
//imgList 图片地址数组
currentImg: this.data.imgList[0]
})
}
previewImg组件代码:
wxml:
<view class="preview_box" wx:if="{{previewHideStatus}}" style="top:{{preview_box_top}}" catchtouchmove='stopPageScroll'>
<view class="totalimg">{{imgindex}}/{{previewImgList.length}}</view>
<view class="preview_box1" style="left:{{left}}" bindtap="jingzhi">
<block wx:for="{{previewImgList}}" wx:key="key">
<view class="img_box">
<view bindtouchstart='touchStart' bindtouchmove='touchMove' bindtouchend='touchEnd'>
<movable-area scale-area>
<movable-view direction="all" animation catchscale="onScale" scale scale-min="1" scale-max="5" scale-value="{{scale}}">
<image src="{{item}}" style="width:100%;" mode="widthFix"></image>
</movable-view>
</movable-area>
</view>
</view>
</block>
</view>
</view>
js 核心代码:
//最困难最核心的代码就是处理手指移动的位置和距离来对图片进行相应的操作
touchStart: function(e) {
this.data.touchStartTime = e.timeStamp //时间点
let sx = e.touches[0].pageX
let sy = e.touches[0].pageY
this.data.touchS = [sx, sy];
},
touchMove: function(e) {
let start = this.data.touchS;
let sx = e.touches[0].pageX;
let sy = e.touches[0].pageY;
this.data.touchE = [sx, sy];
},
touchEnd: function(e) {
this.data.touchEndTime = e.timeStamp //时间点
let start = this.data.touchS
let end = this.data.touchE
let scaleObj = this.data.scaleObj
//如果((start[0] < end[0] - 50) && (scaleObj.scale==1&&scaleObj.x==0&&scaleObj.y==0)) //左滑动
//如果((start[0] > end[0] + 50) && (scaleObj.scale==1&&scaleObj.x==0&&scaleObj.y==0)) //右滑动
if (scaleObj.yes) {
if (end[0] == 0) {
console.log('点击')
} else if ((start[0] < end[0] - 50) && (scaleObj.scale == 1 && scaleObj.x == 0 && scaleObj.y == 0)) {
if (this.data.index !== 0) {
this.data.index -= 1;
this.data.imgindex -= 1;
this.setData({
index: this.data.index,
left: '-' + this.data.index + '00%;transition: all .5s;',
imgindex: this.data.imgindex
});
}
} else if ((start[0] > end[0] + 50) && (scaleObj.scale == 1 && scaleObj.x == 0 && scaleObj.y == 0)) {
if (this.data.index !== this.data.previewImgList.length - 1) {
this.data.index += 1;
this.data.imgindex += 1;
this.setData({
index: this.data.index,
left: '-' + this.data.index + '00%;transition: all .5s;',
imgindex: this.data.imgindex
});
}
} else {
console.log('下滑/上滑');
this.setData({
preview_box_top: '100%'
})
}
this.data.touchE = [0, 0];
}
setTimeout(() => {
if (this.data.scaleObj.x == 0 && this.data.scaleObj.y == 0 && this.data.scaleObj.scale == 1) {
// console.log('yes is true');
this.data.scaleObj.yes = true;
}
}, 500)
}
组件源码可以去 git 下载,目录是:/components/previewImg 文件夹
组件源码涉及公司代码,已隐藏,全部主要的代码都已在上述中贴上了,直接使用即可
2024-7-11修改:补齐wxss代码
page{
height: 100%;
}
.preview_box{
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: #000;
white-space: nowrap;
transition: all .3s;
height: 100%;
z-index: 99999;
}
.preview_box>.totalimg{
color: #fff;
position: absolute;
z-index: 999;
top: 10px;
display: flex;
justify-content: center;
width: 100%;
}
.preview_box>.preview_box1{
height: 100%;
position: relative;
}
.img_box{
position: relative;
display: inline-block;
width: 100%;
height: 100%;
}
.img_box>view{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-items: center;
}
movable-view {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
color: #fff;
}
movable-area {
height: 100%;
width: 100%;
overflow: hidden;
}Ï```