3.6k Star!簡單易用,過濾器強(qiáng)大的在線圖片編輯器
【導(dǎo)語】:ToastUI Image Editor 是一個基于 HTML5 畫布的圖片編輯器,它使用起來非常簡單,而且內(nèi)置了豐富的圖片編輯功能。
簡介
ToastUI Image Editor 是一個基于 HTML5 Canvas 的圖片編輯器,它使用起來非常簡單,而且內(nèi)置了豐富的圖片編輯功能。它支持原生 JavaScript、Vue 組件 和 ?React 組件三種使用方式。
基礎(chǔ)使用
Javascript
最簡單的方式安裝就是直接取引用它在線的 CDN 資源,我們直接看一個 html 的例子:
html>
<html>
<head>
??<meta?charset="UTF-8">
??<title>ImageEditor?Demotitle>
??<link?type="text/css"?href="https://uicdn.toast.com/tui-color-picker/v2.2.6/tui-color-picker.css"?rel="stylesheet">
??<link?rel="stylesheet"?href="https://uicdn.toast.com/tui-image-editor/latest/tui-image-editor.css">
??<style>
????html,
????body?{
??????height:?100%;
??????margin:?0;
????}
??style>
head>
<body>
??<div?id="tui-image-editor-container">div>
??
??<script?type="text/javascript"?src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.0/fabric.js">script>
??
??<script?type="text/javascript"?src="https://uicdn.toast.com/tui.code-snippet/v1.5.0/tui-code-snippet.min.js">script>
??
??<script?type="text/javascript"?src="https://uicdn.toast.com/tui-color-picker/v2.2.6/tui-color-picker.js">script>
??
??<script?type="text/javascript"?src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.3/FileSaver.min.js">script>?
??
??<script?src="https://uicdn.toast.com/tui-image-editor/latest/tui-image-editor.js">script>
??<script>
????var?imageEditor?=?new?tui.ImageEditor('#tui-image-editor-container',?{
??????includeUI:?{
????????initMenu:?'filter',
????????menuBarPosition:?'left'
??????},
??????cssMaxWidth:?700,
??????cssMaxHeight:?500,
??????usageStatistics:?false
????});
????window.onresize?=?function?()?{
??????imageEditor.ui.resizeEditor();
????}
??script>
body>
html>
我們可以看到,引入了很多 CDN 資源,每個資源的作用都有解釋。我們來看一下這個編輯器都使用。
首先我們實(shí)例化了一個 ImageEditor 類,它第一個參數(shù)是掛載點(diǎn),這里表示將編輯器掛載到 id 為 tui-image-editor-container 的元素上;接著第二個參數(shù)是這個編輯器的屬性,下面是對屬性的簡單介紹:
includeUI:表示使用它內(nèi)置的 UI 控件initMenu:表示編輯器加載后,第一個被選中的操作菜單,這里選的是filter,也就是濾鏡menuBarPosition:表示菜單欄的位置,有四個選項可選:'top', 'bottom', 'left', 'right'cssMaxWidth:編輯器 Canvas 的最大寬度cssMaxHeight:編輯器 Canvas 的最大高度usageStatistics:是否開啟 GA (Google Analytics)來收集數(shù)據(jù)。它是默認(rèn)開啟的,不想使用的話可以設(shè)置為false
還有一些屬性我們會在后面用到。這里要注意,無論是原生 JavaScript 的使用方式,還是 Vue、React 的組件使用方式,他們的配置屬性幾乎一致,所以你不用擔(dān)心要根據(jù)不同情況修改配置的問題。 實(shí)際上,Vue、React 組件就是對這個原生方式的一層包裝,本質(zhì)上是一回事。
介紹完了,我們先來看看上面例子的運(yùn)行效果:

