项目功能需求:对echarts导出的图片进行编辑后下载
效果:
一:安装tui-image-editor
npm i tui-image-editor
二:相关代码
1:组件封装
<template>
<div class="modal fade show p-4" style="display: block">
<div
class="modal-dialog modal-dialog-centered m-0 h-100"
style="max-width: 100%"
>
<div class="modal-content h-100">
<div class="modal-header bg-white p-3">
<input
type="text"
class="form-control"
v-model="imageName"
style="width: 16rem"
placeholder="在此输入数据快照名称 "
:class="{ 'is-invalid': isDownload && v$.imageName.$error }"
/>
<div
v-if="isDownload && v$.imageName.$error"
class="invalid-feedback"
>
<span v-if="v$.imageName.maxLength.$message">{{
v$.imageName.maxLength.$message
}}</span>
</div>
</div>
<div class="model-body h-100">
<div class="drawing-container h-100">
<div id="tui-image-editor"></div>
</div>
</div>
<div class="modal-footer">
<div class="hstack gap-2 justify-content-end">
<button type="button" class="btn btn-light" @click="handleClose">
取消
</button>
<button
type="button"
class="btn btn-primary"
id="add-btn"
@click="handleCanvas2Img"
>
下载
</button>
</div>
</div>
</div>
</div>
</div>
<div class="modal-backdrop fade show"></div>
</template>
<script>
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
import ImageEditor from "tui-image-editor";
import { maxLength, helpers } from "@vuelidate/validators";
import useVuelidate from "@vuelidate/core";
import moment from "moment";
import 'moment-timezone';
export default {
emits: ["update:isShowImageEditor"],
props: {
imageUrl: String,
},
setup() {
return { v$: useVuelidate() //校验图片名称 };
},
validations: {
imageName: {
maxLength: helpers.withMessage("名称的长度不能超过20", maxLength(20)),
},
},
data() {
return {
isDownload: false,
instance: null,
imageName: null,
};
},
mounted() {
this.init();
},
methods: {
init() {
const locale_zh = {
ZoomIn: "放大",
ZoomOut: "缩小",
Hand: "手掌",
History: "历史",
Resize: "调整宽高",
Crop: "裁剪",
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: "混合色",
Width: "宽度",
Height: "高度",
"Lock Aspect Ratio": "锁定宽高比例",
};
const customTheme = {
"common.bi.image": "", // 左上角logo图片
"common.bisize.width": "0px",
"common.bisize.height": "0px",
"common.backgroundImage": "none",
"common.backgroundColor": "#f6f6f6",
// "common.border": "1px solid #333",
// header
"header.backgroundImage": "none",
"header.backgroundColor": "#f3f4f6",
"header.border": "0px",
"header.display": "none",
// load button
"loadButton.display": "none",
// download button
"downloadButton.display": "none",
// icons default
"menu.backgroundColor": "#ffffff",
"menu.normalIcon.color": "rgba(33, 37, 41, 0.6)",
"menu.activeIcon.color": "rgba(102, 145, 231, 1)",
"menu.disabledIcon.color": "#ccc",
"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",
};
this.instance = new ImageEditor(
document.querySelector("#tui-image-editor"),
{
includeUI: {
loadImage: {
path: this.imageUrl,
name: "image",
},
menu: [
"resize",
//'crop', // 裁切
"draw", // 添加绘画
// 'rotate', // 旋转
// 'flip', // 翻转
"shape", // 添加形状
"text", // 添加文本
// 'icon', // 添加图标
// 'mask', // 添加覆盖
// 'filter' // 添加滤镜
],
menuBarPosition: "left", // 菜单所在的位置
locale: locale_zh, // 本地化语言为中文
theme: customTheme, // 自定义样式
},
cssMaxWidth: 4000, // canvas 最大宽度
cssMaxHeight: 4000, // canvas 最大高度
}
);
document.getElementsByClassName("tui-image-editor-main")[0].style.top = 0;
document.getElementsByClassName(
"tui-image-editor-controls"
)[0].style.backgroundColor = "#fff";
/* 对一些不需要的按钮进行样式隐藏*/
document.querySelector('[tooltip-content="反撤销"]').style.display =
"none"; // 上一步
document.querySelector('[tooltip-content="放大"]').style.display = "none"; // 放大
document.querySelector('[tooltip-content="缩小"]').style.display = "none"; // 缩小
document.querySelector('[tooltip-content="手掌"]').style.display = "none"; // 拖动界面
document.querySelector('[tooltip-content="重置"]').style.display = "none"; // 拖动界面
document.querySelector('[tooltip-content="历史"]').style.display = "none";
document.querySelector(
".tui-image-editor-container .tui-image-editor-help-menu.right"
).style.height = "140px";
document.querySelector(
".tui-image-editor-container .tui-image-editor-help-menu.right"
).style.backgroundColor = "#fff";
// 隐藏分割线
document
.querySelectorAll(".tui-image-editor-icpartition")
.forEach((item) => {
item.parentNode.style.display = "none";
});
},
/** 保存编辑后图片 */
handleCanvas2Img() {
this.isDownload = true;
this.v$.$touch();
if (this.v$.$invalid) return;
// 调用组件官方方法,获取整个编辑后图片的base64数据
const el = document.createElement("a");
el.href = this.instance.toDataURL();
el.download = el.download = this.imageName || "数据快照" + moment().tz(this.$tz).format("YYYYMMDD");
const event = new MouseEvent("click");
el.dispatchEvent(event);
},
/** 取消按钮关闭弹窗 */
handleClose() {
this.$emit("update:isShowImageEditor", false);
},
},
};
</script>
2:组件引用
<ImageEditor
v-model:isShowImageEditor="isShowImageEditor"
v-if="isShowImageEditor"
:imageUrl="imageUrl"
></ImageEditor>
import ImageEditor from "@/components/image-editor"; //引入
//点击编辑图片
handleImageEditor() {
const myChart = echarts.getInstanceByDom(
document.getElementById("monitor")
);
if (myChart) {
this.imageUrl = myChart.getConnectedDataURL({
pixelRatio: 1,
backgroundColor: "#fff",
type: "png",
});//echarts导出的图片
if (this.imageUrl) {
this.isShowImageEditor = true;
}
}
},