app点击分享生成海报 - canvas

点击分享按钮,将背景图、标题、二维码、介绍文字等内容合并生成为分享海报,需要通过canvas将所需元素重新拼接绘制为新的图片,具体代码如下:

html

需要建立一个canvas画布,并定义其canvas-id属性,以便后续使用

<template>
  <view>
    <canvas
      class="myCanvas"
      canvas-id="myCanvas"
      :style="'width:' + posterWidth + 'px; height:' + posterHeight + 'px'"
    ></canvas>
  </view>
</template>

js

  • 首先,定义状态值,存储设备屏幕的宽高、海报宽高、图片url,并接收父组件传递的海报所需信息(图片、文字等)。
  • 其次,使用uni.createCanvasContext(canvasId, this)创建画布ctx,这时就用到了canvas定义的canvas-id属性啦
  • 为了更好地适配设备,我们通过uni.getSystemInfo 获取一下设备的宽高,并且结合ui设计图,确定海报的宽高

 接下来,就要正式进行画图操作了!

  • 定义绘制海报各个元素的方法

    • 绘制背景 ——  ctx.drawImage 绘制背景图,ctx.setFillStyle填充背景色,ctx.fillRect绘制矩形区域并填充指定的内容;

    • 绘制二维码 —— 同样需要使用drawImage、setFillStyle、fillRect,另外由于此处ui设计有阴影,需要通过ctx.setShadow添加一下图片阴影【canvas绘制会根据绘制先后对绘制内容进行叠加,也就是后绘制的部分会自动位于画面图层顺序的最顶层,注意一下】

    • 插入文字 ——  ctx.setFillStyle和ctx.setFontSize先确定文字的样式,再通过ctx.fillText进行文字的创建

  • 定义绘制海报并保存的方法

    • 调用所定义的绘制各个元素的方法

    • 通过ctx.draw进行绘制,并调用uni.canvasToTempFilePath(object, component),把当前画布指定区域的内容导出生成指定大小的图片,并通过成功的回调获取到返回的图片文件路径

    • 一旦获取图片url,就可以通过uni.saveImageToPhotosAlbum(OBJECT),保存我们的海报图片到系统相册咯~

  • 最最后,由于这里是vue3,因此记得要将子组件的方法通过defineExpose({ drawPoster })暴露出去,以供父组件调用,实现功能。

<script setup lang="ts">
const windowWidth = ref(0); // 设备屏幕宽度
const windowHeight = ref(0); // 设备屏幕高度
const posterWidth = ref(0); // 海报宽度
const posterHeight = ref(0); // 海报高度
const imgUrl = ref(""); // 最终生成的海报图片url

// 接收父组件传递的海报所需内容数据
const { posterData } = defineProps<{
  posterData: any;
}>();

// 创建画布
const ctx = uni.createCanvasContext("myCanvas", this);

// 获取系统宽高
const getSystem = () => {
  uni.getSystemInfo({
    success: function (res) {
      windowHeight.value = res.windowHeight;
      windowWidth.value = res.windowWidth;
      posterWidth.value = res.windowWidth * 0.8;
      posterHeight.value = posterWidth.value * 1.375;
    },
  });
};

// 绘制背景图
const setBg = () => {
  ctx.drawImage(
    posterData.backgroundUrl,
    0,
    0,
    posterWidth.value,
    posterHeight.value
  );
  ctx.setFillStyle("#ffffff");
  ctx.fillRect(
    posterWidth.value * 0.1,
    posterHeight.value * 0.8,
    posterWidth.value * 0.8,
    posterHeight.value * 0.15
  );
  ctx.save();
};
// 绘制二维码
const setQrcode = () => {
  ctx.setFillStyle("#ffffff");
  ctx.setShadow(0, 1, 10, "#FAD3AC");
  ctx.fillRect(
    posterWidth.value * 0.12,
    posterHeight.value * 0.82,
    posterWidth.value * 0.16,
    posterWidth.value * 0.16
  );
  ctx.drawImage(
    posterData.qrcode,
    posterWidth.value * 0.12,
    posterHeight.value * 0.82,
    posterWidth.value * 0.16,
    posterWidth.value * 0.16
  );
  ctx.save();
};
// 绘制文字
const setText = (text, color, size, x, y) => {
  console.log("渲染文字", text);
  ctx.save();
  ctx.setFillStyle(color);
  ctx.setFontSize(size);
  ctx.fillText(text, x, y);
  ctx.save();
};
// 绘制海报
const drawPoster = () => {
  setBg();
  setQrcode();
  setText(
    posterData.title,
    "#666666",
    10,
    posterWidth.value * 0.36,
    posterHeight.value * 0.86
  );
  setText(
    posterData.context,
    "#666666",
    10,
    posterWidth.value * 0.36,
    posterHeight.value * 0.91
  );
  setTimeout(() => {
    //必须延时执行 不然h5不显示
    ctx.save();
    ctx.draw(true, () => {
      setTimeout(() => {
        uni.canvasToTempFilePath(
          {
            canvasId: "myCanvas",
            success: (res) => {
              uni.showLoading({
                title: "保存中...",
              });
              console.log(res.tempFilePath);
              imgUrl.value = res.tempFilePath;
              // #ifdef MP
              uni.getSetting({
                success(ress) {
                  uni.hideLoading();
                  console.log(ress);
                  if (!res.authSetting["scope.writePhotosAlbum"]) {
                    wx.authorize({
                      scope: "scope.writePhotosAlbum",
                      success: (ress) => {
                        console.log(ress);
                      },
                    });
                  } else {
                    setTimeout(() => {
                      uni.saveImageToPhotosAlbum({
                        filePath: imgUrl.value,
                        success(re) {
                          uni.hideLoading();
                          uni.showToast({
                            title: "保存成功",
                            icon: "success",
                          });
                        },
                        fail(err) {
                          console.log(err);
                          uni.showToast({
                            title: "保存失败",
                            icon: "none",
                          });
                        },
                      });
                    }, 1000);
                  }
                },
              });
              // #endif
              // #ifdef APP-PLUS
              setTimeout(() => {
                uni.saveImageToPhotosAlbum({
                  filePath: imgUrl.value,
                  success(re) {
                    uni.hideLoading();
                    uni.showToast({
                      title: "保存成功",
                      icon: "success",
                    });
                  },
                  fail(err) {
                    console.log(err);
                    uni.showToast({
                      title: "保存失败",
                      icon: "none",
                    });
                  },
                });
              }, 1000);
              // #endif
            },
          },
          this
        );
      }, 300);
    });
  });
};
getSystem();

defineExpose({ drawPoster });
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值