我們來感受一下它強(qiáng)大的功能吧!
可以看到,當(dāng)我們加載一張圖片進(jìn)入工作區(qū)的時候,默認(rèn)高亮開啟的操作是最后一個濾鏡(filter)的操作,我們對圖片進(jìn)行了濾鏡、添加文字、添加圖標(biāo)、鏡像翻轉(zhuǎn)、裁剪等操作后,點(diǎn)擊 Download 下載了我們操作后的圖片。只是簡單的幾行代碼,就能實(shí)現(xiàn)如此強(qiáng)大的圖片編輯功能,是不是很神奇!接下來我們看看,如何在我們的前端框架中集成它。
Vue
我們使用 vue-cli 搭建一個簡單的項目,然后安裝 tui-image-editor:
npm?install?--save?@toast-ui/vue-image-editor
接著我們在 App.vue 中使用這個組件:
<template>
??<div?id="app">
????<ImageEditor?:include-ui="useDefaultUI"?:options="options">ImageEditor>
??div>
template>
<script>
//?引入樣式
import?"tui-image-editor/dist/tui-image-editor.css";
import?"tui-color-picker/dist/tui-color-picker.css";
//?引入組件
import?ImageEditor?from?"@toast-ui/vue-image-editor/src/ImageEditor.vue";
import?Logo?from?"@/assets/logo.png";
export?default?{
??name:?"App",
??components:?{
????ImageEditor,
??},
??data()?{
????return?{
??????useDefaultUI:?true,
??????options:?{
????????includeUI:?{
??????????//?默認(rèn)開啟繪圖的功能
??????????initMenu:?"draw",
??????????//?支持的菜單
??????????menu:?[
????????????"crop",
????????????"draw",
????????????"icon",
????????????"text",
??????????],
??????????//?菜單位置在下面
??????????menuBarPosition:?"bottom",
??????????//?默認(rèn)加載的圖片
??????????loadImage:?{
????????????//?圖片路徑
????????????path:?Logo,
????????????//?圖片的名字,可以省略
????????????name:?"sample",
??????????},
????????},
??????},
????};
??},
};
script>
<style>
html,
body?{
??height:?100%;
??margin:?0;
}
#app?{
??height:?100%;
}
style>
可以看到,我們新加了 loadImage 的配置,它表示默認(rèn)加載的圖片;又新加了一個 menu 的配置,它的值是一個數(shù)組,表示我們需要的功能菜單,如果沒有配置的話,默認(rèn)是開啟所有功能。我們運(yùn)行 npm run serve 看一下效果:

果然,我們的功能菜單只有四個了。
全部的功能菜單如下:
?menu:?[
??"crop",?//?裁切
??"flip",?//?翻轉(zhuǎn)
??"rotate",?//?旋轉(zhuǎn)
??"draw",?//?添加繪畫
??"shape",?//?添加形狀
??"icon",?//?添加圖標(biāo)
??"text",?//?添加文本
??"mask",?//?添加覆蓋
??"filter",?//?添加濾鏡
],
可以根據(jù)項目的具體需要來進(jìn)行適當(dāng)?shù)脑鰷p。
React
在 React 使用也很簡單,我們可以基于 create-react-app 創(chuàng)建一個簡單的項目,然后安裝依賴:
npm?install?--save?@toast-ui/react-image-editor
我們接著在 App.js 中使用組件:
import?'tui-image-editor/dist/tui-image-editor.css'
import?ImageEditor?from?'@toast-ui/react-image-editor'
function?App()?{
??return?(
????<div?className="App">
??????<h1>ImageEditor?React?Demoh1>
??????<ImageEditor
????????includeUI=?{{
??????????initMenu:?"draw",
??????????menu:?["crop",?"draw",?"icon",?"text"],
??????????menuBarPosition:?"left",
??????????loadImage:?{
????????????path:?'logo192.png',
????????????name:?"sample",
??????????},
??????????uiSize:?{
????????????height:?'600px'
??????????},
????????}}
????????/>
????div>
??);
}
export?default?App;
我們的配置項與上例中 Vue 組件的方式基本一致。運(yùn)行 npm start 看一下效果,應(yīng)該與上例一樣:

進(jìn)階用法
了解了基礎(chǔ)用法之后,我們來深入的學(xué)習(xí)一下它的其他功能。掌握這些之后,在實(shí)際項目中用到它就可以游刃有余了。注意,這里的例子都會以 Vue 組件的形式來介紹,其他方式的使用可以類比。
本地化(國際化)
這個 tui-image-editor 組件默認(rèn)是英文的,所以它的各種提示信息也都是英文的。我們平時的使用場景大都是中文的環(huán)境,所以做好這些信息的本地化轉(zhuǎn)換是很有必要的。tui-image-editor 也提供了相關(guān)的配置,我們只要補(bǔ)充需要翻譯的文本就可以了。接著上面 Vue 的例子來看一下如何配置:
<script>
import?"tui-image-editor/dist/tui-image-editor.css";
import?"tui-color-picker/dist/tui-color-picker.css";
import?ImageEditor?from?"@toast-ui/vue-image-editor/src/ImageEditor.vue";
import?Logo?from?"@/assets/logo.png";
const?localeCN?=?{
??Crop:?"裁剪",
??Draw:?"涂鴉",
??Icon:?"添加圖標(biāo)",
??Text:?"添加文本",
??Free:?"任意線條",
??Straight:?"直線",
??Color:?"顏色",
??Range:?"范圍",
};
export?default?{
??name:?"App",
??components:?{
????ImageEditor,
??},
??data()?{
????return?{
??????useDefaultUI:?true,
??????options:?{
????????includeUI:?{
??????????initMenu:?"draw",
??????????menu:?["crop",?"draw",?"icon",?"text"],
??????????menuBarPosition:?"bottom",
??????????locale:?localeCN,
??????????loadImage:?{
????????????path:?Logo,
????????????name:?"sample",
??????????},
????????},
??????},
????};
??},
};
script>
我們添加了 includeUI.locale 屬性,來看一下效果:

