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

news2024/12/27 11:09:38
<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;
          display: flex;
          flex-direction: column;
          align-items: center;
        "
      >
        <div v-if="qrCode">
          <img :src="qrCode" 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, // 设备像素比
      })
        .then((canvass) => {
          // 在canvas上添加文字
          const title = "小米科技";
          const src = "链接为:" + this.url;
          const text = "图片复制到的内容";

          const canvas = document.createElement("canvas");

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

          // 获取 Canvas 的 2D 绘图上下文
          const ctx = canvas.getContext("2d");

          // 创建一个图片对象
          const image = new Image();
          image.src = canvass.toDataURL();
          return new Promise((resolve, reject) => {
            image.onload = function () {
              // 下面三个是定义生成的图片里面的文字的
              const textWidth = ctx.measureText(text).width;
              const titleWidth = ctx.measureText(title).width;
              const srcWidth = ctx.measureText(src).width;
              // 在 Canvas 上绘制图片(每个参数含义(图片源,横坐标,纵坐标,宽,高))
              ctx.drawImage(
                image,
                canvas.width / 2 - canvas.width / 4,
                canvas.height / 2 - canvas.height / 4,
                canvas.width / 2,
                canvas.height / 2
              );

              // 绘制其他内容
              ctx.fillStyle = "blue"; // 指定文字颜色
              ctx.font = "16px Arial"; // 指定文字字号大小(只需要改前面的数字就行)
              ctx.fillText(
                text,
                canvas.width / 2 - textWidth / 2,
                canvas.height - 30
              ); // 将文字定位到指定位置(参数(文字,横坐标,纵坐标))
              ctx.fillText(title, canvas.width / 2 - titleWidth / 2, 30);
              ctx.fillText(src, canvas.width / 2 - srcWidth / 2, 50);

              // 将 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;
          // 生成完二维码重新对容器的内容进行图片的生成
          // 这里会有异步情况,会导致图片base64地址不对,因此这里执行了两次,如果自己跑还不够的话可以再往下补一次
          await this.generateimages();
          await this.generateimages();
        })
        .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>

效果图

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1646052.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

重写muduo之EPollPoller

1、EPollPoller.h EPollPoller的主要实现&#xff1a;作为poller的派生类&#xff0c;把基类给派生类保留的这些纯虚函数的接口实现出来。 override表示在派生类里面&#xff0c;这些方法是覆盖方法。必须由编译器来保证在基类里面一定有这些函数的接口的声明。在派生类要重写…

[蓝桥杯2024]-PWN:ezheap解析(堆glibc2.31,glibc2.31下的double free)

查看保护 查看ida 大致就是只能创建0x60大小的堆块&#xff0c;并且uaf只能利用一次 完整exp&#xff1a; from pwn import* #context(log_leveldebug) pprocess(./ezheap2.31)def alloc(content):p.sendlineafter(b4.exit,b1)p.send(content) def free(index):p.sendlineaft…

代码随想录算法训练营DAY46|C++动态规划Part8|139.单词拆分、多重背包理论基础、背包问题总结篇

文章目录 139.单词拆分思路CPP代码 多重背包理论基础处理输入把所有个数大于1的物品展开成1个开始迭代&#xff0c;计算dp数组代码优化 背包问题总结篇 139.单词拆分 力扣题目链接 文章讲解&#xff1a;139.单词拆分 视频讲解&#xff1a;你的背包如何装满&#xff1f;| LeetCo…

体育老师工资高吗,奖金有吗

教师的薪资水平与多种因素相关&#xff0c;包括教育经验、工作地点、学校类型以及个人的教学成果等。在讨论体育教师的工资问题时&#xff0c;不能仅仅关注数字&#xff0c;更应了解教育价值和个人发展。 初中体育教师的工资水平受多种因素影响。根据网络统计的数据&#xff0c…

STM32F4xx开发学习—GPIO

GPIO 学习使用STM32F407VET6GPIO外设 寄存器和标准外设库 1. 寄存器 存储器映射 存储器本身是不具有地址的&#xff0c;是一块具有特定功能的内存单元&#xff0c;它的地址是由芯片厂商或用户分配&#xff0c;给存储器分配地址的过程就叫做存储区映射。给内存单元分配地址之后…

页面多开、谷歌浏览器解决不能批量打开问题、批量打开被限制

目录 问题原因谷歌浏览器解决办法来看效果 问题 我们使用批量打开页面的时候 只能打开第一个页面 原因 这种问题是因为 浏览器限制了浏览器的弹出 并不是人家页面功能不能用 谷歌浏览器解决办法 在浏览器输入这个路径 chrome://settings/content/popups?search%E9%87%…

Vue MVVM这一篇就够啦!

Vue vs React 相似之处: 它们都有使用 Virtual DOM虚拟DOM-CSDN博客&#xff1b;提供了响应式&#xff08;Reactive&#xff09;和组件化&#xff08;Composable&#xff09;的视图组件。将注意力集中保持在核心库&#xff0c;而将其他功能如路由和全局状态管理交给相关的库。R…

Python安装以及环境配置

目录 一、下载安装包二级目录三级目录 一、下载安装包 方式网址Python官网python.org镜像下载地址Download pythonpycharmDownload PyCharm https://blog.csdn.net/sun80760/article/details/135256627 二级目录 三级目录

Spring+SpringMVC+Jsp实现校园二手交易系统

前言介绍 在社会快速发展的影响下&#xff0c;使校园二手交易系统的管理和运营比过去十年更加理性化。依照这一现实为基础&#xff0c;设计一个快捷而又方便的网上校园二手交易系统是一项十分重要并且有价值的事情。对于传统的管理控制模型来说&#xff0c;网上校园二手交易系…

C++构造函数和析构函数的调用顺序

一般情况下&#xff0c;调用析构函数的次序正好与调用构造函数的次序相反&#xff0c;也就是最先被调用的构造函数&#xff0c;其对应的析构函数最后被调用&#xff0c;而最后被调用的构造函数&#xff0c;其对应的析构函数最先被调用。 当然对象的构造函数和析构函数调用时机和…

图片浏览器-PicView

一、前言 PicView 是一款适用于 Windows 10 或 11 的快速高效的图像查看器&#xff0c;配备了干净简洁的用户界面&#xff0c;可以在不需要时方便地隐藏。 二、支持类型 它支持广泛的图像文件类型&#xff0c;包括&#xff1a;WEBP、GIF、SVG、PNG、JXL、HEIC、PSD 三、软件特…

Docker 的网络实现

简介 标准的 Docker 支持以下 4 类网络模式&#xff1a; 1&#xff09;host 模式&#xff1a;使用 --nethost 指定 2&#xff09;container 模式&#xff1a;使用–netcontainer:NAME_or_ID 指定 3&#xff09;none模式&#xff1a;使用 --netnone 指定 4&#xff09;bridge 模…

2.5W字 一文读懂汽车智能座舱的FLASH 存储市场、技术

吃瓜群众&#xff1a;机哥&#xff0c;存储是什么玩意&#xff0c;我买手机、电脑的时候导购员都说买内存大的&#xff0c;三星的好&#xff0c;品牌大&#xff0c;问题少&#xff0c;我也只有看哪个内存大就买那个。 机哥&#xff1a;额&#xff0c;这个嘛&#xff0c;说来话长…

SpringBoot+Vue+Element-UI实现学生综合成绩测评系统

前言介绍 学生成绩是高校人才培养计划的重要组成部分&#xff0c;是实现人才培养目标、培养学生科研能力与创新思维、检验学生综合素质与实践能力的重要手段与综合性实践教学环节。而学生所在学院多采用半手工管理学生成绩的方式&#xff0c;所以有必要开发学生综合成绩测评系…

Day62:单调栈 LeedCode503. 下一个更大元素 II 42. 接雨水

503. 下一个更大元素 II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元素 是按数组遍历顺序&#xff0c;这个数字之后的第一个比它更大的数…

分布式与一致性协议之ZAB协议(三)

ZAB协议 主节点崩溃了&#xff0c;怎么办&#xff1f; 众所周知&#xff0c;系统在运行中不可避免会出现各种各样的问题&#xff0c;比如进程崩溃了、服务器死机了&#xff0c;这些问题会导致很严重的后果&#xff0c;让系统没办法继续运行。在ZAB协议中&#xff0c;写请求是…

【软考】模拟考卷错题本2024-05-05

1 算法 关键词&#xff1a;按照单位重量价值大优先&#xff0c;那就是1、2、3即430&#xff1b;之后的根据排除法又可以得到630&#xff1b;故C。 2 UML 序列图 上图已经基本上有解析&#xff1b;重点在于在四个选项中选正确的。根据概念排除&#xff1a;异步和同步是不一样的&…

GateWay检查接口耗时

添加gateway依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency>创建一个LogTimeGateWayFilterFactory类&#xff0c;可以不是这个名字但是后面必须是x…

opencv基础篇 ——(十六)图形绘制与填充

OpenCV 提供了丰富的图形绘制和填充功能&#xff0c;主要通过 cv::rectangle, cv::circle, cv::line, cv::polylines, cv::fillPoly 和 cv::ellipse 等函数实现。以下是一些基本的图形绘制和填充操作的说明&#xff1a; 矩形: 函数: cv::rectangle语法: cv::rectangle(img, rec…

10000 字详细讲解 Spring 中常用注解及其使用

如下图京东购物页面&#xff0c;当我们选择点击访问某一类商品时&#xff0c;就会向后端发起 HTTP 请求&#xff0c;当后端收到请求时&#xff0c;就会找到对应的代码逻辑对请求进行处理&#xff0c;那么&#xff0c;后端是如何来查找处理请求相对应的代码呢&#xff1f;答案就…