文章目录
一、前言
在实际业务中,经常会有用户截图保存页面内容的需求,比如:
- 表单填写后的结果截图
- 页面中某个模块的操作记录截图
- 可视化大屏、报表区域导出为图片
而我们可以通过 html2canvas
实现将 DOM 节点截图为图片。本篇文章将基于 Vue 3 + html2canvas 封装一个「可指定区域截图」的组件,支持:
- ✅ 任意 DOM 区域截图
- 🎯 鼠标框选截图区域
- 🖼️ 图片预览与下载
- 🧩 可插入业务模块作为截图内容
二、技术栈与原理简析
- Vue 3 +
<script setup>
:组合式 API 更方便封装功能 - html2canvas:将 HTML 节点渲染为 Canvas,再导出为图片
- DOM 操作 + 鼠标事件监听:实现可视化选区
原理核心就是:将目标 DOM 渲染为 canvas,然后将 canvas 导出为 base64 或 Blob 图片。
三、项目准备
3.1 安装依赖
npm install html2canvas
3.2 页面基础布局
我们需要一个区域放置截图目标 + 控制按钮:
<template>
<div class="screenshot-wrapper">
<div class="toolbar">
<button @click="captureFull">📷 截图整个区域</button>
<button @click="toggleCropMode">✂️ 框选截图</button>
</div>
<!-- 可截图区域 -->
<div class="capture-target" ref="captureRef">
<slot />
</div>
<!-- 框选截图遮罩 -->
<div v-if="cropMode" class="crop-mask" @mousedown="startCrop" />
</div>
</template>
四、截图功能实现
4.1 整个区域截图
import html2canvas from 'html2canvas';
const captureRef = ref(null);
function captureFull() {
html2canvas(captureRef.value).then(canvas => {
const img = canvas.toDataURL('image/png');
downloadImage(img);
});
}
function downloadImage(dataUrl) {
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'screenshot.png';
a.click();
}
五、框选截图功能
5.1 实现裁剪区域选择
const cropMode = ref(false);
const cropBox = reactive({ x: 0, y: 0, w: 0, h: 0 });
let startX = 0, startY = 0;
function toggleCropMode() {
cropMode.value = !cropMode.value;
}
function startCrop(e) {
const mask = e.currentTarget;
startX = e.offsetX;
startY = e.offsetY;
const moveHandler = (moveEvent) => {
cropBox.x = Math.min(startX, moveEvent.offsetX);
cropBox.y = Math.min(startY, moveEvent.offsetY);
cropBox.w = Math.abs(startX - moveEvent.offsetX);
cropBox.h = Math.abs(startY - moveEvent.offsetY);
drawCropBox(mask);
};
const upHandler = () => {
document.removeEventListener('mousemove', moveHandler);
document.removeEventListener('mouseup', upHandler);
captureByCropBox();
cropMode.value = false;
};
document.addEventListener('mousemove', moveHandler);
document.addEventListener('mouseup', upHandler);
}
5.2 根据选区截图
function captureByCropBox() {
html2canvas(captureRef.value).then(canvas => {
const croppedCanvas = document.createElement('canvas');
const ctx = croppedCanvas.getContext('2d');
croppedCanvas.width = cropBox.w;
croppedCanvas.height = cropBox.h;
ctx.drawImage(
canvas,
cropBox.x, cropBox.y, cropBox.w, cropBox.h,
0, 0, cropBox.w, cropBox.h
);
const croppedImg = croppedCanvas.toDataURL('image/png');
downloadImage(croppedImg);
});
}
5.3 选区样式绘制
function drawCropBox(maskEl) {
let box = maskEl.querySelector('.crop-box');
if (!box) {
box = document.createElement('div');
box.className = 'crop-box';
maskEl.appendChild(box);
}
box.style.left = `${cropBox.x}px`;
box.style.top = `${cropBox.y}px`;
box.style.width = `${cropBox.w}px`;
box.style.height = `${cropBox.h}px`;
}
六、样式美化
<style scoped>
.screenshot-wrapper {
position: relative;
}
.toolbar {
margin-bottom: 10px;
}
.capture-target {
border: 1px solid #ccc;
padding: 10px;
background: #fff;
position: relative;
}
.crop-mask {
position: absolute;
top: 0; left: 0;
width: 100%;
height: 100%;
cursor: crosshair;
background-color: rgba(0,0,0,0.05);
}
.crop-box {
position: absolute;
border: 2px dashed #409EFF;
background-color: rgba(64, 158, 255, 0.2);
pointer-events: none;
}
</style>
七、使用示例
<template>
<Screenshot>
<div class="content">
<h2>这是可截图区域</h2>
<p>这里的内容将被截图,包括文字、图表等</p>
<img src="https://via.placeholder.com/300x150" />
</div>
</Screenshot>
</template>
<script setup>
import Screenshot from './components/Screenshot.vue';
</script>
到这里,这篇文章就和大家说再见啦!我的主页里还藏着很多 篇 前端 实战干货,感兴趣的话可以点击头像看看,说不定能找到你需要的解决方案~
创作这篇内容花了很多的功夫。如果它帮你解决了问题,或者带来了启发,欢迎:
点个赞❤️ 让更多人看到优质内容
关注「前端极客探险家」🚀 每周解锁新技巧
收藏文章⭐️ 方便随时查阅
📢 特别提醒:
转载请注明原文链接,商业合作请私信联系
感谢你的阅读!我们下篇文章再见~ 💕