工做中遇到一個這麼一個需求:這是一個多圖上傳的場景,若是用戶上傳選擇多張圖片,則上傳後直接展現多張圖片,若是上傳的圖片是gif動圖,則須要分解這張動圖拆分紅一幀一幀的單張圖片,再按順序展現出來。javascript
這裏最核心的就是2,3步,很是慶幸有https://github.com/buzzfeed/libgif-js 這個庫,才得以實現後面的步驟;java
因爲是公司項目就不展現界面和完整代碼,只放關鍵代碼:git
import { SuperGif } from './libgif.js'
// 判斷文件格式並展現的函數 pre_upload() { // 點擊上傳按鈕觸發彈出文件選擇框 const input = document.createElement('input'); input.setAttribute('type', 'file'); // 注意要設置多選屬性 input.setAttribute('multiple', 'true'); input.addEventListener('change', (e) => { this.img_list = []; this.can_upload = true; this.qiniu_url_list = []; // 判斷是gif格式則交給this.pre_load_gif函數處理 if (/(image\/gif)/.test(e.path[0].files[0].type)) { this.pre_load_gif(e.path[0].files[0]) return; } // 若是是上傳多張靜態的png、jpg圖片則直接轉換成baseURL var img_list = []; for(let i=0,item; item = e.path[0].files[i]; i++) { if (!/(image\/png)|(image\/jp(e?)g)/.test(item.type)) { alert('請上傳jpg、png格式的圖片') return; } img_list.push({ file_name: item.name, url: URL.createObjectURL(item), file: item, }) } this.img_list = img_list }); input.click(); },
dataURLtoFile(dataurl, filename) { const arr = dataurl.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bstr = atob(arr[1]); var n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, {type:mime}); }, // 將canvas轉換成file對象 convertCanvasToImage(canvas, filename) { return this.dataURLtoFile(canvas.toDataURL('image/png'), filename); }, pre_load_gif(gif_source) { var img_list = []; const gifImg = document.createElement('img'); // gif庫須要img標籤配置下面兩個屬性 gifImg.setAttribute('rel:animated_src', URL.createObjectURL(gif_source)) gifImg.setAttribute('rel:auto_play', '0') // 新建gif實例 var rub = new SuperGif({ gif: gifImg } ); rub.load(() => { var img_list = []; for (let i=1; i <= rub.get_length(); i++) { // 遍歷gif實例的每一幀 rub.move_to(i); // 將每一幀的canvas轉換成file對象 let cur_file = this.convertCanvasToImage(rub.get_canvas(), gif_source.name.replace('.gif', '') + `-${i}`) img_list.push({ file_name: cur_file.name, url: URL.createObjectURL(cur_file), file: cur_file, }) } this.img_list = img_list }); },
至此,核心功能基本實現,上面的函數已經將gif分解成多張圖片存放在this.img_list 這個數組裏面。github
接下來只要拿img_list數組裏的file對象上傳到服務器便可。canvas
上傳方式各不相同,這裏就不放具體代碼了,須要注意的是,圖片上傳是異步操做,多圖上傳須要得知全部的圖片所有上傳成功才能肯定上傳完成,因此若是上傳的函數返回的是promise對象,則能夠直接用Promise.all
函數便可得知全部圖片上傳完畢的回調。數組