封装小程序图片预览组件-商品评价功能

背景

wx.previewImage无法添加文字,所以需要手动封装小程序图片预览插件
在这里插入图片描述

$headerIconWidth: 32px;
$swiperImageHeight: 1068rpx; // 534px
page {
  background-color: black;
  box-sizing: border-box;
  height: 100%;
}
.bigImageBox {
  background-color: black;
  box-sizing: border-box;
  color: #ffffff;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 9px;
    box-sizing: border-box;
    width: 100%;
    .header-left {
      border-radius: 50%;
      width: $headerIconWidth;
      height: $headerIconWidth;
      .header-left-icon {
        width: 100%;
        height: 100%;
      }
    }
    .header-center {
      color: #ffffff;
      font-size: 17px;
      flex: 1;
      display: flex;
      justify-content: center;
    }
    .header-right {
      width: $headerIconWidth; // 为了跟.header-left同宽,适应flex
    }
  }
  .bigImage-swiperBox {
    // margin-top: 50px;
    width: 100%;
    .swiperItem {
      width: 100%;
      height: 100%;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      .swiperItem-image {
        width: 100%;
        height: $swiperImageHeight;
      }
    }
  }
  .bigImage-info {
    // height: 200rpx;
    max-height: 200rpx;
    padding: 0 12px 12px 12px;
    box-sizing: border-box;
    font-size: 12px;
    color: #ffffff;
    .info-sku {
      margin: 6px 0;
      color: #999999;
    }
  }
}
.movableBox {
  width: 100%;
  height: 100%;
  overflow: hidden;
}

movable-view {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  width: 100%;
  color: #fff;
}

movable-area {
  height: 100%;
  width: 100%;
  overflow: hidden;
}

头部按钮
<view class="bigImageBox" style="height:100vh;">
  <view class="header" style="position: fixed; height:	{{menuInfo.height}}px;top:{{menuInfo.top}}px;z-index:999;">
    <view class="header-left" catchtap="onPageBack">
      <image lazy-load="{{true}}" src="{{commentsTopBackIconUrl}}" class="header-left-icon" />
    </view>
    <view class="header-center">
      <text class="imageIndex">{{swiperCurrent + 1}}</text>
      /
      <text class="imageLength">{{swiperLength}}</text>
    </view>
    <view class="header-right"></view>
  </view>
  <!--  轮播图+movable -->
  <swiper current="{{swiperCurrent}}" class="bigImage-swiperBox" style="width:100%;height:100%;" catchchange="onSwiperChange" catchtransition='onChange'>
    <block wx:for="{{imageList}}" wx:key="index">
      <swiper-item item-id="">
        <movable-area scale-area class='swiperItem movableBox'>
          <movable-view direction="all" disabled="{{!item.enableMove  &&  isHSwiper}}" data-index="{{index}}" animation catchscale="onScale" scale damping="999"  scale-min="1" scale-max="2" scale-value="{{swiperCurrent===index?scale:1}}" style=" width:100%;height:100%;" catchchange="slideChange"  catchvtouchmove="{{!isSwiper?'touchmove':''}}" catchhtouchmove="{{!isSwiper?'touchmove':''}}" out-of-bounds>
            <image lazy-load="{{true}}" mode="aspectFit" style="max-width:100%;max-height:100%;" show-menu-by-longpress="{{shareImg}}" src="{{item.bigImagePath || item.imagePath}}" class="swiperItem-image" data-index="{{index}}" catchtap="onClosePage" />
          </movable-view>
        </movable-area>
      </swiper-item>
    </block>
  </swiper>
  <!--文字显示-->
  <scroll-view class="bigImage-info" scroll-y="{{true}}" style="position:fixed;bottom:40rpx;">
    <wxs module="fn">
      module.exports = {
        nickNameHandle: function(str = '') {
          return str.substring(0, 1) + '***' + str.substring(str.length - 1, str.length)
        }
      }
    </wxs>
    <view class="info-name">{{fn.nickNameHandle(detailInfo.nickName)}}</view>
    <view class="info-sku">{{detailInfo.skuSpec}}</view>
    <view class="info-content">{{detailInfo.content}}</view>
  </scroll-view>
