基于浏览器的截图且可编辑组件
使用到 tui-image-editor 和 html2canvas
安装方法
npm install --save tui-image-editor
npm i --save html2canvas
配上官网链接
tui-image-editor: nhn.github.io/tui.image-e…
html2canvas: html2canvas.hertzen.com/
tui-image-editor用于截图之后的编辑操作,有裁切、翻转、旋转、绘画、形状、文本、图标、覆盖、滤镜
html2canvas用于web浏览器截图
实践
使用vue3 + vite + element-plus,安装过程略过。。。 完整代码在文末
页面部分 使用element-plus的弹窗,截图之后弹窗内编辑图片
<template>
<div>
<slot :screenshot="clickGeneratePicture">
<el-button class="screenshotBtn button" @click="clickGeneratePicture">
一键截图
</el-button>
</slot>
<el-dialog
draggable
v-model="dialogVisible"
title="截图"
:width="width"
:before-close="handleClose"
@opened="opened"
:append-to-body="true"
align-center
>
<!-- 用于存放截图 -->
<div ref="editor"></div>
<template #footer>
<div class="dialog-footer">
<el-button @click="save">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
css部分
.tui-image-editor-container {
width: 1500px;
height: 800px !important;
}
导入所需的包
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
import html2canvas from "html2canvas";
import ImageEditor from "tui-image-editor";
截图方法,使用 html2canvas
const clickGeneratePicture = () => {
html2canvas(props.imageWrapper, {
logging: false,
allowTaint: true,
scale: window.devicePixelRatio,
// width: shareContent.clientWidth,
// height: shareContent.clientHeight,
scrollY: 0,
scrollX: 0,
useCORS: true,
backgroundColor: null,
}).then(async function (canvas) {
imgUrl.value = canvas.toDataURL("image/png");
dialogVisible.value = true;
});
};
修改 tui-image-editor 英文转中文
// 转中文
const locale_zh = {
// override default English locale to your custom
Crop: "裁剪",
Load: "替换图片",
DeleteAll: "全部删除",
Delete: "删除",
Undo: "撤销",
Redo: "反撤销",
Reset: "重置",
Flip: "镜像",
Rotate: "旋转",
Draw: "画",
Shape: "形状标注",
Icon: "图标标注",
Text: "文字标注",
Mask: "遮罩",
Filter: "滤镜",
Bold: "加粗",
Italic: "斜体",
Underline: "下划线",
Left: "左对齐",
Center: "居中",
Right: "右对齐",
Color: "颜色",
"Text size": "字体大小",
Custom: "自定义",
Square: "正方形",
Apply: "应用",
Cancel: "取消",
"Flip X": "X 轴",
"Flip Y": "Y 轴",
Range: "区间",
Stroke: "描边",
Fill: "填充",
Circle: "圆",
Triangle: "三角",
Rectangle: "矩形",
Free: "曲线",
Straight: "直线",
Arrow: "箭头",
"Arrow-2": "箭头2",
"Arrow-3": "箭头3",
"Star-1": "星星1",
"Star-2": "星星2",
Polygon: "多边形",
Location: "定位",
Heart: "心形",
Bubble: "气泡",
"Custom icon": "自定义图标",
"Load Mask Image": "加载蒙层图片",
Grayscale: "灰度",
Blur: "模糊",
Sharpen: "锐化",
Emboss: "浮雕",
"Remove White": "除去白色",
Distance: "距离",
Brightness: "亮度",
Noise: "噪音",
"Color Filter": "彩色滤镜",
Sepia: "棕色",
Sepia2: "棕色2",
Invert: "负片",
Pixelate: "像素化",
Threshold: "阈值",
Tint: "色调",
Multiply: "正片叠底",
Blend: "混合色",
Double: "双击",
Download: "预览图片",
// etc...
};
自定义tui-image-editor样式
const customTheme = {
// image 坐上角度图片
"common.bi.image": "", // 在这里换上你喜欢的logo图片
"common.bisize.width": "0px",
"common.bisize.height": "0px",
"common.backgroundImage": "none",
"common.backgroundColor": "#f3f4f6",
"common.border": "1px solid #444",
// header
"header.backgroundImage": "none",
"header.backgroundColor": "#f3f4f6",
"header.border": "0px",
"header.margin": "0px auto",
// load button
"loadButton.backgroundColor": "#fff",
"loadButton.border": "1px solid #ddd",
"loadButton.color": "#222",
"loadButton.fontFamily": "NotoSans, sans-serif",
"loadButton.fontSize": "12px",
"loadButton.width": "150px",
"loadButton.display": "none", // 可以直接隐藏掉
// download button
"downloadButton.backgroundColor": "#fdba3b",
"downloadButton.border": "1px solid #fdba3b",
"downloadButton.color": "#fff",
"downloadButton.fontFamily": "NotoSans, sans-serif",
"downloadButton.fontSize": "12px",
// "downloadButton.display": "none", // 可以直接隐藏掉
// icons default
"menu.normalIcon.color": "#8a8a8a",
"menu.activeIcon.color": "#555555",
"menu.disabledIcon.color": "#434343",
"menu.hoverIcon.color": "#e9e9e9",
"submenu.normalIcon.color": "#8a8a8a",
"submenu.activeIcon.color": "#e9e9e9",
"menu.iconSize.width": "24px",
"menu.iconSize.height": "24px",
"submenu.iconSize.width": "32px",
"submenu.iconSize.height": "32px",
// submenu primary color
"submenu.backgroundColor": "#1e1e1e",
"submenu.partition.color": "#858585",
// submenu labels
"submenu.normalLabel.color": "#858585",
"submenu.normalLabel.fontWeight": "lighter",
"submenu.activeLabel.color": "#fff",
"submenu.activeLabel.fontWeight": "lighter",
// checkbox style
"checkbox.border": "1px solid #ccc",
"checkbox.backgroundColor": "#fff",
// rango style
"range.pointer.color": "#fff",
"range.bar.color": "#666",
"range.subbar.color": "#d1d1d1",
"range.disabledPointer.color": "#414141",
"range.disabledBar.color": "#282828",
"range.disabledSubbar.color": "#414141",
"range.value.color": "#fff",
"range.value.fontWeight": "lighter",
"range.value.fontSize": "11px",
"range.value.border": "1px solid #353535",
"range.value.backgroundColor": "#151515",
"range.title.color": "#fff",
"range.title.fontWeight": "lighter",
// colorpicker style
"colorpicker.button.border": "1px solid #1e1e1e",
"colorpicker.title.color": "#fff",
};
tui-image-editor 实例化
const options = {
usageStatistics: false,
includeUI: {
loadImage: {
path: imgUrl.value,
name: "imgName",
},
//操作菜单栏
menu: [
"crop", // 裁切
"flip", // 翻转
"rotate", // 旋转
"draw", // 添加绘画
"shape", // 添加形状
"text", // 添加文本
"icon", // 图标
// "mask", // 添加覆盖,
// 'filter' // 滤镜
],
menuBarPosition: "top", //操作栏位置
locale: locale_zh, // 中文
theme: customTheme, //主题样式
},
cssMaxWidth: props.imgWidth, // 图片宽度
cssMaxHeight: props.imgHeight, // 图片高度
selectionStyle: {
cornerSize: 20,
rotatingPointOffset: 70,
},
};
// 实例化编辑器
imageEditor.value = new ImageEditor(editor.value, options);
使用 tui-image-editor 回调保存编辑后的图片
const base64 = imageEditor.value.toDataURL();
附上完整代码
<!--
截图组件 用于dom的截图 并提供编辑操作
-->
<template>
<div>
<slot :screenshot="clickGeneratePicture">
<el-button class="screenshotBtn button" @click="clickGeneratePicture">
一键截图
</el-button>
</slot>
<el-dialog
draggable
v-model="dialogVisible"
title="截图"
:width="width"
:before-close="handleClose"
@opened="opened"
:append-to-body="true"
align-center
>
<!-- 用于存放截图 -->
<div ref="editor"></div>
<template #footer>
<div class="dialog-footer">
<el-button @click="save">保存</el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup>
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
import html2canvas from "html2canvas";
import ImageEditor from "tui-image-editor";
import { computed, ref } from "vue";
const props = defineProps({
/**
* 需要截图的dom的ref
*/
imageWrapper: {
required: true,
},
/**
* dialog的宽度
*/
width: {
type: Number,
default: 1500,
required: false,
},
/**
* 截图宽度
*/
imgWidth: {
type: Number,
required: false,
default: 1600,
},
/**
* 截图高度
*/
imgHeight: {
type: Number,
required: false,
default: 700,
},
/**
* 截图宽度
*/
containerWidth: {
type: Number,
required: false,
default: 1500,
},
/**
* 截图高度
*/
containerHeight: {
type: Number,
required: false,
default: 800,
},
});
const emit = defineEmits(["save"]);
const customTheme = {
// image 坐上角度图片
"common.bi.image": "", // 在这里换上你喜欢的logo图片
"common.bisize.width": "0px",
"common.bisize.height": "0px",
"common.backgroundImage": "none",
"common.backgroundColor": "#f3f4f6",
"common.border": "1px solid #444",
// header
"header.backgroundImage": "none",
"header.backgroundColor": "#f3f4f6",
"header.border": "0px",
"header.margin": "0px auto",
// load button
"loadButton.backgroundColor": "#fff",
"loadButton.border": "1px solid #ddd",
"loadButton.color": "#222",
"loadButton.fontFamily": "NotoSans, sans-serif",
"loadButton.fontSize": "12px",
"loadButton.width": "150px",
"loadButton.display": "none", // 可以直接隐藏掉
// download button
"downloadButton.backgroundColor": "#fdba3b",
"downloadButton.border": "1px solid #fdba3b",
"downloadButton.color": "#fff",
"downloadButton.fontFamily": "NotoSans, sans-serif",
"downloadButton.fontSize": "12px",
// "downloadButton.display": "none", // 可以直接隐藏掉
// icons default
"menu.normalIcon.color": "#8a8a8a",
"menu.activeIcon.color": "#555555",
"menu.disabledIcon.color": "#434343",
"menu.hoverIcon.color": "#e9e9e9",
"submenu.normalIcon.color": "#8a8a8a",
"submenu.activeIcon.color": "#e9e9e9",
"menu.iconSize.width": "24px",
"menu.iconSize.height": "24px",
"submenu.iconSize.width": "32px",
"submenu.iconSize.height": "32px",
// submenu primary color
"submenu.backgroundColor": "#1e1e1e",
"submenu.partition.color": "#858585",
// submenu labels
"submenu.normalLabel.color": "#858585",
"submenu.normalLabel.fontWeight": "lighter",
"submenu.activeLabel.color": "#fff",
"submenu.activeLabel.fontWeight": "lighter",
// checkbox style
"checkbox.border": "1px solid #ccc",
"checkbox.backgroundColor": "#fff",
// rango style
"range.pointer.color": "#fff",
"range.bar.color": "#666",
"range.subbar.color": "#d1d1d1",
"range.disabledPointer.color": "#414141",
"range.disabledBar.color": "#282828",
"range.disabledSubbar.color": "#414141",
"range.value.color": "#fff",
"range.value.fontWeight": "lighter",
"range.value.fontSize": "11px",
"range.value.border": "1px solid #353535",
"range.value.backgroundColor": "#151515",
"range.title.color": "#fff",
"range.title.fontWeight": "lighter",
// colorpicker style
"colorpicker.button.border": "1px solid #1e1e1e",
"colorpicker.title.color": "#fff",
};
// 编辑器的实例
let imageEditor = ref();
// 编辑器的容器
const editor = ref();
// 截图的url
let imgUrl = ref("");
// 转中文
const locale_zh = {
// override default English locale to your custom
Crop: "裁剪",
Load: "替换图片",
DeleteAll: "全部删除",
Delete: "删除",
Undo: "撤销",
Redo: "反撤销",
Reset: "重置",
Flip: "镜像",
Rotate: "旋转",
Draw: "画",
Shape: "形状标注",
Icon: "图标标注",
Text: "文字标注",
Mask: "遮罩",
Filter: "滤镜",
Bold: "加粗",
Italic: "斜体",
Underline: "下划线",
Left: "左对齐",
Center: "居中",
Right: "右对齐",
Color: "颜色",
"Text size": "字体大小",
Custom: "自定义",
Square: "正方形",
Apply: "应用",
Cancel: "取消",
"Flip X": "X 轴",
"Flip Y": "Y 轴",
Range: "区间",
Stroke: "描边",
Fill: "填充",
Circle: "圆",
Triangle: "三角",
Rectangle: "矩形",
Free: "曲线",
Straight: "直线",
Arrow: "箭头",
"Arrow-2": "箭头2",
"Arrow-3": "箭头3",
"Star-1": "星星1",
"Star-2": "星星2",
Polygon: "多边形",
Location: "定位",
Heart: "心形",
Bubble: "气泡",
"Custom icon": "自定义图标",
"Load Mask Image": "加载蒙层图片",
Grayscale: "灰度",
Blur: "模糊",
Sharpen: "锐化",
Emboss: "浮雕",
"Remove White": "除去白色",
Distance: "距离",
Brightness: "亮度",
Noise: "噪音",
"Color Filter": "彩色滤镜",
Sepia: "棕色",
Sepia2: "棕色2",
Invert: "负片",
Pixelate: "像素化",
Threshold: "阈值",
Tint: "色调",
Multiply: "正片叠底",
Blend: "混合色",
Double: "双击",
Download: "预览图片",
// etc...
};
// 弹窗显隐
let dialogVisible = ref(false);
/**
* 弹窗关闭
*/
const handleClose = () => {
dialogVisible.value = false;
imageEditor.value.destroy();
};
/**
* 保存图片
* 返回截图编辑之后的图片 base64格式
*/
const save = () => {
const base64 = imageEditor.value.toDataURL();
emit("save", { url: base64 });
};
/**
* 弹窗显示之后的回调
*/
const opened = () => {
const options = {
usageStatistics: false,
includeUI: {
loadImage: {
path: imgUrl.value,
name: "imgName",
},
//操作菜单栏
menu: [
"crop", // 裁切
"flip", // 翻转
"rotate", // 旋转
"draw", // 添加绘画
"shape", // 添加形状
"text", // 添加文本
"icon", // 图标
// "mask", // 添加覆盖,
// 'filter' // 滤镜
],
menuBarPosition: "top", //操作栏位置
locale: locale_zh, // 中文
theme: customTheme, //主题样式
},
cssMaxWidth: props.imgWidth, // 图片宽度
cssMaxHeight: props.imgHeight, // 图片高度
selectionStyle: {
cornerSize: 20,
rotatingPointOffset: 70,
},
};
// 实例化编辑器
imageEditor.value = new ImageEditor(editor.value, options);
};
/**
* 截图
*/
const clickGeneratePicture = () => {
html2canvas(props.imageWrapper, {
logging: false,
allowTaint: true,
scale: window.devicePixelRatio,
// width: shareContent.clientWidth,
// height: shareContent.clientHeight,
scrollY: 0,
scrollX: 0,
useCORS: true,
backgroundColor: null,
}).then(async function (canvas) {
imgUrl.value = canvas.toDataURL("image/png");
dialogVisible.value = true;
});
};
</script>
<style scoped lang="scss">
.tui-image-editor-container {
width: 1500px;
height: 800px !important;
}
</style>
完结~~~