Vue在线编辑图片
- 一、目的
- 二、样式
- 1、初始上传页面(编辑前)
- 2、在线编辑页面
- 3、初始上传页面(编辑后)
- 三、上代码
- 1、安装依赖
- 2、使用代码
- 2.1、接近原版的代码
- 2.2、改版的代码
不想看的直接跳去第三步的2.2,点击2.2、改版的代码哈,代码基本上都注释了(就在改版的里面进行注释的,都是一行一行敲得,老可怜了)
一、目的
突然来个问题,就要让我在线编辑图片,并且还得上传,我直接干一天就得敲一天。
二、样式
1、初始上传页面(编辑前)
虽然弄得不好,但好在实现功能了
2、在线编辑页面
这是我改版之后的,也可以根据自己需要进行修改哈
下面上原版(我直接关闭美颜和滤镜,当然还得留件衣服,毕竟得见人)
3、初始上传页面(编辑后)
然后就是修改后的图片
三、上代码
1、安装依赖
具体怎么弄的忘了哈,可能也和本身的项目有关,就安装了这仨依赖,tui-image-editor安装不上加入不到
package.json
文件,加入了–save命令就下载成功了
npm install tui-color-picker
npm install --save tui-image-editor
npm install vue-quill-editor
2、使用代码
2.1、接近原版的代码
代码有点多哈,先发一下原版穿衣的
<template>
<div class="box">
<div class="drawing-container">
<div id="tui-image-editor"></div>
</div>
</div>
</template>
<script>
import storage from "@/utils/storage";
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
import ImageEditor from "tui-image-editor";
export default {
name: 'copper',
data() {
return {
myHeaders:{},
instance: null,
}
},
mounted() {
this.init();
this.myHeaders= {
'Token':storage.get("Token")
}
},
methods: {
init(file) {
this.instance = new ImageEditor(
document.querySelector("#tui-image-editor"),
{
includeUI: {
loadImage: {
// path: require("@/assets/这里可以自定义照片,我给改成带入的了"),
path: file,
name: "image",
},
initMenu: "draw", // 默认打开的菜单项
menuBarPosition: "bottom", // 菜单所在的位置
},
cssMaxWidth: 1000, // canvas 最大宽度
cssMaxHeight: 600, // canvas 最大高度
}
);
document.getElementsByClassName("tui-image-editor-main")[0].style.top = "45px"; // 图片距顶部工具栏的距离
},
}
}
</script>
<style scoped>
.box {
width: 100%;
height: 100%;
}
.drawing-container {
height: 900px;
position: relative;
}
</style>
2.2、改版的代码
说是改版也就加了几个参数几个按钮
在return
下面加入了locale_zh
和customTheme
一个汉化的,反正我是不懂英文,
另一个是修改了样式,不然黢黑,我一般都用白色的,
想用黑的也好办,直接把common.backgroundColor
这一行给他隐藏就OK了
只于加入的方法就保存返回了,解释也有
在代码中搜索以上的东西建议使用ctrl+F
(一般都可以用,当然排除不一般)
然后下面是改版的
<template>
<div class="box">
<div class="drawing-container">
<div id="tui-image-editor"></div>
<el-button class="back" type="primary" size="small" @click="back">返回</el-button>
<el-button class="save" type="primary" size="small" @click="save">保存</el-button>
</div>
</div>
</template>
<script>
import storage from "@/utils/storage";
import "tui-image-editor/dist/tui-image-editor.css";
import "tui-color-picker/dist/tui-color-picker.css";
import ImageEditor from "tui-image-editor";
export default {
name: 'copper',
data() {
return {
myHeaders:{},
instance: null,
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": "锁定宽高比例",
},
customTheme : {
"common.bi.image": "", // 左上角logo图片
"common.bisize.width": "0px",
"common.bisize.height": "0px",
"common.backgroundImage": "none",
"common.backgroundColor": "#f3f4f6",
"common.border": "1px solid #333",
// header
"header.backgroundImage": "none",
"header.backgroundColor": "#f3f4f6",
"header.border": "0px",
// load button
"loadButton.backgroundColor": "#fff",
"loadButton.border": "1px solid #ddd",
"loadButton.color": "#222",
"loadButton.fontFamily": "NotoSans, sans-serif",
"loadButton.fontSize": "12px",
"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": "#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",
},
}
},
props: ["parent2"],
mounted() {
this.init();
this.myHeaders= {
'Token':storage.get("Token")
}
},
methods: {
init(file) {
this.instance = new ImageEditor(
document.querySelector("#tui-image-editor"),
{
includeUI: {
loadImage: {
// path: require("@/assets/这里可以自定义照片,我给改成带入的了"),
path: file,
name: "image",
},
menu: ["resize", "crop", "flip", "rotate", "draw", "shape", "icon", "text", "mask", "filter"], // 底部菜单按钮列表 想隐藏什么按顺序去除就行
initMenu: "draw", // 默认打开的菜单项
menuBarPosition: "bottom", // 菜单所在的位置
locale: this.locale_zh, // 本地化语言为中文
theme: this.customTheme, // 自定义样式
},
cssMaxWidth: 1000, // canvas 最大宽度
cssMaxHeight: 600, // canvas 最大高度
}
);
document.getElementsByClassName("tui-image-editor-main")[0].style.top = "45px"; // 图片距顶部工具栏的距离
// document.getElementsByClassName("tie-btn-reset tui-image-editor-item help") [0].style.display = "none"; // 隐藏顶部重置按钮
},
//返回
back(){
this.parent2.showFlag1 = true;
this.parent2.copperCrossAddOrUpdateFlag = false;
this.parent2.addEditStyleChange()
},
// 保存图片,并上传
save() {
//下面进行获取图片,然后进行转换到后台可以上传的格式
const base64String = this.instance.toDataURL(); // base64 文件
const data = window.atob(base64String.split(",")[1]);
const ia = new Uint8Array(data.length);
for (let i = 0; i < data.length; i++) {
ia[i] = data.charCodeAt(i);
}
const blob = new Blob([ia], { type: "image/png" }); // blob 文件
//下面懒得弄组件直接用当前时间弄得文件名,如果后台写了这里可以随便,也可以使用uuid进行生成
const file = new File([blob], new Date().getTime()+'.png', { type: blob.type });
const form = new FormData();
//后端使用@RequestParam("file") MultipartFile file接受,这里变换一下格式
form.append("file", file);
// 上传文件操作
const url = this.$base.url + "file/upload"
this.$http({
url: url,
method: "POST",
data: form,
header: this.myHeaders
}).then(({data}) => {
if (data && data.code === 0) {
//我这里返回的是图片地址
var url = data.url;
//点击进入的代码我在下一部分贴出来
//保存完要返回,这里是一些返回操作,这里是从孙组件返回子组件,可以百度一下
//让上级组件显示
this.parent2.showFlag1 = true;
//让自己隐藏
this.parent2.copperCrossAddOrUpdateFlag = false;
//这个是恢复上级组件按钮的方法,框架有毛病,这个不重要
this.parent2.addEditStyleChange()
//这里是组件传值里面的带参返回
this.$emit('fileUrl', url);
} else {
this.$message.error(data.msg);
}
})
},
}
}
</script>
<style scoped>
.box {
width: 100%;
height: 100%;
}
.drawing-container {
height: 900px;
position: relative;
.save {
position: absolute;
right: 50px;
top: 15px;
}
.back {
position: absolute;
right: 120px;
top: 15px;
}
}
</style>
子组件怎么到的父组件
<copper-cross-add-or-update v-if="copperCrossAddOrUpdateFlag" @fileUrl="getFileUrl" :parent2="this" ref="copperCrossaddOrUpdate"></copper-cross-add-or-update>
点击在线编辑调用下面的方法
// 编辑
openOnlineEditor(file) {
//让当前页面隐藏
this.showFlag1 = false;
//让组件页面显示
this.copperCrossAddOrUpdateFlag = true;
//这个是调用组件的方法进行赋值文件,就是我说在自定义照片那一块
this.$nextTick(() => {
this.$refs.copperCrossaddOrUpdate.init(file);
});
},
然后组件保存带参返回
getFileUrl(data){
//给那个在线编辑的图片框赋值
this.ruleForm.zuoyepigai = data
//修改一下状态,让在线编辑消失
this.zuoyepigaiStatus = false
},
应该就这些了,可能弄得有点多,看懵的可以看看解释,看不清楚可以发一下信息