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) }