我們看到了,菜單的懸浮提示,和編輯圖片的提示都變成了中文。完整的本地化的 Key 值列表可以參考 tui-image-editor localization[1],你可以根據(jù)項目情況進(jìn)行修改。
主題
如果你不喜歡它這個樣式,你可以自己定制一份。它的配置類似于上面的本地化配置,也是提供一組 key-value 的映射對象。比如我們繼續(xù)在上面的例子上添加主題配置:
<script>
import?"tui-image-editor/dist/tui-image-editor.css";
import?"tui-color-picker/dist/tui-color-picker.css";
import?ImageEditor?from?"@toast-ui/vue-image-editor/src/ImageEditor.vue";
import?Logo?from?"@/assets/logo.png";
const?localeCN?=?{
??Crop:?"裁剪",
??Draw:?"涂鴉",
??Icon:?"添加圖標(biāo)",
??Text:?"添加文本",
??Free:?"任意線條",
??Straight:?"直線",
??Color:?"顏色",
??Range:?"范圍",
};
const?customTheme?=?{
??//?菜單-普通狀態(tài)?-?綠色
??"menu.normalIcon.color":?"green",
??//?菜單-選中狀態(tài)?-?藍(lán)色
??"menu.activeIcon.color":?"blue",
??//?菜單-禁用狀態(tài)?-?灰色
??"menu.disabledIcon.color":?"grey",
??//?菜單-鼠標(biāo)懸浮狀態(tài)?-?黃色
??"menu.hoverIcon.color":?"yellow",
??//?整體背景顏色
??"common.backgroundColor":?"#eaeaea",
??//?頭部的背景顏色
??"header.backgroundColor":?"#556677",
??//?下載按鈕背景顏色
??"downloadButton.backgroundColor":?"lightgreen",
??//?下載按鈕文字顏色
??"downloadButton.color":?"#fff",
??//?下載按鈕邊框樣式
??"downloadButton.border":?"none",
};
export?default?{
??name:?"App",
??components:?{
????ImageEditor,
??},
??data()?{
????return?{
??????useDefaultUI:?true,
??????options:?{
????????includeUI:?{
??????????initMenu:?"draw",
??????????menu:?["crop",?"draw",?"icon",?"text"],
??????????menuBarPosition:?"bottom",
??????????locale:?localeCN,
??????????loadImage:?{
????????????path:?Logo,
????????????name:?"sample",
??????????},
??????????theme:?customTheme,
????????},
??????},
????};
??},
};
script>
我們添加了一組樣式到 includeUI.theme 屬性上,來看看效果:

