有點(diǎn)意思的Gif動圖生成平臺開發(fā)實(shí)戰(zhàn)
前言
筆者之前利于業(yè)余時間開發(fā)了一個gif動圖生成平臺, 具體開發(fā)背景我也在上一篇文章手把手教你擼一個能生成抖音風(fēng)格動圖的gif制作平臺中介紹過了, 我們今天繼續(xù)來實(shí)現(xiàn)該平臺, gif動圖平臺的實(shí)現(xiàn)方式比較將完全用前端的手段來實(shí)現(xiàn), 所以大家在接下來的內(nèi)容中會發(fā)現(xiàn)很多有意思的前端插件。 接下來我們看看主要要實(shí)現(xiàn)的功能點(diǎn):
- 純前端實(shí)現(xiàn)圖片上傳和預(yù)覽。
- 基于react-beautiful-dnd實(shí)現(xiàn)元素自由拖動排序。
- 使用javascript實(shí)現(xiàn)生成uuid的函數(shù)。
- 使用file-saver實(shí)現(xiàn)前端下載文件。
- 使用gif.js實(shí)現(xiàn)基于圖片生成gif動圖。
- 控制gif動圖播放速度的方法。
正文
還是按照筆者一貫的風(fēng)格, 在實(shí)現(xiàn)功能之前我們先看看實(shí)現(xiàn)后的預(yù)覽效果:
由效果圖可以看出我們只需要上傳圖片序列, 就可以動態(tài)生成gif動圖, 并且可以右鍵保存gif文件. 我們還可以控制動圖的播放速度和排列順序, 以便更靈活的配置動圖. 如果大家想親自體驗(yàn),可以用以下方式直達(dá):
1、基本頁面搭建
在開始之前我們先要理清基本的頁面結(jié)構(gòu), 筆者劃分為如下結(jié)構(gòu):
由上圖可知一共劃分為3個區(qū), 我們可以使用任何我們熟悉的第三方組件去實(shí)現(xiàn), 筆者這里采用antd來開發(fā). 技術(shù)方案圖如下:
以上就是筆者分析的大致實(shí)現(xiàn)目標(biāo), 也是筆者常用的開發(fā)導(dǎo)圖, 目標(biāo)導(dǎo)向?qū)﹂_發(fā)效率的提升還是非常有幫助的, 筆者建議大家也可以在實(shí)現(xiàn)較復(fù)雜的業(yè)務(wù)需求之前先思考方案,再動手敲代碼.
2、實(shí)現(xiàn)圖片上傳預(yù)覽功能
對于第一步驟的界面我想大家都能實(shí)現(xiàn), 我們現(xiàn)在具體一步步落實(shí)到功能實(shí)現(xiàn). 我們先來實(shí)現(xiàn)一下圖片的上傳預(yù)覽. 由于我們這里沒有借助服務(wù)器, 完全由前端的方式實(shí)現(xiàn)圖片預(yù)覽, 所以我們需要用到FileReader對象.
FileReader 對象允許Web應(yīng)用程序異步讀取存儲在用戶計(jì)算機(jī)上的文件(或原始數(shù)據(jù)緩沖區(qū))的內(nèi)容,使用 File 或 Blob 對象指定要讀取的文件或數(shù)據(jù)。
其中File對象可以是來自用戶在一個input元素上選擇文件后返回的FileList對象,也可以來自拖放操作生成的DataTransfer對象,還可以是來自在一個HTMLCanvasElement上執(zhí)行mozGetAsFile()方法后返回結(jié)果。接下來我們看看如何利用antd的Upload組件和FileReader實(shí)現(xiàn)圖片預(yù)覽, 具體代碼如下:
uploadprops即為Upload組件需要的屬性配置, 通過代碼我們可以知道, 我們在beforeUpload階段攔截了圖片, 通過FileReader對象的readAsDataURL
在代碼中我們將圖片數(shù)據(jù)存儲到一個對象里, 對象包括由uuid函數(shù)生成的唯一id和url組成, 至于為何生成唯一id, 這里筆者將在下文中介紹。
3. 使用react-beautiful-dnd實(shí)現(xiàn)元素自由拖動排序
大家在研究過H5-Dooring | 一款強(qiáng)大的開源H5編輯器 后就會發(fā)現(xiàn)react-dnd這個模塊很熟悉, 因?yàn)樵撻_源編輯器就使用了react-dnd實(shí)現(xiàn)的組件拖拽和組件數(shù)據(jù)傳遞的. 筆者在社區(qū)又發(fā)現(xiàn)了一個比較有意思的拖拽庫react-beautiful-dnd, 同樣可以實(shí)現(xiàn)優(yōu)雅平滑的智能拖拽效果, 基本案例如下:
在深入研究該庫之后筆者發(fā)現(xiàn)可以直接用來實(shí)現(xiàn)圖片組件的拖拽并排序的功能, 所以筆者直接使用該庫來封裝我們的圖片組件. 由于該庫的使用有詳細(xì)的案例代碼,這里筆者就不做詳細(xì)介紹了, 只需要提一點(diǎn)就是為了實(shí)現(xiàn)排序, 我們需求確定每一個元素的唯一標(biāo)識, 所以這里筆者想到了uuid, 所以渲染圖片的數(shù)組數(shù)據(jù)結(jié)構(gòu)可以長這樣:
為了限制圖片上傳過大, 我們還可以在Upload組件的beforeUpload階段限制圖片上傳大小, 這個根據(jù)使用而定. uuid的實(shí)現(xiàn)方式很多, 筆者這里送上一個實(shí)現(xiàn)方式:
實(shí)現(xiàn)后的效果如下圖:
至于刪除圖片的方法也很簡單, 通過圖片的唯一id去數(shù)組里使用數(shù)組的fiter方法刪除即可。
4、控制gif動圖播放速度的方法
控制gif的播放速度方法我們可以用slider組件實(shí)現(xiàn), gif.js也提供速度的接口, 我們只需要實(shí)現(xiàn)速度值的計(jì)算即可. 我們都知道滑塊滑動越長, 數(shù)值越大, 與之對應(yīng)的 速度越大, 時間間隔越小, 所以我們在前端層設(shè)計(jì)的展示效果如下:
滑塊最大值筆者設(shè)置為20, 最小值為1, 對應(yīng)的當(dāng)滑塊設(shè)置為最大值時, gif的播放速度最大, 每張圖片停留間隔為0.1s, 滑塊為最小值1時, gif播放速度最小, 每張圖片停留2s, 根據(jù)這個規(guī)律我們得到了如下規(guī)律:
具體代碼如下:
當(dāng)然大家可以用更簡單的方式來實(shí)現(xiàn), slider組件也提供反向取值的操作。
5、基于圖片序列生成gif動圖
基于圖片序列生成gif的方式也很簡單, 我們通過批量獲取圖片拖動區(qū)的圖片, 組裝成數(shù)組傳給gif.js即可. 我們直接看效果:
6. 使用file-saver實(shí)現(xiàn)前端下載文件
我們只需要把生成的gif圖片, 傳遞給file-saver模塊中, 使用其提供的API即可下載文件, 這里在之前文章筆者也介紹過了, 這里直接上代碼:
本文轉(zhuǎn)載自微信公眾號「趣談前端」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系趣談前端公眾號。