Vue实现对图片的涂鸦等操作
安装插件tui-image-editor引入组件import "tui-image-editor/dist/tui-image-editor.css";import "tui-color-picker/dist/tui-color-picker.css";const ImageEditor = require("tui-image-editor");
·
新的项目中要求在聊天消息中可以对发送的图片进行标注,经过分析发现可以使用tui-image-editor
插件可以实现,在此记录一下使用的方式和过程,下次在遇到类似的需求可以直接参考使用.
安装插件
npm i tui-image-editor --save
引入组件
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
const ImageEditor = require("tui-image-editor");
使用
<template>
<div class="image-previewer-wrapper" v-show="showPreviewer">
<div class="image-wrapper">
<div id="tui-image-editor" class="image-preview"></div>
</div>
<i class="el-icon-check check-button" @click="saveImg"> </i>
<i class="el-icon-close close-button" @click="close" />
<i class="el-icon-back prev-button" @click="goPrev"></i>
<i class="el-icon-right next-button" @click="goNext"></i>
<div class="actions-bar">
<span class="image-counter"
>{{ index + 1 }} / {{ imgUrlList.length }}</span
>
</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import * as moment from "moment";
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
const ImageEditor = require("tui-image-editor");
const {
operatorImageLocaleZh,
operatorImageTheme,
} = require("../../assets/json/i18n.json");
export default {
name: "ImagePreviewer",
data() {
return {
url: "",
index: 0,
visible: false,
zoom: 1,
rotate: 0,
minZoom: 0.1,
urlFlag: false,
useDefaultUI: true,
imageInfoData: null,
};
},
computed: {
...mapGetters(["imgUrlList"]),
showPreviewer() {
return this.url.length > 0 && this.visible;
},
imageStyle() {
return {
transform: `scale(${this.zoom});`,
};
},
previewUrl() {
if (this.urlFlag) {
return this.url;
} else {
return this.formatUrl(this.imgUrlList[this.index]);
}
},
},
mounted() {
this.$bus.$on("image-preview", this.handlePreview);
},
methods: {
// 对图片操作之后保存到本地
saveImg() {
let a = document.createElement("a");
a.href = this.imageInfoData.toDataURL();
a.setAttribute(
"download",
moment(new Date()).format("YYYY-MM-DD hh:mm:ss")
);
a.click();
},
// 聊天记录中点击图片,图片放大并显示出可操作图片菜单
handlePreview({ url, flag = undefined }) {
this.url = url;
this.urlFlag = flag ? "merger" : false;
this.index = this.imgUrlList.findIndex((item) => item === url);
this.visible = true;
const self = this;
this.customDrawImg(url);
},
// 处理图片涂鸦部门
customDrawImg(url) {
this.imageInfoData = new ImageEditor(
document.querySelector("#tui-image-editor"),
{
includeUI: {
loadImage: {
// 图片地址
path: url,
// 图片名字
name: moment(new Date()).format("YYYY-MM-DD hh:mm:ss"),
},
// 默认菜单选项
initMenu: "shape",
//菜单栏
menu: [
"crop",
"flip",
"rotate",
"draw",
"shape",
"icon",
"text",
"mask",
"filter",
],
// 汉化
locale: operatorImageLocaleZh,
// 操作图片时各种样式
theme: operatorImageTheme,
usageStatistics: true,
// 菜单位置
menuBarPosition: "bottom",
},
cssMaxWidth: document.documentElement.clientWidth,
cssMaxHeight: document.documentElement.clientHeight,
// 操作时线的大小和颜色
selectionStyle: {
cornerSize: 20,
rotatingPointOffset: 70,
borderColor: "red",
cornerColor: "red",
cornerSize: 5,
rotatingPointOffset: 0,
},
}
);
},
// 关闭
close() {
Object.assign(this, { zoom: 1 });
this.visible = false;
},
// 对下一张图片进行操作
goNext() {
this.index = (this.index + 1) % this.imgUrlList.length;
this.customDrawImg(this.imgUrlList[this.index]);
},
// 对上一张图片进行操作
goPrev() {
this.index =
this.index - 1 >= 0 ? this.index - 1 : this.imgUrlList.length - 1;
this.customDrawImg(this.imgUrlList[this.index]);
},
// url格式化
formatUrl(url) {
if (!url) {
return "";
}
return url.slice(0, 2) === "//" ? `https:${url}` : url;
},
},
};
</script>
<style scoped>
.image-previewer-wrapper {
position: fixed;
width: 100%;
left: 0;
top: 0;
height: 100%;
display: flex;
justify-content: center;
align-items: flex-start;
background: rgba(14, 12, 12, 0.7);
z-index: 2000;
cursor: zoom-out;
}
.close-button,
.check-button {
cursor: pointer;
font-size: 28px;
color: #000;
position: fixed;
top: 50px;
right: 50px;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
padding: 6px;
}
.check-button {
cursor: pointer;
color: #000;
position: fixed;
top: 50px;
right: 120px;
}
.image-wrapper {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.image-preview {
transition: transform 0.1s ease 0s;
}
.actions-bar {
display: flex;
justify-content: space-around;
align-items: center;
position: fixed;
top: 50px;
left: 50%;
margin-left: -14px;
}
.actions-bar i {
font-size: 24px;
cursor: pointer;
margin: 0 6px;
}
.prev-button,
.next-button {
position: fixed;
cursor: pointer;
background: rgba(255, 255, 255, 0.8);
border-radius: 50%;
font-size: 24px;
padding: 12px;
}
.prev-button {
left: 0;
top: 50%;
margin-left: 20px;
}
.next-button {
right: 0;
margin-right: 20px;
top: 50%;
}
.image-counter {
background: rgba(20, 18, 20, 0.53);
padding: 3px;
border-radius: 3px;
color: #fff;
}
</style>
汉化和主题配置
{
"operatorImageLocaleZh": {
"Crop": "裁剪",
"ZoomIn": "放大",
"ZoomOut": "缩小",
"Hand": "拖拽",
"History": "历史记录",
"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": "混合色",
"Load": "记录列表"
},
"operatorImageTheme": {
"header.display": "none",
"loadButton.display": "none",
"downloadButton.display": "none",
"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.backgroundColor": "#1e1e1e",
"submenu.partition.color": "#858585",
"submenu.normalLabel.color": "#858585",
"submenu.normalLabel.fontWeight": "lighter",
"submenu.activeLabel.color": "#fff",
"submenu.activeLabel.fontWeight": "lighter",
"checkbox.border": "1px solid #ccc",
"checkbox.backgroundColor": "#fff",
"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.button.border": "1px solid #1e1e1e",
"colorpicker.title.color": "#fff"
}
}
更多推荐
已为社区贡献2条内容
所有评论(0)