完整的樣式主題可以參考源碼中 src/js/ui/theme/standard.js[2] 文件。
如果你想要修改他的 icon 文件的話,可以參考這個鏈接 menu-submenu-svg-icon-setting[3],要注意的是要考慮到每個狀態(tài)下的icon(normal,active,disable,hover)。
方法調(diào)用
tui-image-editor 也提供了許多內(nèi)置的方法,方便我們自己處理一些邏輯。它的方法列表文檔可以參考:http://nhn.github.io/tui.image-editor/latest/ImageEditor/[4]
我們繼續(xù)修改上面的例子,這次我們增加幾個外部的按鈕,來自己手動的操作圖片:
<template>
??<div?id="app">
????<ImageEditor?ref="editor"?:include-ui="useDefaultUI"?:options="options">ImageEditor>
????<div?class="actions">
??????<button?@click="addText">Add?Textbutton>
??????<button?@click="rotate">Rotatebutton>
??????<button?@click="flip">Flip?Ybutton>
??????<button?@click="undo">Undobutton>
????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?"@toast-ui/vue-image-editor/src/ImageEditor.vue";
import?Logo?from?"@/assets/logo.png";
const?localeCN?=?{
??Crop:?"裁剪",
??Draw:?"涂鴉",
??Icon:?"添加圖標(biāo)",
??Text:?"添加文本",
??Free:?"任意線條",
??Straight:?"直線",
??Color:?"顏色",
??Range:?"范圍",
};
const?customTheme?=?{
??//?菜單-普通狀態(tài)?-?綠色
??"menu.normalIcon.color":?"green",
??//?菜單-選中狀態(tài)?-?藍(lán)色
??"menu.activeIcon.color":?"blue",
??//?菜單-禁用狀態(tài)?-?灰色
??"menu.disabledIcon.color":?"grey",
??//?菜單-鼠標(biāo)懸浮狀態(tài)?-?黃色
??"menu.hoverIcon.color":?"yellow",
??//?整體背景顏色
??"common.backgroundColor":?"#eaeaea",
??//?頭部的背景顏色
??"header.backgroundColor":?"#556677",
??//?下載按鈕背景顏色
??"downloadButton.backgroundColor":?"lightgreen",
??//?下載按鈕文字顏色
??"downloadButton.color":?"#fff",
??//?下載按鈕邊框樣式
??"downloadButton.border":?"none",
};
export?default?{
??name:?"App",
??components:?{
????ImageEditor,
??},
??data()?{
????return?{
??????useDefaultUI:?true,
??????options:?{
????????includeUI:?{
??????????initMenu:?"draw",
??????????menu:?["crop",?"draw",?"icon",?"text"],
??????????menuBarPosition:?"bottom",
??????????locale:?localeCN,
??????????loadImage:?{
????????????path:?Logo,
????????????name:?"sample",
??????????},
??????????theme:?customTheme,
????????},
??????},
????};
??},
??methods:?{
????addText()?{
??????//?添加文字?Hello?Jerry
??????//?默認(rèn)在工作區(qū)的中間
??????//?文字填充顏色?-?紅色;文字大小 22px;
??????this.$refs.editor.invoke("addText",?"Hello?Jerry",?{
????????styles:?{
??????????fontSize:?22,
??????????fill:?"red",
????????},
??????});
????},
????//?旋轉(zhuǎn)?20?度
????rotate()?{
??????this.$refs.editor.invoke("rotate",?10);
????},
????//?沿?Y?軸翻轉(zhuǎn)
????flip()?{
??????this.$refs.editor.invoke("flipY");
????},
????//?撤銷上一次操作
????undo()?{
??????this.$refs.editor.invoke("undo");
????},
??},
};
script>
<style>
html,
body?{
??height:?100%;
??margin:?0;
}
#app?{
??height:?80%;
}
button?{
??height:?30px;
??line-height:?30px;
??margin:?30px;
}
style>
我們添加了四個操作按鈕,分別是 添加文字,旋轉(zhuǎn),沿Y軸翻轉(zhuǎn),撤銷,來看一下效果:

可以看到,與我們在編輯器內(nèi)的操作無異。其實(shí)編輯器內(nèi)幾乎所有的操作,我們都可以使用方法調(diào)用的方式自己實(shí)現(xiàn)。這樣,我們就可以充分的發(fā)揮自由性,結(jié)合需求自己封裝出一個更貼合實(shí)際的組件。
事件監(jiān)聽
Vue 組件提供了如下的事件監(jiān)聽:
addText: 添加文字 mousedown: 鼠標(biāo)按下 objectActivated: Canvas 中 有元素被選中 objectMoved: Canvas 中有元素移動 objectScaled: 元素縮放 redoStackChanged: 操作棧中的 redo 事件 textEditing: 文字編輯 undoStackChanged: 操作棧中的 undo 事件
我們在上面的例子上添加幾個監(jiān)聽事件:
<template>
??//?.....
??<ImageEditor
????ref="editor"
????@addText="onAddText"
????@textEditing="onEditText"
????@objectMoved="onObjectMove"
????:include-ui="useDefaultUI"
????:options="options"
??>ImageEditor>
template>
<script>
export?default?{
??//?....
??methods:?{
????onAddText(pos)?{
??????console.info(`Adding?Text?on?(${pos.originPosition.x},?${pos.originPosition.y})`);
????},
????onEditText()?{
??????console.info("Text?Editing");
????},
????onObjectMove(e)?{
??????console.info(`Object?moving...?`,?e);
????}
??}
}
script>
來看一下效果:

通過控制臺的日志可以看到,我們的事件回調(diào)函數(shù)都被觸發(fā)了。更多事件的使用方法請參考 官方文檔[5]
參考資料
tui-image-editor localization: https://github.com/nhn/tui.image-editor/blob/master/docs/Basic-Tutorial.md#5-localization
[2]src/js/ui/theme/standard.js: https://github.com/nhn/tui.image-editor/blob/master/src/js/ui/theme/standard.js
[3]menu-submenu-svg-icon-setting: https://github.com/nhn/tui.image-editor/blob/master/docs/Basic-Tutorial.md#4-menu-submenu-svg-icon-setting
[4]http://nhn.github.io/tui.image-editor/latest/ImageEditor/: http://nhn.github.io/tui.image-editor/latest/ImageEditor/
[5]官方文檔: http://nhn.github.io/tui.image-editor/latest/ImageEditor#event-addObjectAfter
-?EOF -?
更多優(yōu)秀開源項目(點(diǎn)擊下方圖片可跳轉(zhuǎn))
如果覺得本文介紹的開源項目不錯,歡迎轉(zhuǎn)發(fā)推薦給更多人。
分享、點(diǎn)贊和在看
支持我們分享更多優(yōu)秀開源項目,謝謝!



