使用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>