效果图
代码如下
组件中
- wxml 中
<view class="preview-img-container" wx:if="{
{previewHideStatus}}" style="top:{
{previewBoxTop}}" catchtouchmove='stopPageScroll'>
<view class="num-indicator" style="height:{
{customBar}}px;padding-top:{
{statusBar}}px">{
{
imgIndex}}/{
{
previewImgList.length}}</view>
<view class="preview-box" style="left:{
{left}}" bindtap="singleClick">
<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 class="preview-img-oper-btn">
<button catchtap="handleOperBtn" id="0" class="btn" open-type="share">分享</button>
<button catchtap="handleOperBtn" id="1" class="btn">保存</button>
</view>
</view>
- wxss 中
page {
height: 100%;
}
.preview-img-container {
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: #000;
white-space: nowrap;
transition: all .3s;
height: 100%;
/* width: 100%; */
z-index: 99999;
}
.preview-img-container>.num-indicator {
color: #fff;
position: absolute;
z-index: 999;
/* top: 10px; */
display: flex;
justify-content: center;
width: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.preview-img-container>.preview-box {
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;
}
.preview-img-oper-btn {
position: absolute;
bottom: 148rpx;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
.preview-img-oper-btn .btn {
width: 152rpx;
height: 64rpx;
text-align: center;
line-height: 64rpx;
font-weight: 500;
color: #FFFFFF;
font-size: 28rpx;
background: rgba(92, 89, 89, 0.7);
border-radius: 40rpx;
z-index: 999;
}
.preview-img-oper-btn .btn:nth-child(1) {
margin-right: 64rpx;
}
- index.js 中
const app = getApp();
var that;
Component({
/**
* 组件的属性列表
*/
properties: {
previewImgList: {
type: Array,
value: false
},
previewImg: {
type: null,
value: false
},
},
attached: function () {
that = this;
},
/**
* 组件的初始数据
*/
data: {
statusBar: app.globalData.statusBar,
customBar: app.globalData.customBar,
previewBoxTop: 0,
left: '0px;',
touchS: [0, 0],
touchE: [0, 0],
index: 0,
imgIndex:0,
previewHideStatus:false,
scale: 1,
scaleObj:{
scale:1,
x:0,
y:0,
yes:true
},
touchStartTime: 0, // 触摸开始时间
touchEndTime: 0, // 触摸结束时间
lastTapTime: 0, // 最后一次单击事件点击发生时间
tapTimer: null, // 单击事件 点击后要触发的函数
},
/**
* 组件的方法列表
*/
methods: {
handleOperBtn(e) {
const id = e.target.id
const index = this.data.index
console.log('当前图片url:', this.data.previewImgList[index])
if (id == 0) {
console.log('分享')
this.onShareAppMessage()
} else {
console.log('保存')
wx.downloadFile({
url: this.data.previewImgList[index], //需要下载的图片url
success: function (res) {
//成功后的回调函数
wx.saveImageToPhotosAlbum({
//保存到本地
filePath: res.tempFilePath,
success(res) {
wx.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
})
},
fail: function (err) {
if (err.errMsg === "saveImageToPhotosAlbum:fail auth deny") {
wx.openSetting({
success(settingdata) {
console.log(settingdata)
if (settingdata.authSetting['scope.writePhotosAlbum']) {
console.log('获取权限成功,给出再次点击图片保存到相册的提示。')
} else {
console.log('获取权限失败,给出不给权限就无法正常使用的提示')
}
}
})
}
}
})
}
});
}
},
onShareAppMessage: function (ops) {
return {
title: '分享给好友',
path: 'pages/mine/sharing/sharing',//点击分享消息是打开的页面
imageUrl: this.data.previewImg,
success: function (res) {
// 转发成功
console.log("转发成功:" + JSON.stringify(res));
// var shareTickets = res.shareTickets;
},
fail: function (res) {
// 转发失败
console.log("转发失败:" + JSON.stringify(res));
}
}
},
singleClick(e) {
let diffTouch = this.data.touchEndTime - this.data.touchStartTime;
console.log('diffTouch:', diffTouch)
let curTime = e.timeStamp;
let lastTime = this.data.lastTapDiffTime;
this.data.lastTapDiffTime = curTime;
// 两次点击间隔小于300ms, 认为是双击
let diff = curTime - lastTime;
if (diff < 300) {
console.log("double tap")
clearTimeout(this.data.tapTimer); // 成功触发双击事件时,取消单击事件的执行
if(that.data.scale == 1){
that.setData({
scale:3
})
}else{
that.setData({
scale:1
})
}
} else {
this.data.tapTimer = setTimeout(function () {
console.log("single tap")
if(that.data.scaleObj.yes){
that.setData({
previewBoxTop: '100%' })
}
}, 300);
}
},
configqxClick(e) {
this.setData({
scopeWritePhotosAlbum: e.detail }) },
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({
previewBoxTop: '100%' })
}
this.data.touchE = [0, 0];
}
setTimeout(()=>{
if(this.data.scaleObj.x == 0 && this.data.scaleObj.y == 0 && this.data.scaleObj.scale == 1){
this.data.scaleObj.yes = true;
}
},500)
},
showPreview() {
this.setData({
previewHideStatus: true, previewBoxTop: 0 })
},
hidePreview() {
this.setData({
previewHideStatus: false, previewBoxTop: 0 })
},
onScale(e) {
this.data.scaleObj = {
scale:e.detail.scale,
x:e.detail.x,
y:e.detail.y,
yes:false
}
},
stopPageScroll() {
return },
},
observers: {
'previewImgList': function (arr) {
console.log(arr)
},
'previewImg':function(img){
this.data.previewImgList.map((item,index)=>{
if(item == img){
let imgIndex = index;
imgIndex+=1;
this.setData({
index: index, imgIndex: imgIndex, left: '-'+index+'00%;' })
}
})
}
},
})
页面使用组件
- wxml 中
<preview-img id="previewComponent" previewImgList="{
{imgList}}" previewImg="{
{previewImgUrl}}"></preview-img>
- json 中
{
"usingComponents": {
"preview-img":"/components/preview-img/index"
}
}
简单说明
preview-img:组件文件夹名称,自己随意取
- js 中
const app = getApp()
Page({
/**
* 页面的初始数据
*/
data: {
nvabarData: {
title: "社群分享",
isLeftArrow: true, // 是否显示左侧按钮
isLeftTitle: false, // 是否显示左侧标题
},
isIphoneX: app.globalData.isIphoneX,
// 图片数组
imgList: [
'https://img1.baidu.com/it/u=3255190183,75483312&fm=253&fmt=auto?w=400&h=400',
'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2885427348.webp'
],
show: false,
previewImgUrl:'', // 当前预览图片url
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
handlePreviewImage(e){
const {
src } = e.currentTarget.dataset
this.selectComponent("#previewComponent").showPreview();
this.setData({
previewImgUrl: src
})
}
})