vue2实现生成二维码和复制保存图片功能(复制的同时会给图片加文字)

<template>
  <div
    style="
      display: flex;
      justify-content: center;
      align-items: center;
      width: 100vw;
      height: 100vh;
    "
  >
    <div>
      <!-- 生成二维码按钮和输入二维码的输入框 -->
      <input v-model="url" placeholder="输入链接" type="text" />
      <button @click="generateQRCode">输入网址链接生成二维码</button>
      <hr />

      <!-- 生成图片主要的容器部分 -->
      <div
        class="container"
        style="
          margin-top: 20px;
          /* border: 1px solid; */
          width: 200px;height: 200px;
          display: flex;
          flex-direction: column;
          align-items: center;
        "
      >
        <div v-if="qrCode">
          <img :src="qrCode" style="width: 200px;height: 200px;border: 1px #CCCCCC solid;" alt="QR Code" />
        </div>
      </div>

      <!-- 保存图片和复制图片按钮 -->
      <div
        style="
          width: 100%;
          display: flex;
          justify-content: space-around;
          align-items: center;
          height: 100px;
        "
      >
        <button @click="saveImage">保存图片</button>
        <button @click="copyImage">复制图片</button>
      </div>
    </div>
  </div>
</template>

<script>
// yarn add qrcode 执行命令安装
import QRCode from "qrcode";
// yarn add html2canvas@1.0.0-rc.4 执行命令安装
import html2canvas from "html2canvas";
export default {
  data() {
    return {
      url: "", // 这个是输入框的值
      qrCode: "", // 这个是二维码图片的url
      base64Image: "", // 这个是保存图片和复制图片使用的base64图片地址
    };
  },
  methods: {
    // 将页面内容生成图片的逻辑
    generateimages() {
      // 获取容器元素
      const container = document.querySelector(".container");
      const that = this;
      // 使用 html2canvas 生成图片
      return html2canvas(container, {
        useCORS: true, // 开启跨域配置
        allowTaint: false, // 允许跨域图片
        scale: 2, // 按比例增加分辨率 (2=双倍).
        dpi: window.devicePixelRatio * 2, // 设备像素比
        height: document.querySelector('.container').clientHeight + 3, // 预防生成的图片截图不全的问题(例如加填充,边框等,就会导致截图不全,这样适当给截图区域加一点距离)
      })
        .then((canvass) => {
          // 在canvas上添加文字内容准备
          const title = "萧寂";
          const title2 = "萧寂的文件分享";
          const title3 = "有效期至: 2024/04/08 23:59:59";

          // 创建画布
          const canvas = document.createElement("canvas");

          // 设置 Canvas 元素的宽度和高度,与生成的canvas宽高一致
          canvas.width = canvass.width;
          canvas.height = canvass.height;

          // 获取 Canvas 的 2D 绘图上下文
          const ctx = canvas.getContext("2d");
          // 设置背景颜色为白色
          ctx.fillStyle = "#FFFFFF";
          // 创建白色块,宽高等于1画布的宽高
          ctx.fillRect(0, 0, canvas.width, canvas.height);

          // 设置圆形的中心位置(x和y轴)
          var centerX = canvas.width / 2;
          var centerY = 40;

          // 设置圆形的半径
          var radius = 30;

          // 绘制圆形
          ctx.beginPath();
          // (参数:中心点横坐标,中心点纵坐标,半径,路径(这里是2π代表整个圆),顺时针还是逆时针(由于是一整个圆,就不区分顺时针和逆时针了))
          ctx.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
          // 圆的填充颜色
          ctx.fillStyle = "blue";
          ctx.fill();

          // 创建一个图片对象
          const image = new Image();
          // 图片对象的src指向生成的图片的base64字符串,通过canvass.toDataURL()获得
          image.src = canvass.toDataURL();

          // 这里使用了promise,预防异步
          return new Promise((resolve, reject) => {
            // 等图片加载完毕
            image.onload = function () {
              // 下面三个是获取三个文字的宽
              const titleWidth = ctx.measureText(title).width;
              const titleWidth2 = ctx.measureText(title2).width;
              const titleWidth3 = ctx.measureText(title3).width;
              // 在 Canvas 上绘制图片(每个参数含义(图片源,横坐标,纵坐标,宽,高))
              ctx.drawImage(
                image,
                canvas.width / 2 - canvas.width / 4+5,
                canvas.height / 2 - canvas.height / 4+50,
                canvas.width / 2,
                canvas.height / 2
              );

              // 绘制其他内容
              ctx.fillStyle = "#FFFFFF"; // 指定文字颜色
              ctx.font = "16px Arial"; // 指定文字字号大小(只需要改前面的数字就行)
              
              // !!!!注意,下面的文字理论可以通过canvas.width / 2 - titleWidth/ 2直接定位到水平中间的,但是如果画布内容有html内容则也会有影响的,因此这里需要手动调整
              // 将文字定位到指定位置(参数(文字,横坐标,纵坐标))
              ctx.fillText(title, (canvas.width / 2 - titleWidth/ 2-6), 45);

              // 指定第二个文字的位置和颜色
              ctx.fillStyle = "#000000"; // 指定文字颜色
              ctx.font = "20px Arial";
              ctx.fillText(title2, (canvas.width / 2 - titleWidth2), 100);

              // 指定第三个文字的位置和颜色
              ctx.fillStyle = "#000000"; // 指定文字颜色
              ctx.font = "13px Arial";
              ctx.fillText(title3, (canvas.width / 2 - titleWidth3/2-20), 130);

              // 将 Canvas 转换为 base64 图片并保存
              console.log("canvas.toDataURL()", canvas.toDataURL());
              that.base64Image = canvas.toDataURL();

              // 操作完成,resolve Promise
              resolve("完成");
            };

            image.onerror = function (error) {
              // 操作失败,reject Promise
              reject(error);
            };
          });
        })
        .catch((error) => {
          console.error("生成图片出错:", error);
          throw error;
        });
    },
    generateQRCode() {
      // 生成二维码逻辑(参数指定url文字即可)
      QRCode.toDataURL(this.url)
        .then(async (qr) => {
          this.qrCode = qr;
          // 生成完二维码重新对容器的内容进行图片的生成
          // 这里会有异步情况,建议等一会
          setTimeout(()=>{
            this.generateimages()
          },1000)
        })
        .catch((error) => {
          console.error("生成二维码出错:", error);
        });
    },
    saveImage() {
      // 保存图片功能
      // 创建一个虚拟的链接元素
      const link = document.createElement("a");
      // 指定a元素href地址(指向base64图片)
      link.href = this.base64Image;
      // 下载图片的图片名后缀
      link.download = "image.png";

      // 使用点击事件模拟下载操作
      link.dispatchEvent(new MouseEvent("click"));
    },
    copyImage() {
      // 实现复制图片到剪贴板的逻辑
      // 创建一个Image元素并设置src为base64图片
      const image = new Image();
      image.src = this.base64Image;
      console.log("复制的图片为:", this.base64Image);
      // 等待图片加载完成
      image.onload = () => {
        // 创建一个canvas元素
        const canvas = document.createElement("canvas");
        // 获取canvas上下文对象
        const ctx = canvas.getContext("2d");

        // 设置canvas的尺寸与图片一致
        canvas.width = image.width;
        canvas.height = image.height;

        // 将图片绘制到canvas上
        ctx.drawImage(image, 0, 0, image.width, image.height);

        // 调用Clipboard API将canvas内容复制到剪贴板
        canvas.toBlob((blob) => {
          const item = new ClipboardItem({ "image/png": blob });
          navigator.clipboard
            .write([item])
            .then(() => {
              console.log("图片已复制到剪贴板");
            })
            .catch((err) => {
              console.error("复制图片失败:", err);
            });
        });
      };

      image.onerror = (err) => {
        console.error("图片加载失败:", err);
      };
    },
  },
};
</script>

<style>
*{
  padding: 0;
  margin: 0;
}
</style>

效果图

在这里插入图片描述
点击复制图片或者保存图片的效果图

在这里插入图片描述

  • 22
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

萧寂173

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值