微信小程序开发生成海报并保存本地(一张图片+一段文字)

css
 

.container1 {  
  display: flex;  
  justify-content: center;  
  align-items: center;  
  height: 100vh;  
  // padding-top: 140rpx;
background-color: #000;
color: red;
display: flex;
justify-content: center;
align-items: center;
}

json
 

{
  "navigationStyle":"custom",
  "usingComponents": {}
}

html
 

<view class="container1">
  <canvas canvas-id="myCanvas" style="width: 400px; height: 80%;"></canvas>
  <view bindtap="savePicture">保存图片</view>
</view>

ts
 

Page({
  data: {
    productDesc: '',
    productUrl: ''
  },
  savePicture() {
    console.log("保存图片");

    let that = this;
    wx.canvasToTempFilePath({
      width: 375,
      canvasId: 'myCanvas',
      success(res) {
        that.saveImg(res.tempFilePath)
      },
      fail: function () {
        console.log('fail-downloadFile')
      }
    })
  },
  saveImg(tempFilePath) {
    let that = this;
    wx.saveImageToPhotosAlbum({
      filePath: tempFilePath,
      success: function () {
        // applyApi.toast('保存成功!', 'success')
        wx.showToast({
          title: '保存成功!',
          icon: 'success',
          duration: 2000,
          mask: true,
        })
      },
      fail: function () {
        if (wx.getStorageSync('canvasSave') == true) {
          that.openSetting(tempFilePath)
        }
        wx.setStorageSync('canvasSave', true)
      }
    })
  },
  openSetting(tempFilePath) {
    let that = this;
    wx.getSetting({
      success: (res) => {
        if (res.authSetting['scope.writePhotosAlbum']) {
          that.saveImg(tempFilePath)
        } else {
          wx.showModal({
            title: '是否授权保存到相册',
            content: '需要获取您的保存图片权限,请确认授权,否则图片将无法保存到相册',
            success: function (tip) {
              if (tip.confirm) {
                wx.openSetting({
                  success: function (data) {
                    if (data.authSetting['scope.writePhotosAlbum'] === true) {
                      applyApi.toast('授权成功')
                      that.saveImg(tempFilePath)
                    } else {
                      applyApi.toast('授权失败')
                    }
                  }
                })
              }
            }
          })
        }
      }
    })
  },
  onLoad: function (options: any) {
    console.log("海报页", options, options.productDesc, options.productUrl);
    this.setData({
      productDesc: options.productDesc,
      productUrl: options.productUrl
    })
    this.getImgInfo()
  },
  getImgInfo() {
    let that = this
    wx.getImageInfo({
      src: this.data.productUrl,
      success(res) {
        console.log(res)
        that.drawCombinedImage()
      }
    })

  },
  downLoadImage(list) {
    return new Promise((resolve) => {
      const loadList = []
      const listLen = list.length
      let downTimes = 0
      for (let i = 0; i < listLen; i++) {
        wx.downloadFile({
          url: list[i],
          success(res) {
            if (res.statusCode === 200) {
              loadList[i] = res.tempFilePath
            }
          },
          complete: function () {
            if (++downTimes >= listLen) {
              resolve(loadList)
            }
          }
        })
      }
    })
  },
  drawCombinedImage: function () {
    const imgList = [this.data.productUrl];
    this.downLoadImage(imgList).then(loadList => {

      console.log("this.data.productUrl8888888888", this.data.productUrl);
      const ctx = wx.createCanvasContext('myCanvas');
      const imgSrc = loadList[0];
      // const imgSrc='../../static/home/car.png'
      const text = this.data.productDesc;
      const fontSize = 14;
      const lineHeight = 20; // 行高,根据字体大小和间距调整  
      const canvasWidth = 400; // canvas的宽度  
      const padding = 20; // 文本与canvas边界的内边距  

      // 绘制图片  
      // 设置画布背景为白色(如果需要的话)  
      //  ctx.setFillStyle('#fff')
      //  ctx.fillRect(10, 10, 150, 75)
      ctx.fillStyle = "#fff";
      ctx.fillRect(0, 0, 750, 980);
      ctx.drawImage(imgSrc, 0, 50, canvasWidth, 300);

      // 拆分文本并绘制每一行  
      console.log("text", text, ctx, canvasWidth, canvasWidth - 2 * padding);

      let lines = this.splitTextByWidth(text, canvasWidth - 2 * padding, fontSize);
      let y = 350 + padding; // 起始y坐标,根据图片高度调整  
      console.log("lines.length", lines, lines.length);

      for (let i = 0; i < lines.length; i++) {
        ctx.setFillStyle('#000');
        ctx.fillText(lines[i], padding, y);
        y += lineHeight; // 增加行高以绘制下一行  
      }
      console.log("y8888", y);


      // 导出图片  
      ctx.draw(false, () => {
        wx.canvasToTempFilePath({
          canvasId: 'myCanvas',
          success: (res) => {
            const tempFilePath = res.tempFilePath;
            console.log(tempFilePath);
            // 使用生成的图片路径...  
          },
          fail: (err) => {
            console.error('生成图片失败', err);
          }
        });
      });
    });
  },
  splitTextByWidth(text, maxWidth, fontSize) {
    const ctx = wx.createCanvasContext('tempCanvas');
    ctx.setFontSize(fontSize); // 设置字体大小,与 canvas 组件的样式保持一致  

    let lines = [];
    let currentLine = '';
    let currentWidth = 0;

    for (let i = 0; i < text.length; i++) {
      const char = text[i];
      const metrics = ctx.measureText(char);
      const charWidth = metrics.width;

      if (currentWidth + charWidth > maxWidth) {
        // 当前行宽度加上当前字符宽度超过最大宽度,开始新行  
        lines.push(currentLine);
        currentLine = char;
        currentWidth = charWidth;
      } else {
        // 否则,将字符添加到当前行  
        currentLine += char;
        currentWidth += charWidth;
      }

      // 处理中文字符后可能存在的空格或标点,这些通常宽度较小,可以尝试将它们放在当前行末尾  
      if (/\s|[^\x00-\xff]/.test(char)) {
        // 如果是空格或非ASCII字符(可能是中文字符),尝试将其与前一个字符合并检查宽度  
        const combinedWidth = ctx.measureText(currentLine + char).width;
        if (combinedWidth <= maxWidth) {
          currentWidth = combinedWidth;
        } else {
          // 如果合并后超过最大宽度,则回溯到上一行,并开始新行  
          lines.push(currentLine.slice(0, -1)); // 移除最后一个字符  
          currentLine = char;
          currentWidth = charWidth;
        }
      }
    }

    // 添加最后一行  
    if (currentLine) {
      lines.push(currentLine);
    }

    return lines;
  }
});

效果图

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值