在線圖片編輯器,支持PSD解析、AI摳圖等
自從我上次分享一個人開發(fā)仿造稿定設(shè)計的圖片編輯器到現(xiàn)在,不知不覺已過去一年時間了,期間我經(jīng)歷了裁員失業(yè)、面試找工作碰壁,寒冬下一直沒有很好地履行計劃.....這些就放在日后談吧。
最近擠出時間來完善了這個項目,正式開源后在一天內(nèi)就收獲了上百個Star,今天想向大家分享下這個開源圖片編輯器項目——迅排設(shè)計,以及我的一些感悟和開源體驗。
項目速覽
git clone https://github.com/palxiao/poster-design.git
cd poster-design
npm run prepared # 快捷安裝依賴指令
npm run serve # 本地運行
將同時運行前端界面與圖片生成服務(3000與7001端口),合成圖片時本地會啟動一個Chrome瀏覽器實例。
下面一起來看下都有些什么功能吧。
上傳 PSD 模板
點擊 “我的” - “資源管理”,上傳PSD模板按鈕,進入PSD解析上傳界面[4]界面。選擇或拖入 PSD 文件,等待解析完成后開始編輯,調(diào)整好模板后點擊右上角“上傳模板”,等待完成。
上傳完成后點擊查看作品即可打開模板,之后在 “我的作品” 中可以找到該模板。
線上為功能測試,資源將被上傳到 Github,并使用 jsdelivr 作為 CDN 節(jié)點訪問,這在某些網(wǎng)絡條件下可能會體驗不佳,請確認你的網(wǎng)絡環(huán)境,必要時科學上網(wǎng)。
由于服務器在國內(nèi),生成下載圖片可能會圖裂,這不是BUG。
AI 摳圖
上傳需要去除背景的圖片,自動摳除背景。在線體驗[5]
以上在線體驗效果Demo所分配的服務器資源僅1核1G內(nèi)存,可以看到應付簡單摳圖場景還是不錯的,后續(xù)我會另開一篇文章介紹如何部署,感興趣的話提前關(guān)注不迷路~
編輯與設(shè)計
快捷鍵
? 保存:Ctrl / Command + S
? 復制(選中元素):Ctrl / Command + C
? 粘貼:Ctrl / Command + V
? 多選:按住 Shift 或 Ctrl / Command 然后鼠標點選
? 組合成組(多選時):Ctrl / Command + G
文字
畫布中雙擊內(nèi)容,編輯文字,修改顏色,原生吸色器(Chrome):
圖片
除了拖拽縮放圖片大小,也可對圖像內(nèi)容進行縮放裁剪,裁剪通常用于截取顯示原圖像的一部分:
支持拖動圖片放置到一個容器中顯示:
圖層
圖層面板中可隨意拖動元素快速改變層級,圖層鎖定后將固定在畫布中,此時元素變得不可移動,再次點擊按鈕即可解鎖:
標尺
從標尺欄中拖出輔助線,按住線段拖回標尺欄中刪除輔助線
項目架構(gòu)
編輯界面就不多說了,就是對著稿定設(shè)計來,主要說說在保存時的操作,實際保存的是兩段JSON內(nèi)容:
其中 Page 是整個頁面的 Schema,而 Widgets 則是扁平化的數(shù)組,代表著整個頁面中的元素集合,拍平是為了高效直觀地實現(xiàn)層級以及查找組件。
保存這些 JSON 后,在繪制頁面請求這些信息,然后將頁面呈現(xiàn)出來,繪制頁移除了畫布操作、屬性菜單面板等編輯頁才有的功能,只保留了基礎(chǔ)組件的引入(如果有充足開發(fā)成本理論上可嘗試采用 SSR 進一步提升速度),并通過一系列方法判斷字體、圖片、SVG等元素是否加載完畢,一旦整個頁面以及資源都加載完成則調(diào)用 window 下的廣播通知開始截圖。
在服務端,我們使用 puppeteer 啟動無頭瀏覽器,在 Chrome 中打開繪制頁,并往其 BOM 中注入廣播通知方法,這樣就完成了整個圖片生成操作的閉環(huán)。
技術(shù)棧概括
前端:Vue3 、Vite2 、Vuex 、ElementPlus
圖片生成:Puppeteer、Express
服務端:Node.js
一些可獨立的功能會被抽取出來作為單獨的庫引入使用。
組件庫 Github 地址:https://github.com/palxiao/front-end-arsenal
前端目錄詳解
/src
├── App.vue
├── api // 請求接口管理
├── assets
| ├── data // 數(shù)據(jù)資源
| ├── fonts // 本地字體資源
| └── styles // CSS 樣式文件
├── common // 存放一些公共方法,例如上傳下載、彈窗提示等
| ├── hooks
| └── methods
├── components
| ├── business // 放置業(yè)務組件
| | ├── cropper // 裁剪(暫時棄用)
| | ├── image-cutout // 摳圖
| | ├── moveable // 操作插件
| | ├── picture-selector // 照片庫彈窗選擇
| | ├── qrcode // 二維碼插件
| | ├── right-click-menu // 右鍵菜單
| | └── save-download // 保存下載彈窗
| ├── common // 公共組件
| | ├── PopoverTip.vue // 氣泡提示組件
| | ├── ProgressLoading // 百分比進度條
| | └── Uploader // 上傳組件
| └── modules // 核心模塊
| ├── index.ts
| ├── layout
| | ├── designBoard.vue // 主界面
| | ├── lineGuides.vue // 網(wǎng)格(棄用,由moveable提供輔助線功能)
| | ├── sizeControl.vue // 元素操作組件(棄用,由moveable代理)
| | └── zoomControl.vue // 縮放畫布
| ├── panel // 該目錄下的所有文件自動導入項目中
| | ├── components
| | ├── stylePanel.vue // 右側(cè)屬性編輯面板
| | ├── widgetPanel.vue // 左側(cè)功能菜單面板
| | └── wrap
| | ├── BgImgListWrap.vue // 背景選擇面板
| | ├── PhotoListWrap.vue // 照片面板
| | ├── TempListWrap.vue // 模板列表
| | ├── ToolsListWrap.vue // 工具面板
| | ├── UserWrap.vue // 我的資源作品面板
| | ├── GraphListWrap.vue // 素材面板
| | ├── CompListWrap.vue // 組合列表(目前主要是文字組合)
| | └── TextListWrap.vue // 文字面板
| ├── settings // 放置操作面板下的一些組件
| | ├── EffectSelect // 效果選擇(未開發(fā))
| | ├── colorSelect.vue // 顏色選擇
| | ├── iconItemSelect.vue // icon選擇
| | ├── numberInput.vue // 數(shù)字輸入
| | ├── numberSlider.vue // 數(shù)字拖拉
| | ├── textInput.vue // 文字輸入
| | ├── textInputArea.vue // 文字域輸入
| | └── valueSelect.vue // 下拉選擇
| └── widgets // 該目錄下的所有文件自動導入項目中
| ├── pageStyle.vue // 背景/頁面設(shè)置
| ├── wGroup // 組合
| | ├── wGroup.vue
| | └── wGroupStyle.vue // 對應右側(cè)面板的操作
| ├── wImage // 圖片
| | ├── components
| | | └── innerToolBar.vue
| | ├── wImage.vue
| | └── wImageStyle.vue // 對應右側(cè)面板的操作
| ├── wQrcode // 二維碼
| | ├── wQrcode.vue
| | └── wQrcodeStyle.vue // 對應右側(cè)面板的操作
| ├── wSvg // 矢量圖
| | ├── wSvg.vue
| | └── wSvgStyle.vue // 對應右側(cè)面板的操作
| └── wText // 文字
| ├── wText.vue
| └── wTextStyle.vue // 對應右側(cè)面板的操作
├── config.ts // 公共配置
├── main.ts // 項目入口文件
├── mixins // 一些公共混合代碼,考慮優(yōu)化
| ├── methods
| | ├── DealWithCtrl.ts
| | └── keyCodeOptions.ts
| ├── mouseDragging.ts
| ├── move.ts
| └── shortcuts.ts
├── router // vue 路由
| ├── .....
├── store // Vuex 狀態(tài)管理器
| ├── index.ts
| └── modules
| ├── base
| | ├── .......
| └── design
| ├── .......
├── types // TS類型配置
| ├── .......
├── utils // 工具函數(shù)目錄
| ├── axios.ts
| ├── index.ts
| ├── plugins
| | ├── cssLoader.ts // 異步加載css
| | ├── modules.ts // 全局加載公共組件
| | ├── pointImg.ts // 圖片點位顏色,測試中
| | ├── preload.ts // 加載資源
| | └── psd // 設(shè)計稿解析
| ├── utils.ts
| └── widgets
| └── elementConfig.ts // 配置全局默認導入的element組件
└── views // 頁面目錄
├── Draw.vue // 繪制頁
├── Index.vue // 編輯頁(首頁)
├── Psd.vue // PSD解析頁
└── components
由于項目當初開發(fā)至一半時才改用 Vue3 重構(gòu),所以有部分代碼混合了 Options 寫法,還請各位大佬不要笑話。
開源感受
早在去年我于年中總結(jié)文章里分享這個項目后,就收到不少私信留言表示對項目感興趣,甚至有要花錢買源碼或商業(yè)化二次開發(fā)的,我都回絕了。當時我的想法是:這個項目能受到關(guān)注說明一定是有價值的,那么就不應該封閉起來!
與大多數(shù)程序員一樣,我開始寫前端也是從一段段“膠水”代碼開始的,遇到問題的第一反應就是打開瀏覽器搜索,然后從各種問答與筆記中抽絲剝繭式地嘗試解決問題。
后來,代碼越寫越熟練,各種框架庫使用起來得心應手,算得上是初窺門徑,有時甚至也能一個人扛起整個前端項目了。當然,項目里通常也包含了幾十甚至上百個第三方依賴。
不必感到羞恥,這就是許多公司開發(fā)的常態(tài),技術(shù)細節(jié)的探索與學習是永無止境的,但無法保證效率的話,你可能會先丟掉飯碗,所有插件庫都手擼,你可能一個項目都做不出來。
在我一開始做這個項目的時候,沒有找到現(xiàn)成的開源可以依貓畫虎,最后雖然寫完了整個項目,但也走了不少彎路。所以我看到了對項目關(guān)注的人,就仿佛看到了曾經(jīng)的自己,因此決定開源,即使我代碼寫得再爛,興許也會有需要的人。
事實上,今年有人基于我的項目二次開發(fā),上線了公司內(nèi)部的編輯器:
有人正打算在公司的搭建器上增加類似的功能,特地加了我微信向我道謝:
雖然這些都不是我的產(chǎn)出成果,但他們至少不用踩我踩過的坑,留出更多的時間,可以去研究自己熱愛的東西,去實現(xiàn)自己某方面的技術(shù)追求,最終產(chǎn)出更多的輪子,前端的生態(tài)就會越來越好,所有人也就都能從中受益,這也是開源的意義之一。
目前項目還在不斷完善中,可能有很多的不足之處,代碼寫得爛,我也是一邊學習一邊成長。開源不易,如果項目對你有幫助或啟發(fā),可以點個 Star 支持一下~ 感謝!
Github 倉庫地址: https://github.com/palxiao/poster-design
鏈接
[1] 在線Demo: https://design.palxp.com/
[2] 文檔網(wǎng)站: https://xp.palxp.com/
[3] PSD解析上傳界面: https://design.palxp.com/psd
[4] AI摳圖在線體驗: https://design.palxp.com/home?koutu=1