当前位置:   article > 正文

Vue中使用图片编辑器 tui-image-editor 实现在线编辑保存

Vue中使用图片编辑器 tui-image-editor 实现在线编辑保存

不想看的直接跳去第三步的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
  • 1
  • 2
  • 3

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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

2.2、改版的代码

说是改版也就加了几个参数几个按钮
return下面加入了locale_zhcustomTheme
一个汉化的,反正我是不懂英文,
另一个是修改了样式,不然黢黑,我一般都用白色的,
想用黑的也好办,直接把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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279

子组件怎么到的父组件

<copper-cross-add-or-update v-if="copperCrossAddOrUpdateFlag" @fileUrl="getFileUrl" :parent2="this" ref="copperCrossaddOrUpdate"></copper-cross-add-or-update>
  • 1

点击在线编辑调用下面的方法

// 编辑
openOnlineEditor(file) {      
      //让当前页面隐藏
      this.showFlag1 = false;
      //让组件页面显示
      this.copperCrossAddOrUpdateFlag = true;
      //这个是调用组件的方法进行赋值文件,就是我说在自定义照片那一块
      this.$nextTick(() => {
          this.$refs.copperCrossaddOrUpdate.init(file);
      });
  },
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

然后组件保存带参返回

getFileUrl(data){
	//给那个在线编辑的图片框赋值
    this.ruleForm.zuoyepigai = data
    //修改一下状态,让在线编辑消失
    this.zuoyepigaiStatus = false
},
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

应该就这些了,可能弄得有点多,看懵的可以看看解释,看不清楚可以发一下信息
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/585562
推荐阅读
相关标签
  

闽ICP备14008679号