原生微信小程序中处理点击不规则图片的透明区域不触发点击事件

154 阅读2分钟

前言

最近在公司项目原生小程序开发中遇到UI给出的一张不规则图形需要增加点击事件,产品需求是除在这张图片点击触发事件,不包含透明区域,也是头次遇见这个需求,但这个问题也是前端开发中经常会出现和遇到的问题,可能之前做B端项目很少有遇到,此篇文章主要记录该需求的解决方案,废话不多说上方案和代码

方案一:给图片对应区域增加点击热点


这个方案实现起来很简单,就是在对应区域增加一个块级标签,定位到图片对应区域,给该块级标签增加点击事件触发相应操作,代码如下

    <view class="box-img-wrapper">
       <image class="box-img" src="https://assets.xxxx.com/assets/xxx.png" />
       <view class="hot-deal-img-top" catchtap="handle">
       </view>
       <view class="hot-deal-img-bottom"catchtap="handle">
       </view>
   </view>
.box-img-wrapper {
      position: relative;
      .box-img {
        width: 300rpx;
        height: 464rpx;
        margin: 0 auto;
        display: block;
      }
      .hot-deal-img-top { 
        position: absolute;
        top: 0;
        left: 50%;
        width: 188rpx;
        height: 45rpx;
      }
      .hot-deal-img-bottom {
        position: absolute;
        top: 45rpx;
        left: 50%;
        transform: translateX(-150rpx);
        width: 300rpx;
        height: 350rpx;
      }
    }
handle() {
    //Todo 对应事件操作
    console.log(22222)
}
  • 优点:简单易实现,完全靠css来实现
  • 缺点:仍然会存在盲区,多一点区域或者少一点

方案二:类似方案一,将图片分块切然后拼接,不推荐该方案


方案三:借助convas来绘制该张图片,获取到具体rgba值后对透明度为0的区域直接return,代码如下


<view class="container" bindtap="handleTap">
  <canvas id="myCanvas" type="2d"></canvas>
</view>
Page({
  data: {
    
  },
  onLoad: function () {
    const imageSrc = 'https://assets.xxxx.com/assets/xxx.png';
    wx.getImageInfo({
      src: imageSrc,
      success: res => {
        const width = res.width;
        const height = res.height;
        this.createConvasImage(imageSrc,width,height)
      }
    })
  },
  createConvasImage(imgUrl,imgW,imgH) {
    wx.createSelectorQuery()
      .select('#myCanvas') // 在 WXML 中填入的 id
      .node(({
        node: canvas
      }) => {
        
        const context = canvas.getContext('2d')
        const image = canvas.createImage()
        
        image.onload = () => {
          context.drawImage(
            image,
            0,
            0,
            imgW,
            imgH
          )
        }
        image.src = imgUrl
      })
      .exec()
  },
  onReady() {
 // 获取系统信息
 wx.getSystemInfo({
  success: res => {
      console.log(res);
      this.setData({
          windowWidth: res.windowWidth,
          windowHeight: res.windowHeight,
      });
      this.setData({
          // 屏幕宽度 375px = 750rpx,1px=2rpx
          // 1px = (750 / 屏幕宽度)rpx;
          // 1rpx = (屏幕宽度 / 750)px;
          ratio: 750 / this.data.windowWidth
      });
  }
});
  },
  handleTap: function (event) {
    const x = event.detail.x;
    const y = event.detail.y;
    wx.createSelectorQuery()
    .select('#myCanvas') // 在 WXML 中填入的 id
    .node(({
      node: canvas
    }) => {
      
      const context = canvas.getContext('2d')
      const imageData = context.getImageData(x, y, 1, 1)
      console.log(imageData)
      if(imageData.data[3] === 0) {
        return
      }
      // todo 对应操作
    })
    .exec()
  }
});
  • 优点:无盲区,就是完全符合产品的需求的实现方案
  • 缺点:方案较复杂,还要考虑兼容问题,不适用于首页等页面,体验感会不乐观