Bootstrap

微信小程序预览图片和H5使用canvas实现图片+蒙层+文字

1、效果

2.H5实现

<!--
 * @Author: limingfang
 * @Date: 2024-05-20 10:26:51
 * @LastEditors: limingfang
 * @LastEditTime: 2024-05-21 16:31:11
 * @Description: 
-->
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <meta name="viewport" content="width=device-width, initial-scale=1.0">  
    <title>Canvas Draw Image and Elements</title>  
    <style>
        body {
            padding: 0;
            margin: 0;
        }
    </style>
</head>  
<body>  
    <canvas id="myCanvas" width="375" height="375"></canvas>  
  
    <script>  
        const canvas = document.getElementById('myCanvas');  
        const ctx = canvas.getContext('2d');  
  
        // 加载图片  
        const img = new Image();  
        img.onload = function() {  
            // 绘制图片  
            ctx.drawImage(img, 0, 0, 375, 375); // 参数:图片对象, x坐标, y坐标, 宽度, 高度  
  
            // 绘制文本  
            ctx.font = '28px Arial';  
            ctx.fillStyle = '#767B8D';  
            ctx.fillText('处方药', 146, 174);  
            ctx.fillText('依法不展示包装', 90, 222);  
            ctx.filter = 'blur(5px)';
  
            // 导出为图片(可选)  
            const dataUrl = canvas.toDataURL('image/png');  
            console.log(dataUrl,'dataUrl00000000000000000000');
            // 你可以使用dataUrl进行进一步的操作,例如将其设置为img元素的src属性  
            const imgElement = document.createElement('img');  
            imgElement.src = dataUrl;  
            imgElement.style.filter = 'blur(5px)';  
            document.body.appendChild(imgElement);  
        };  
        img.src = './4.jpg'; // 替换为你的图片路径  
		img.crossOrigin = "anonymous";//添加此行anonymous必须小写
    </script>  
</body>  
</html>

3.小程序实现

        <swiper indicator-color="#efeff4" indicator-active-color="#f16a33" circular="true" interval="2000" duration="600" bindchange="handleSwiperChange">
          <block wx:for="{{ json_data.goods[0].images }}" wx:key="index" wx:for-index="index" wx:for-item="item">
            <swiper-item>
              <image src="{{ filter.formattingPictureThumbnail(['750', '750'], item.img_url) }}" class="swiper-image" 
              data-index="{{index}}"
              catchtap="previewMedia"
              mode="aspectFit" />
              <view catchtap="previewMedia" data-index="{{index}}" wx:if="{{json_data.medicinesIsPrescribe&&mark.markFlag}}" class="d6-goods-img-no absolute left-0 top-0 w-full text-center box-border" style="-webkit-backdrop-filter: blur({{mark.markTransparency}}px);backdrop-filter:blur({{mark.markTransparency}}px);">
                <view catchtap="previewMedia" data-index="{{index}}">
                  <view catchtap="previewMedia" data-index="{{index}}">处方药</view>
                  <view catchtap="previewMedia" data-index="{{index}}">依法不展示包装</view>
                </view>
              </view>
            </swiper-item>
          </block>
        </swiper>
/**
   * 绘制canvas图片+图片阴影+蒙层
   * @returns 
   */
  initCanvasImages(){
    let images = this.data.json_data?.goods && this.data.json_data?.goods[0]?.images || [];
    if(images.length <= 0) return;
    let sources = [];
    const _this = this;
    if (this.data.json_data.medicinesIsPrescribe && this.data.mark.markFlag) {
      // 获取canvas上下文  
      wx.createSelectorQuery()
      .select('#goodsCanvas')
      .fields({
        node: true,
        size: true,
      })
      .exec((canvasRes)=>{
        if(canvasRes.length <= 0) return;
        const canvas = canvasRes[0].node;
        const ctx = canvas.getContext('2d');

        // 设置canvas的宽度和高度与图像相同  
        canvas.width = 375;  
        canvas.height = 375;  

        images.forEach((item,index) => {
            images[index] = canvas.createImage();
            images[index].onload = function() {

            // 简单模糊处理(非高斯模糊): 只是多次绘制图片来模拟模糊效果
            for (let i = 0; i < _this.data.mark.markTransparency; i++) { // 重复次数越多,模糊效果越明显  
              ctx.globalAlpha = 1 / (i + 1); // 每次绘制时降低透明度  
              ctx.drawImage(images[index], i, i, 375, 375); // 参数:图片对象, x坐标, y坐标, 宽度, 高度  
            }  
            // 重置透明度  
            ctx.globalAlpha = 0.2;  
            ctx.filter = `blur(${_this.data.mark.markTransparency})px`;

            // 绘制文本  
            ctx.font = '28px Arial';
            ctx.fillStyle = '#767B8D';
            ctx.fillText('处方药', 146, 168);
            ctx.fillText('依法不展示包装', 90, 210);

            const dataUrl = canvas.toDataURL('image/png', 0.5); 
            sources[index] = {
              url: dataUrl,
              type: item.img_type === 3 ? 'image' : 'video'
            };

            // 清除画布内容  
            ctx.clearRect(0, 0, 375, 375); // 清除画布上的所有内容,参数是画布的宽高  
            };
            images[index].src = item.img_url;
        })
      });
    } else {
      sources = images.map(item => ({
        url: item.img_url,  // 图片或视频的地址
        type: item.img_type === 3 ? 'image' : 'video' // 需要预览的资源类型
      }));
    }
    this.setData({
      canvasImages: sources
    });
  },
  /**
   * 预览图片/video
   */
  async previewMedia(e) {
    let current = e.target.dataset.index;
    wx.previewMedia({
      sources: this.data.canvasImages, // 需要预览的资源列表
      current // 当前显示的资源序号
    })
  },

;