vue截图-html2canvas

使用html2canvas进行截图操作

在 Vue 中使用 ​​html2canvas​​ 将 HTML 元素(如包含贝塞尔曲线的 Canvas/SVG)转换为图片

下载html2canvas

npm install html2canvas

在页面中使用,要截取哪个div的内容,先给这个div加一个ref标识,如ref=“html_container”

主要用到的:
在这里插入图片描述

具体代码:

<template><div class="CanvasPage" ref="html_container"><!-- 未处理时的canvas画布数据 --><canvas :id="'canvas' + '002'" :style="`position: absolute; `"></canvas><!-- 使用赛贝尔曲线以及笔锋处理之后的画布数据 --><canvas:id="'canvas' + '001'"@pointerdown.stop="onPointerDown":style="`position: absolute; `"@touchstart="onTouchstart"></canvas><div class="CanvasPageSave"><el-button @click="toSave" type="primary">保存当前页面</el-button></div></div>
</template><script setup>
import { ref, reactive, onMounted } from "vue";
import { Bezier } from "bezier-js";
import html2canvas from 'html2canvas'
let html_container = ref(null);
let canvas, ctx;
let canvasCover, ctxCover;
const winH = window.innerHeight,winW = window.innerWidth;let isMove = false;
// canvas初始化
const initCanvas = () => {canvas = document.getElementById("canvas001");ctx = canvas.getContext("2d", {antialias: true, // 抗锯齿});canvas.width = winW; // canvas宽度canvas.height = winH; // canvas高度ctx.lineWidth = 2; // 画线默认宽度ctx.strokeStyle = "red"; // 设置颜色// 复制出来一份原始的canvas画线数据canvasCover = document.getElementById("canvas002");ctxCover = canvasCover.getContext("2d", {antialias: true, // 抗锯齿});canvasCover.width = winW; // canvas宽度canvasCover.height = winH; // canvas高度ctxCover.lineWidth = 2; // 画线默认宽度ctxCover.strokeStyle = "red"; // 设置颜色
};let startx = ref(0), //起始坐标starty = ref(0),pointerId = ref(null);let points = []; // 收集所有点的数据// pointerdown同时处理鼠标、触摸屏和触控笔。
const onPointerDown = (e) => {points = [];isMove = true;const { offsetX, offsetY } = e;pointerId = e.pointerId;startx.value = offsetX;starty.value = offsetY;canvas.addEventListener("pointermove", onDrawMove);canvas.addEventListener("pointerup", onDrawUp);
};/* 单个触摸事件 */
// 处理移动逻辑
const onDrawMove = (e) => {if (isMove) {const { offsetX, offsetY } = e;if (pointerId != e.pointerId) return;// 原始画线数据ctxCover.beginPath();ctxCover.lineWidth = 2; // 设置线条粗细ctxCover.moveTo(startx.value, starty.value);ctxCover.lineTo(offsetX, offsetY);ctxCover.stroke();ctxCover.closePath();startx.value = offsetX;starty.value = offsetY;points.push({x: offsetX,y: offsetY,});e.preventDefault();}
}
// 处理释放逻辑
const onDrawUp = (e) => {ctx.closePath();// 鼠标释放时处理线条,将处理过的数据显示,之前的数据清空drawSmoothLine();points = [];isMove = false;document.removeEventListener("pointermove", onDrawMove);document.removeEventListener("pointerup", onDrawUp);
}
// 优化线条
const drawSmoothLine = () => {isMove = false;if (points.length > 1) {let num1 = 200; // 补点数let num2 = 20; // 从后面开始变细的点数const startWidth = 2; // 设置线条粗细const endWidth = 0; // 最后变细的宽度ctxCover.clearRect(0, 0, canvasCover.width, canvasCover.height); // 清除原始数据// 在释放的时候使用贝塞尔曲线重新处理画出来的线ctx.lineWidth = startWidth;// 设置线条粗细// 使用赛贝尔曲线让线条更丝滑const bez = new Bezier(points);const pointOnCurve = bez.getLUT(num1); // 补点ctx.beginPath();ctx.moveTo(pointOnCurve[0].x, pointOnCurve[0].y);// 截取,从开始截取到需要变细的位置,正常画线pointOnCurve.slice(0, -num2).forEach((p) => ctx.lineTo(p.x, p.y)); ctx.stroke();// 笔锋,设置线从哪个位置开始,按一定比例变细pointOnCurve.slice(-num2).forEach((p, px) => {const lineWidth = startWidth + ((endWidth - startWidth) * px) / num2;ctx.lineWidth = lineWidth;ctx.lineTo(p.x, p.y);ctx.stroke();});ctx.lineWidth = startWidth;ctx.closePath();}
};const toSave = () => {// html2canvas截取工具,第一个参数是截取的元素这里使用的ref,第二个参数是相应的配置html2canvas(html_container.value, {background: 'transparent',useCORS: true}).then((canvas) => {const base64 = canvas.toDataURL().replace(/^data:image\/(png|jpg);base64,/, '');// console.log(`data:image/png;base64,${base64}`);// 可选:自动下载图片const link = document.createElement('a');link.download = 'bezier-curve.png';link.href = `data:image/png;base64,${base64}`;link.click();});
}
onMounted(() => {initCanvas();
});
</script><style scoped lang="scss">
.CanvasPage {width: 100%;height: 100%;background-color: #044444;position: relative;.CanvasPageSave {position: absolute;left: 0;top: 0;}
}
</style>

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

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

相关文章

介绍Unity中的Dictionary

在 Unity&#xff08;C#&#xff09;中&#xff0c;Dictionary 是一个非常常用的数据结构&#xff0c;它提供 键值对&#xff08;Key-Value Pair&#xff09; 的存储方式。类似于 Python 的 dict 或 JavaScript 的对象&#xff08;Object&#xff09;&#xff0c;但它是强类型的…

MySQL 常用函数(详解)

目录 一、数学函数1.1 四舍五入函数1.2 求绝对值函数二、日期时间函数2.1 获取当前日期和时间三、字符串函数3.1 字符串拼接函数3.2 提取子字符串函数四、聚合函数4.1 计算平均值函数4.2 计算最大值函数五、转换函数5.1 类型转换函数六、总结MySQL 提供了丰富的内置函数,涵盖了…

SOFA编译-Ubuntu20.04-SOFA22.12

一、事前说明 单纯的编译sofa是很简单的&#xff0c;但是想要同时编译SofaPython3则比较难了&#xff0c;我编译了v22.12分支&#xff0c;其他版本sofa的编译也可以参考此篇教程&#xff0c;需注意的是&#xff1a; 1、确定SOFA需要的Python版本&#xff0c;sofa22.12需要的是…

静态BFD配置

AR2配置 int g0/0/0 ip add 10.10.10.2 quit bfd quit bfd 1 bind peer-ip 10.10.10.1 source-ip 10.10.10.2 auto commit AR1配置 int g0/0/0 ip add 10.10.10.1 int g0/0/1 ip add 10.10.11.1 quit bfd quit bfd 1 bind peer-ip 10.0.12.2 source-ip 10.0.12.1 auto co…

关键字where

C# 中的 where 关键字主要用在泛型约束&#xff08;Generic Constraints&#xff09;中&#xff0c;目的是对泛型类型参数限制其必须满足的条件&#xff0c;从而保证类型参数具备特定的能力或特性&#xff0c;增强类型安全和代码可读性。 约束写法说明适用场景举例C#版本要求w…

Arm核的Ubuntu系统上安装Wireshark

Arm核的Ubuntu系统上安装Wireshark 一、安装wireshark 安装命令&#xff1a; sudo apt-get install wireshark-qt 如下图所示&#xff1a; 安装过程弹出如下界面&#xff1a; 鼠标选择Yes&#xff0c;点回车键确认 安装完成。 二、打开wireshark 输入命令行打开wireshark …

编专利或委托他人编专利属于学术不端行为吗?

原文链接&#xff1a;编专利或委托他人编专利属于学术不端行为吗&#xff1f; 自己编专利或委托他人编专利属于学术不端吗&#xff1f; 5月4日&#xff0c;一篇题为《针对性护理干预在子宫肌瘤围手术期的情绪和生活质量临床应用效果》的论文&#xff0c;受到网友的广泛议论。…

Music AI Sandbox:打开你的创作新世界

AI 和音乐人的碰撞 其实&#xff0c;Google 早在 2016 年就启动了一个叫 Magenta 的项目&#xff0c;目标是探索 AI 在音乐和艺术创作上的可能性。一路走来&#xff0c;他们和各种音乐人合作&#xff0c;终于在 2023 年整出了这个 Music AI Sandbox&#xff0c;并且通过 YouTub…

Java游戏服务器开发流水账(2)开发中Maven的管理

Maven 是一款流行的 Java 项目管理工具&#xff0c;它基于项目对象模型&#xff08;Project Object Model&#xff0c;POM&#xff09;的概念来管理项目的构建、依赖和文档等。游戏服务器开发中也会使用. 项目构建 生命周期管理&#xff1a;Maven 定义了一套清晰的项目构建生…

枚举 · 例8扩展-校门外的树:hard

登录—专业IT笔试面试备考平台_牛客网 代码区&#xff1a; #include<algorithm> #include<iostream> #include<vector>using namespace std; struct TREE{int left,right; }; bool compare(const TREE&a,const TREE& b ){if(a.left!b.left){return…

Windows Server 2025 安装AMD显卡驱动

运行显卡驱动安装程序&#xff0c;会提示出问题。但是此时资源已经解压 来到驱动路径 C:\AMD\AMD-Software-Installer\Packages\Drivers\Display\WT6A_INF 打开配置文件&#xff0c;把这两行替换掉 %ATI% ATI.Mfg, NTamd64.10.0...16299, NTamd64.10.0, NTamd64.6.0, NTamd64.…

为什么 MySQL 用 B+ 树作为数据的索引,以及在 InnoDB 中数据库如何通过 B+ 树索引来存储数据以及查找数据

http://www.liuzk.com/410.html 索引是一种数据结构&#xff0c;用于帮助我们在大量数据中快速定位到我们想要查找的数据。 索引最形象的比喻就是图书的目录了。注意这里的大量&#xff0c;数据量大了索引才显得有意义&#xff0c;如果我想要在 [1,2,3,4] 中找到 4 这个数据&am…

AWS VPC架构师指南:从零设计企业级云网络隔离方案

一、VPC核心概念解析 1.1 核心组件 VPC&#xff1a;逻辑隔离的虚拟网络&#xff0c;可自定义IPv4/IPv6地址范围&#xff08;CIDR块&#xff09; 子网&#xff08;Subnet&#xff09;&#xff1a; 公有子网&#xff1a;绑定Internet Gateway&#xff08;IGW&#xff09;&#…

HuggingFace与自然语言处理(从框架学习到经典项目实践)[ 01 API操作 ]

本教程适用与第一次接触huggingface与相应框架和对nlp任务感兴趣的朋友&#xff0c;该栏目目前更新总结如下&#xff1a; ​​Tokenizer​​&#xff1a; 支持单句/双句编码&#xff0c;自动处理特殊符号和填充。 批量编码提升效率&#xff0c;适合训练数据预处理。Datasets​…

【LeetCode 42】接雨水(单调栈、DP、双指针)

题面&#xff1a; 思路&#xff1a; 能接雨水的点&#xff0c;必然是比两边都低&#xff08;小&#xff09;的点。有两种思路&#xff0c;一种是直接计算每个点的最大贡献&#xff08;也就是每个点在纵向上最多能接多少水&#xff09;&#xff0c;另一种就是计算每个点在横向上…

【嵌入式开发-USB】

嵌入式开发-USB ■ USB简介 ■ USB简介

Visual Studio 项目转Qt项目

1. 先确保qmake 和 minGW &#xff08;g&#xff09; 路径都在系统变量内&#xff1b;或者通过WinR -> cmd 来检测&#xff0c; 如果能够 显示qmake 的信息 &#xff0c; g 的信息 &#xff0c; 就说明设置环境变量成功。 2. 打开项目文件夹&#xff0c;在这里打开cmd, 换…

总线通信篇:I2C、SPI、CAN 的底层结构与多机通信设计

本文为嵌入式通信协议系列第三章,深入剖析 MCU 世界中的三大总线协议 —— I2C、SPI 和 CAN。 这些总线协议广泛应用于传感器数据采集、Flash 存储、外设扩展、汽车电子、工业设备控制等领域,是嵌入式开发不可或缺的通信骨架。 📜 一、总线通信的基本概念 1.1 什么是总线?…

sherpa:介绍

更多内容&#xff1a;XiaoJ的知识星球 目录 1. sherpa 介绍 1. sherpa 介绍 sherpa是 Next-gen Kaldi 项目的部署框架。 sherpa 支持在各种平台上部署与语音相关的预训练模型&#xff0c;并提供多种语言绑定。 目前&#xff0c;sherpa 拥有以下子项目&#xff1a; k2-fsa/sh…

77.组合问题

主函数 combine def combine(self, n: int, k: int) -> List[List[int]]:result [] # 存放所有有效的组合self.backtracking(n, k, 1, [], result) # 从数字1开始搜索return result 作用&#xff1a;初始化并启动回溯过程。参数&#xff1a; n4&#xff1a;数字范围是1…