</view>
import wepy from 'wepy'
import { productImages } from '@/constant/images'
import { debounce, throttle } from '@/utils/index'
Page({
  data: {
    commentsTopBackIconUrl: productImages.commentsTopBack,
    menuInfo: {},
    commentList: [], // 所有评论
    commentIndex: 0, // 当前评论的索引
    imageIndex: 0, // 当前图片的索引
    imageList: [],
    swiperCurrent: 0, // 当前所在滑块的index
    swiperLength: 0, // 所有滑块的数量
    detailInfo: {}, // 显示的名称规格评价等信息
    shareImg: true, // 是否可以分享图片
    isCloseImg: true, // 是否关闭大图
    scale: 1,
    lastTapTimeoutFunc: null,
    lastTapDiffTime: 0,
    isScale: false, // 是否双指放大 ,如果是,用户双击scale变成1
    isSwiper: true, // 是否禁止swiper滑动,为解决图片放大滑动和swiper滑动冲突
    movableType: 'touch', // movable组件触摸类型,正常touch,触碰到边界out-of-bounds,touch-out-of-bounds
    x_axis: 0, // movable的x坐标
    allowOneMove: false, // 只允许一次
    dxMax: 0,
    isHSwiper: false // 上下也会触发边界事件,阻止用户在上下滑动时被当作左右滑动而禁止了movable
  },
  onLoad(option) {
    option = wepy.$instance.commonInitialSceneOptions(option)
    let { productId, skuId, commentIndex, imageIndex } = option
    this.setData({
      commentIndex: Number(commentIndex), // option传递过来是string类型
      imageIndex: Number(imageIndex)
    })
  },
  onShow() {
    let menuInfo = wx.getMenuButtonBoundingClientRect()
    let commentList = wepy.$instance.globalData.commentList || []
    console.log('评论页 menuInfo:', commentList)
    this.setData({
      menuInfo,
      commentList
    })
    this.getImageList()
    this.getDetailInfo(this.data.swiperCurrent)
  },
  // 获取图片list   所有图片,非当前用户发表图片,数量根据已加载的评价数变化
  getImageList() {
    let allImageList = []
    let currentImgIndex = 0
    console.log('评论页sadhakdhak:', this.data.commentList)
    if (this.data.commentList.length > 0) {
      this.data.commentList.forEach((item, index) => {
        if (index === this.data.commentIndex) {
          currentImgIndex = allImageList.length + this.data.imageIndex
        }
        if (item.commentImageDtoList && item.commentImageDtoList.length > 0) {
          // 评论中有图片时才push
          item.commentImageDtoList.forEach((cit, cin) => {
            allImageList.push(cit)
          })
        }
      })
    }

    this.setData({
      imageList: allImageList,
      swiperCurrent: currentImgIndex,
      swiperLength: allImageList.length
    })
  },
  // 获取下方的评论内容detialInfo
  getDetailInfo(swiperCurrent) {
    let detailInfo = {}
    let commentIdCur =
      this.data.imageList.length > 0 && this.data.imageList[swiperCurrent]
        ? this.data.imageList[swiperCurrent].commentId
        : ''
    if (this.data.commentList.length > 0) {
      this.data.commentList.forEach((item) => {
        if (String(commentIdCur) === String(item.uuid)) {
          // 说明 是某个人的评论
          detailInfo = item
        }
      })
    }
    this.setData({
      detailInfo
    })
  },
  // 左上角返回按钮
  onPageBack() {
    const eventChannel = this.getOpenerEventChannel()
    eventChannel.emit('acceptDataFromOpenedPage', 'commentsBigImage')
    wx.navigateBack()
  },
  // 点击大图后关闭
  onClosePage(e) {
    if (!this.data.isCloseImg) {
      return
    }
    const { index } = e.currentTarget.dataset
    console.log(index, this.data.swiperCurrent, 'onClosePage++++')
    let _this = this
    let curTime = new Date().getTime()
    let lastTime = _this.data.lastTapDiffTime
    _this.data.lastTapDiffTime = curTime
    //  两次点击间隔小于300ms, 认为是双击
    let diff = curTime - lastTime
    if (diff < 300) {
      _this.setData({
        scale:
          _this.data.scale == 1 && index === this.data.swiperCurrent ? 2 : 1,
        isSwiper: _this.data.scale == 1 // 如果是正常图片可以滑动
      })
      clearTimeout(_this.data.lastTapTimeoutFunc) // 成功触发双击事件时,取消单击事件的执行
    } else {
      if (!this.data.isCloseImg) {
        return
      }
      // 单击事件延时300毫秒执行
      _this.data.lastTapTimeoutFunc = setTimeout(function () {
        console.log(_this.data.isCloseImg, '单击+++')
        // 回到pdp
        if (_this.data.isCloseImg) {
          _this.onPageBack()
        }
      }, 300)
    }
  },

  // 滑动后将左右两侧的数据重置
  resetImageListAdditionProperties(index) {
    let _previous = index - 1
    let _next = index + 1
    if (_previous >= 0) {
      this.setData({
        [`imageList[${_previous}].isScaling`]: false,
        [`imageList[${_previous}].enableMove`]: false
      })
    }
    if (_next < this.data.imageList.length) {
      this.setData({
        [`imageList[${_next}].isScaling`]: false,
        [`imageList[${_next}].enableMove`]: false
      })
    }
  },
  // swiper滑动throttle
  onSwiperChange(e) {
    this.setData({
      scale: 1
    })
    // 微信官方提醒:如果在 bindchange 的事件回调函数中使用 setData 改变 current 值,则有可能导致 setData 被不停地调用,
    // 因而通常情况下请在改变 current 值前检测 source 字段来判断是否是由于用户触摸引起
    // 1、autoplay 自动播放导致 swiper 变化;
    // 2、touch 用户划动引起 swiper 变化;
    // 3、其它原因将用空字符串表示。
    if (e.detail.source !== 'touch' && e.detail.source !== 'autoplay') {
      return false
    }
    this.resetImageListAdditionProperties(e.detail.current)
    this.getDetailInfo(e.detail.current)
    this.setData({
      swiperCurrent: e.detail.current
    })
  },
  onScale(e) {
    const { scale } = e.detail
    this.setData(
      {
        shareImg: false,
        isCloseImg: false,
        isSwiper: false,
        [`imageList[${this.data.swiperCurrent}].isScaling`]: scale > 1,
        [`imageList[${this.data.swiperCurrent}].enableMove`]: scale > 1
      },
      () => {
        setTimeout(() => {
          this.setData({ shareImg: true, isCloseImg: true })
        }, 500)
      }
    )
  },
  // 禁止用户滑动
  catchTouchMove(e) {
    return this.data.isSwiper
  },
  slideChange: throttle(
    function (e) {
      console.log(e, 'e+++')
      const { source } = e.detail
      // 节流,判断是否触碰左右边界
      if (source == 'out-of-bounds' || source == 'touch-out-of-bounds') {
        this.setData({
          isSwiper: true,
          [`imageList[${this.data.swiperCurrent}].enableMove`]: false
        })
      }
      this.setData({movableType: source})
    },
    800,
    1
  ),
  onChange: throttle(function (e) {
    const {dx} = e.detail
    // 当用户触发swiper移动
    this.setData({
      isHSwiper: true
    })
    // dx为0 =>滑动又弹回去,可以movalble不可以swiper
    // if (this.data.dxMax > parseInt(dx)) {
      if (dx > -20  && dx < 20) {
      this.setData({
        shareImg: false,
        isCloseImg: true,
        isSwiper: false,
        isScale: false,
        isHSwiper: false,
        [`imageList[${this.data.swiperCurrent}].isScaling`]: false,
        [`imageList[${this.data.swiperCurrent}].enableMove`]: true
      })
    }
    if (Math.abs(this.data.dxMax - parseInt(dx)) > 10) {
      console.log(dx, 'onChange++++')
      this.setData({
        dxMax: parseInt(dx)
      })
    }
  }, 100, 2)
})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值