1.上图
2.引入 tui-image-editor
npm i tui-image-editor
3.直接上代码
1 <template> 2 <el-dialog append-to-body :visible.sync="imgVisible" :title="imgName" width="75%"> 3 <div class="container"> 4 <div id="tui-image-editor"></div> 5 </div> 6 <div class="dialog-bottom"> 7 <el-button size="mini" @click="downloadImg">下载</el-button> 8 <el-button size="mini" @click="uploadImg">保存至服务器</el-button> 9 </div> 10 </el-dialog> 11 </template> 12 <script> 13 import { base64ToFile, uploadFileBase64 } from '@/utils/file-util' 14 import { fileLocalDownLoad } from '@/utils' 15 import 'tui-image-editor/dist/tui-image-editor.css' 16 import 'tui-color-picker/dist/tui-color-picker.css' 17 import ImageEditor from 'tui-image-editor' 18 const locale_zh = { 19 ZoomIn: '放大', 20 ZoomOut: '缩小', 21 Hand: '手掌', 22 History: '历史', 23 Resize: '调整宽高', 24 Crop: '裁剪', 25 DeleteAll: '全部删除', 26 Delete: '删除', 27 Undo: '撤销', 28 Redo: '反撤销', 29 Reset: '重置', 30 Flip: '镜像', 31 Rotate: '旋转', 32 Draw: '画', 33 Shape: '形状标注', 34 Icon: '图标标注', 35 Text: '文字标注', 36 Mask: '遮罩', 37 Filter: '滤镜', 38 Bold: '加粗', 39 Italic: '斜体', 40 Underline: '下划线', 41 Left: '左对齐', 42 Center: '居中', 43 Right: '右对齐', 44 Color: '颜色', 45 'Text size': '字体大小', 46 Custom: '自定义', 47 Square: '正方形', 48 Apply: '应用', 49 Cancel: '取消', 50 'Flip X': 'X 轴', 51 'Flip Y': 'Y 轴', 52 Range: '区间', 53 Stroke: '描边', 54 Fill: '填充', 55 Circle: '圆', 56 Triangle: '三角', 57 Rectangle: '矩形', 58 Free: '曲线', 59 Straight: '直线', 60 Arrow: '箭头', 61 'Arrow-2': '箭头2', 62 'Arrow-3': '箭头3', 63 'Star-1': '星星1', 64 'Star-2': '星星2', 65 Polygon: '多边形', 66 Location: '定位', 67 Heart: '心形', 68 Bubble: '气泡', 69 'Custom icon': '自定义图标', 70 'Load Mask Image': '加载蒙层图片', 71 Grayscale: '灰度', 72 Blur: '模糊', 73 Sharpen: '锐化', 74 Emboss: '浮雕', 75 'Remove White': '除去白色', 76 Distance: '距离', 77 Brightness: '亮度', 78 Noise: '噪音', 79 'Color Filter': '彩色滤镜', 80 Sepia: '棕色', 81 Sepia2: '棕色2', 82 Invert: '负片', 83 Pixelate: '像素化', 84 Threshold: '阈值', 85 Tint: '色调', 86 Multiply: '正片叠底', 87 Blend: '混合色', 88 Width: '宽度', 89 Height: '高度', 90 'Lock Aspect Ratio': '锁定宽高比例' 91 92 } 93 94 const customTheme = { 95 "common.bi.image": "", // 在这里换上你喜欢的logo图片 96 "common.bisize.width": "0px", 97 "common.bisize.height": "0px", 98 "common.backgroundImage": "none", 99 "common.backgroundColor": "#f3f4f6", 100 "common.border": "1px solid #444", 101 102 // header 103 "header.backgroundImage": "none", 104 "header.backgroundColor": "#f3f4f6", 105 "header.border": "0px", 106 107 // load button 108 "loadButton.backgroundColor": "#fff", 109 "loadButton.border": "1px solid #ddd", 110 "loadButton.color": "#222", 111 "loadButton.fontFamily": "NotoSans, sans-serif", 112 "loadButton.fontSize": "12px", 113 "loadButton.display": "none", // 可以直接隐藏掉 114 115 // download button 116 "downloadButton.backgroundColor": "#fdba3b", 117 "downloadButton.border": "1px solid #fdba3b", 118 "downloadButton.color": "#fff", 119 "downloadButton.fontFamily": "NotoSans, sans-serif", 120 "downloadButton.fontSize": "12px", 121 "downloadButton.display": "none", // 可以直接隐藏掉 122 123 // icons default 124 "menu.normalIcon.color": "#8a8a8a", 125 "menu.activeIcon.color": "#555555", 126 "menu.disabledIcon.color": "#434343", 127 "menu.hoverIcon.color": "#e9e9e9", 128 "submenu.normalIcon.color": "#8a8a8a", 129 "submenu.activeIcon.color": "#e9e9e9", 130 131 "menu.iconSize.width": "24px", 132 "menu.iconSize.height": "24px", 133 "submenu.iconSize.width": "32px", 134 "submenu.iconSize.height": "32px", 135 136 // submenu primary color 137 "submenu.backgroundColor": "#1e1e1e", 138 "submenu.partition.color": "#858585", 139 140 // submenu labels 141 "submenu.normalLabel.color": "#858585", 142 "submenu.normalLabel.fontWeight": "lighter", 143 "submenu.activeLabel.color": "#fff", 144 "submenu.activeLabel.fontWeight": "lighter", 145 146 // checkbox style 147 "checkbox.border": "1px solid #ccc", 148 "checkbox.backgroundColor": "#fff", 149 150 // rango style 151 "range.pointer.color": "#fff", 152 "range.bar.color": "#666", 153 "range.subbar.color": "#d1d1d1", 154 155 "range.disabledPointer.color": "#414141", 156 "range.disabledBar.color": "#282828", 157 "range.disabledSubbar.color": "#414141", 158 159 "range.value.color": "#fff", 160 "range.value.fontWeight": "lighter", 161 "range.value.fontSize": "11px", 162 "range.value.border": "1px solid #353535", 163 "range.value.backgroundColor": "#151515", 164 "range.title.color": "#fff", 165 "range.title.fontWeight": "lighter", 166 167 // colorpicker style 168 "colorpicker.button.border": "1px solid #1e1e1e", 169 "colorpicker.title.color": "#fff", 170 }; 171 export default { 172 props: { 173 bucketName: { 174 type: String, 175 default: 'bridge', 176 }, 177 }, 178 data () { 179 return { 180 instance: null, 181 imgSrc: '', 182 imgUrl: '', 183 imgName: '图片', 184 imgVisible: false 185 }; 186 }, 187 mounted () { 188 189 }, 190 methods: { 191 init () { 192 this.imgVisible = true 193 this.$nextTick(() => { 194 this.instance = new ImageEditor(document.querySelector('#tui-image-editor'), { 195 includeUI: { 196 loadImage: { 197 path: this.imgUrl, 198 name: 'image' 199 }, 200 menu: ['resize', 'crop', 'rotate', 'draw', 'shape', 'icon', 'text', 'filter'], // 底部菜单按钮列表 隐藏镜像flip和遮罩mask 201 initMenu: 'draw', // 默认打开的菜单项 202 menuBarPosition: 'bottom', // 菜单所在的位置 203 locale: locale_zh, // 本地化语言为中文 204 theme: customTheme // 自定义样式 205 206 }, 207 cssMaxWidth: 1000, // canvas 最大宽度 208 cssMaxHeight: 600 // canvas 最大高度 209 210 }) 211 document.getElementsByClassName('tui-image-editor-main')[0].style.top = '0px' // 调整图片显示位置 212 }) 213 }, 214 downloadImg () { // 文件下载 215 const base64String = this.instance.toDataURL(); 216 const file = base64ToFile(base64String, this.imgName) 217 fileLocalDownLoad([file], this.imgName) 218 }, 219 async uploadImg () { 220 const base64String = this.instance.toDataURL(); 221 let fileId = await uploadFileBase64(base64String, this.bucketName) 222 // 调用上级页面 223 this.$emit('doImgUpload', fileId) 224 this.imgVisible = false 225 }, 226 227 }, 228 }; 229 </script> 230 231 <style lang="css" scoped> 232 .container { 233 height: 90vh; 234 text-align: center; 235 } 236 .dialog-bottom { 237 text-align: right; 238 padding-top: 20px; 239 padding-right: 20px; 240 } 241 </style>
文件引入
export const base64ToFile = (base64, fileName) => { let arr = base64.split(',') let mime = arr[0].match(/:(.*?);/)[1] let bstr = atob(arr[1]) let n = bstr.length let u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } let blob = new Blob([u8arr], { type: mime }) blob.lastModifiedDate = new Date() blob.name = fileName console.log('functionbase64ToFile -> blob', blob) // file return blob } // 上传base64 export const uploadFileBase64 = (file, bucketName) => { let sendData = { strBase64Image: file, bucketName: bucketName } if (loading) { loading.close() // 关闭加载 } startLoading() // 开启加载 return request({ url: '/filemgr/uploadFileBase64', method: 'post', data: sendData }).then(({ data }) => { loading.close() // 关闭加载 if (data.code === 0) { return data.data } }) } // 文件下载 export function fileLocalDownLoad(data, fileName) { const blob = new Blob(data) let downloadElement = document.createElement('a') let href = window.URL.createObjectURL(blob) downloadElement.href = href downloadElement.download = decodeURIComponent(fileName) document.body.appendChild(downloadElement) downloadElement.click() document.body.removeChild(downloadElement) window.URL.revokeObjectURL(href) }