前言
最近用户提出了一个新的需要,老师能够批改学生的图片作业,须要对图片进行旋转、缩放、裁剪、涂鸦、标注、增加文本等。乍一听,又要掉不少头发。有没有功能强大的插件实现以上性能,让我有更多的工夫去阻止女票双十一剁手呢?答案当然是有的。
成果展现
涂鸦
裁剪
标注
旋转
滤镜
是不是很弱小!还有泛滥性能我就不一一展现了。那么还等什么,跟我一起用起来吧~
装置
npm i tui-image-editor// oryarn add tui-image-editor
应用
疾速体验
复制以下代码,将插件引入到本人的我的项目中。
<template> <div class="drawing-container"> <div id="tui-image-editor"></div> </div></template><script>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 { data() { return { instance: null, }; }, mounted() { this.init(); }, methods: { init() { this.instance = new ImageEditor( document.querySelector("#tui-image-editor"), { includeUI: { loadImage: { path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image", name: "image", }, initMenu: "draw", // 默认关上的菜单项 menuBarPosition: "bottom", // 菜单所在的地位 }, cssMaxWidth: 1000, // canvas 最大宽度 cssMaxHeight: 600, // canvas 最大高度 } ); document.getElementsByClassName("tui-image-editor-main")[0].style.top = "45px"; // 图片距顶部工具栏的间隔 }, },};</script><style lang="scss" scoped>.drawing-container { height: 900px;}</style>
能够看到活生生的图片编辑工具就呈现了,是不是很简略:
国际化
因为是老外开发的,默认的文字描述都是英文,这里咱们先汉化一下:
const 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": "锁定宽高比例",};this.instance = new ImageEditor( document.querySelector("#tui-image-editor"), { includeUI: { loadImage: { path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image", name: "image", }, initMenu: "draw", // 默认关上的菜单项 menuBarPosition: "bottom", // 菜单所在的地位 locale: locale_zh, // 本地化语言为中文 }, cssMaxWidth: 1000, // canvas 最大宽度 cssMaxHeight: 600, // canvas 最大高度 });
成果如下:
自定义款式
默认格调为暗黑系,如果想改成白底,或者想扭转按钮的大小、色彩等款式,能够应用自定义款式。
const 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",};this.instance = new ImageEditor( document.querySelector("#tui-image-editor"), { includeUI: { loadImage: { path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image", name: "image", }, initMenu: "draw", // 默认关上的菜单项 menuBarPosition: "bottom", // 菜单所在的地位 locale: locale_zh, // 本地化语言为中文 theme: customTheme, // 自定义款式 }, cssMaxWidth: 1000, // canvas 最大宽度 cssMaxHeight: 600, // canvas 最大高度 });
成果如下:
按钮优化
通过自定义款式,咱们看到右上角的 Load 和 Download 按钮曾经被暗藏了,接下来咱们再暗藏掉其余用不上的按钮(依据业务须要),并增加一个保留图片的按钮。
<template> <div class="drawing-container"> <div id="tui-image-editor"></div> <el-button class="save" type="primary" size="small" @click="save">保留</el-button> </div></template>// ...methods: { init() { this.instance = new ImageEditor( document.querySelector("#tui-image-editor"), { includeUI: { loadImage: { path: "https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image", name: "image", }, menu: ["resize", "crop", "rotate", "draw", "shape", "icon", "text", "filter"], // 底部菜单按钮列表 暗藏镜像flip和遮罩mask initMenu: "draw", // 默认关上的菜单项 menuBarPosition: "bottom", // 菜单所在的地位 locale: locale_zh, // 本地化语言为中文 theme: 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"; // 暗藏顶部重置按钮 }, // 保留图片,并上传 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 文件 const form = new FormData(); form.append("image", blob); // upload file },}<style lang="scss" scoped>.drawing-container { height: 900px; position: relative; .save { position: absolute; right: 50px; top: 15px; }}</style>
成果如下:
能够看到顶部的重置按钮,以及底部的镜像和遮罩按钮都曾经不见了。右上角多了一个咱们本人的保留按钮,点击按钮,能够获取到 base64 文件和 blob 文件。
残缺代码
<template> <div class="drawing-container"> <div id="tui-image-editor"></div> <el-button class="save" type="primary" size="small" @click="save">保留</el-button> </div></template><script>import 'tui-image-editor/dist/tui-image-editor.css'import 'tui-color-picker/dist/tui-color-picker.css'import ImageEditor from 'tui-image-editor'const 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': '锁定宽高比例'}const 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",};export default { data() { return { instance: null } }, mounted() { this.init() }, methods: { init() { this.instance = new ImageEditor(document.querySelector('#tui-image-editor'), { includeUI: { loadImage: { path: 'https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c1d7a1feb60346449c1a64893888989a~tplv-k3u1fbpfcp-watermark.image', name: 'image' }, menu: ['resize', 'crop', 'rotate', 'draw', 'shape', 'icon', 'text', 'filter'], // 底部菜单按钮列表 暗藏镜像flip和遮罩mask initMenu: 'draw', // 默认关上的菜单项 menuBarPosition: 'bottom', // 菜单所在的地位 locale: locale_zh, // 本地化语言为中文 theme: 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' // 暗藏顶部重置按钮 }, // 保留图片,并上传 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 文件 const form = new FormData() form.append('image', blob) // upload file } }}</script><style lang="scss" scoped>.drawing-container { height: 900px; position: relative; .save { position: absolute; right: 50px; top: 15px; }}</style>
总结
以上就是 tui.image-editor 的根本应用办法,相比其余插件,tui.image-editor 的劣势是功能强大,简略易上手。
插件诚然好用,但自己也发现一个小 bug,当放大图片,用手掌拖动显示地位,再点击重置按钮时,图片很可能就隐没不见了。解决办法有两个,一是改源码,在重置之前,先调用 resetZoom 办法,还原缩放比列;二是本人做一个重置按钮,点击之后调用 this.init 办法从新进行渲染。
赠人玫瑰,手有余香。如果感觉有用,就动动发财的小手,点个赞把~
更多 API 及 Demo 请参考:
github地址:https://github.com/nhn/tui.im...
API 及 Examples 地址:http://nhn.github.io/tui.imag...
其余插件
每一款都是自己亲测,精挑细选、凤毛麟角。让你有更多工夫去摸
Vue 1分钟实现右键菜单,懒人的福音
Vue 如何疾速实现头像裁剪?办法比你设想的简略
如何在富文本中插入表情,word文档,及数学公式?
1分钟实现拖拽,让你划水更自在