uniapp vue2 微信小程序项目使用canvas绘制画布并导出图片

封装组件

<template>
  <view class="page">
    <view>
      <canvas :style="{ width: canvasW + 'px', height: canvasH + 'px' }" canvas-id="myCanvas" id="myCanvas01">
      </canvas>
      <button class="btn" v-if="isShow" @click="saveImage">保存至相册</button>
    </view>
  </view>
</template>
<script>
export default {
  data() {
    return {
      canvasW: 0, // 画布宽
      canvasH: 0, // 画布高
      SystemInfo: {}, // 设备信息
      goodsImg: {}, // 商品主图信息
      ewmImg: {}, // 二维码图片信息
      ewmW: 140, // 二维码大小
      title: '商品标题商品标题商品标题', // 商品标题
      price: '4158.00', // 价格
      name: '浪迹天涯', // 推荐人
      isShow: false,
    }
  },
  async onLoad(option) {
    // 获取设备信息,主要获取宽度,赋值给canvasW 也就是宽度:100%
    this.SystemInfo = await this.getSystemInfo();
    console.log(this.SystemInfo, '我是设备宽度');
    // this.title = option.goodsTitle
    // this.price = option.goodsPrice

    this.title = '我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题我是标题';
    this.price = '价格价格价格';

    // this.id = option.id  
    // 获取商品主图,二维码信息,APP端会返回图片的本地路径(H5端只能返回原路径)
    // let goodsImgUrl = option.goosImg // 主图本地路径,也可以用网络地址
    let goodsImgUrl = 'http://img.touxiangwu.com/2020/3/uq6Bja.jpg' // 头部封面图片

    // var arr = [];
    // arr.push(option.id)
    // arr.push(option.shopId)
    // var param = {
    // 	code: arr.join(","),
    // 	path: 'pages/commodity_details/index'
    // }
    // shareCodeGet(param).then(res => {	//调接口
    // 	console.log(res, 'resres')
    // let ewmImgUrl = res.data.msg;	//二维码图片地址-从接口取
    // 以下内容放接口里面---下面的内容放接口里面-主要返回二维码地址
    // })

    // 以下内容放接口里面---
    let that = this
    uni.downloadFile({
      url: goodsImgUrl,
      success: function (logoRes) {
        goodsImgUrl = logoRes.tempFilePath
        var ewmImgUrl =
          'https://citybalcony.oss-cn-qingdao.aliyuncs.com/west/pics/d5887fd3-f2bf-4826-8ba3-bde70e71b2f26872716576832637570.jpg';
        uni.downloadFile({
          url: ewmImgUrl,
          success: function (logoRes) {
            ewmImgUrl = logoRes.tempFilePath
            that.canvasW = that.SystemInfo.windowWidth; // 画布宽度
            that.canvasH =
              580 //this.goodsImg.height + this.ewmW + 10;  // 画布高度 = 主图高度+二维码高度 + 文字图片的间距(大概50)

            uni.showToast({
              icon: 'loading',
              mask: true,
              duration: 10000,
              title: '海报绘制中',
            });
            setTimeout(() => {
              var ctx = uni.createCanvasContext(
                'myCanvas', that);
              // 1.填充背景色,白色
              ctx.setFillStyle('#fff'); // 默认白色
              ctx.fillRect(0, 0, that.canvasW, that
                .canvasH) // fillRect(x,y,宽度,高度)

              // 2.绘制商品主图,二维码
              ctx.drawImage(goodsImgUrl, 0, 0, that
                .canvasW, that
                  .canvasW - 100
              ) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度)
              // ctx.drawImage(ewmImgUrl, 50, this.canvasW + 75, this.ewmW, this
              // 	.ewmW) // drawImage(图片路径,x,y,绘制图像的宽度,绘制图像的高度,二维码的宽,高)
              ctx.drawImage(ewmImgUrl, that.canvasW / 2 -
                that.canvasW / 2.4 / 2, that
                  .canvasW + that
                  .ewmW - 150, that.ewmW, that.ewmW
              ); //填充进图片 二维码
              // 3.绘制商品标题,多余文字自动换行
              ctx.setFontSize(
                16); // setFontSize() 设置字体字号
              ctx.setFillStyle(
                '#333'); // setFillStyle() 设置字体颜色

              // 4、商品价格
              ctx.setFontSize(16) // 字号
              ctx.setFillStyle('#FE470E') // 颜色
              ctx.fillText('¥' + that.price || '', 10,
                that.canvasW - 75); // (文字,x,y)

              // 5、标题
              ctx.setFontSize(16)
              ctx.setFillStyle('#333')
              let _strlineW = 0;
              let _strLastIndex = 0; //每次开始截取的字符串的索引
              let _strHeight = that.canvasW -
                50; //绘制字体距离canvas顶部的初始高度
              let _num = 1;
              for (let i = 0; i < that.title
                .length; i++) {
                _strlineW += ctx.measureText(that
                  .title[i]).width + 0.5;
                if (_strlineW > that.canvasW) {
                  if (_num == 2 && 2) {
                    //文字换行数量大于二进行省略号处理
                    ctx.fillText(that.title
                      .substring(
                        _strLastIndex, i -
                      5) + '...' ||
                      '', 10,
                      _strHeight);
                    _strlineW = 0;
                    _strLastIndex = i;
                    _num++;
                    break;
                  } else {
                    ctx.fillText(that.title
                      .substring(
                        _strLastIndex, i
                      ) || '', 10,
                      _strHeight);
                    _strlineW = 0;
                    _strHeight += 20;
                    _strLastIndex = i;
                    _num++;
                  }
                } else if (i == that.title.length -
                  1) {
                  ctx.fillText(that.title.substring(
                    _strLastIndex, i + 1
                  ) || '', 10,
                    _strHeight);
                  _strlineW = 0;
                }
              }

              ctx.setFontSize(14)
              ctx.setFillStyle('#b8b8b8')
              ctx.fillText('长按或扫描识别二维码' || '', that
                .canvasW / 2 - that.canvasW / 2.4 /
                2,
                that.canvasW +
                that
                  .ewmW + 10);

              // draw方法 把以上内容画到 canvas 中
              ctx.draw(true, (ret) => {
                that.isShow =
                  true // 显示按钮-保存图片到相册
                uni.showToast({
                  icon: 'success',
                  mask: true,
                  title: '绘制完成',
                });
                uni.canvasToTempFilePath({ // 保存canvas为图片
                  canvasId: 'myCanvas',
                  quality: 1,
                  complete: function (
                    res) {
                    // 在H5平台下,tempFilePath 为 base64, // 图片提示跨域 H5保存base64失败,APP端正常输出临时路径
                    console
                      .log(
                        res
                          .tempFilePath,
                        '66666666'
                      )
                    uni.setStorageSync(
                      'filePath',
                      res
                        .tempFilePath
                    ) //保存临时文件路径到缓存
                  },
                })
              });
            }, 1500)

          }
        })
      }
    })
  },

  methods: {
    // 获取图片信息
    getImageInfo(image) {
      return new Promise((req, rej) => {
        uni.getImageInfo({
          src: image,
          success: function (res) {
            req(res)
          },
        });
      })
    },

    // 获取设备信息
    getSystemInfo() {
      return new Promise((req, rej) => {
        uni.getSystemInfo({
          success: function (res) {
            req(res)
          }
        });
      })
    },

    // 保存图片到相册
    saveImage() {
      let filePath = uni.getStorageSync('filePath') //从缓存中读取临时文件路径		
      console.log(filePath, "filePath")
      uni.saveImageToPhotosAlbum({
        filePath: filePath,
        success() {
          uni.showToast({
            title: '图片保存成功',
            icon: 'none'
          })
        },
        fail(e) {
          uni.showToast({
            title: '图片保存失败',
            icon: 'none'
          })
        }
      })
    }

  }
}
</script>

<style lang="scss" scoped>
.btn {
  margin: 20rpx;
  width: 94%;
  background: linear-gradient(135deg, #ff913d 0%, #ff3c06 100%) !important;
  border-radius: 49rpx;
  font-size: 36rpx;
  font-family: PingFangSC-Medium, PingFang SC;
  font-weight: 500;
  color: #ffffff;
  text-align: center;
  line-height: 98rpx;
}
</style>
<template>
  <view class='commonShare'>
    <image class='shareImg' mode="widthFix" :src='url'></image>
    <view class="footer">
      <button @click="share">保存并分享</button>
    </view>
  </view>
</template>
<script>
export default {
  data() {
    return {
      url: ''
    };
  },
  components: {
  },
  onLoad(options) {
    //options 传过来的值
    this.url = options.url
    //获取相册授权
    wx.getSetting({
      success(res) {
        if (!res.authSetting['scope.writePhotosAlbum']) {
          wx.authorize({
            scope: 'scope.writePhotosAlbum',
            success() {
              console.log('授权成功')
            }
          })
        }
      }
    })
  },
  mounted() {

  },
  methods: {
    share() {
      var that = this;
      wx.showLoading({
        title: '保存中...',
        mask: true
      });
      wx.saveImageToPhotosAlbum({
        filePath: that.url,
        success: function (res) {
          wx.showToast({
            title: '保存成功',
            icon: 'success',
            duration: 2000
          })
        },
        fail: function (res) {
          wx.hideLoading()
          console.log(res)
        }
      })
    },
  },
};

</script>
<style>
.commonShare {
  padding-bottom: 152rpx;
  background: #333;
  height: 100%;
  width: 100%;
  overflow-y: auto;
  position: absolute;
  -webkit-overflow-scrolling: touch;
}

.shareImg {
  width: 100%;
}
</style>

代码有点乱,需要你自己去读代码理解。在这里我只是给自己记录一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值