整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          利用Canvas壓縮圖片并完成Base64編碼

          項目遷移的過程中,或多或少都會遇到各種兼容性問題。本文是在uniapp項目遷移至微信小程序的業務背景下,講述如何利用Canvas壓縮圖片并完成Base64編碼。

          這兩種環境下,在實現上傳圖片的功能時,都會用到的一個API就是chooseImage,那么,對比一下uni.chooseImagewx.chooseImage,會發現前者返回的是一個以blob:http開頭的地址,這個地址可以在瀏覽器中訪問到圖片,這里的blob實際上是一個Blob對象;而后者返回的是一個以http://tmp開頭的地址,這個地址可以在微信開發者工具中查看圖片,卻不能在瀏覽器中訪問到圖片,這個地址實際上是微信小程序生成的臨時地址。也就是這個“臨時地址”,導致后續方法在Base64編碼時失敗。

          為什么需要Canvas

          說到上傳圖片,比較容易想到的一個API就是uploadFile,調用這個API需要提供一個服務器地址存儲圖片,那么,在沒有服務器地址的情況下,就用到Canvas了。

          具體實現過程

          References

          [1] https://developer.mozilla.org/zh-CN/docs/Glossary/Base64

          [2] https://developer.mozilla.org/zh-CN/docs/Web/API/Blob

          文簡介

          點贊 + 關注 + 收藏 = 學會了

          前端開發的過程中, 我們經常遇到文件上傳或者圖片上傳的需求, 有些場景中可能還會要求上傳圖片后對圖片進行裁切, 壓縮. 對于不想加班的程序員來說, 第一要義就是使用第三方庫. 雖然像我們熟悉的antd, element等庫提供了上傳組件:

          image.png

          但是這些第三方UI庫一方面體積比較龐大, 不夠輕量, 另一方面不支持裁切, 壓縮等功能, 所以還是需要自己實現或者整合第三方庫實現, 當然 antd 提供了一個圖片裁切的庫 antd-img-crop, 但是使用上極度“難受”(受限), 無法自由裁切圖片, 同時也無法提供壓縮能力:

          image.png

          所以這個方案也直接pass. 最終為了實現想要的效果,我還是決定犧牲自己, 手動實現一個支持上傳裁切并壓縮的組件, 并取名為react-cropper-pro.

          2022-07-16 16.02.04.gif

          react-cropper-pro 使用介紹

          react-cropper-pro是一款簡單輕量的圖片上傳 + 裁切 + 壓縮 組件, 不依賴antd / element等第三方UI, 快速實現圖片處理相關操作, 底層依賴react-cropper.

          安裝

          yarn add react-cropper-pro
          

          使用

          import CropperPro from 'react-cropper-pro';
          
          export default () => 
            <CropperPro 
              defaultImg="" 
              onChange={(file) => console.log(file)} 
              onDel={(image) => console.log('remove', image)} 
            />;
          

          image.png

          API介紹

          image.png

          技術實現

          技術上主要有以下幾個核心點:

          1. 實現文件上傳組件樣式(主要是覆蓋原生input[file]的“純潔UI”)
          2. 實現突圖片裁切
          3. 實現圖片壓縮
          4. 包裝成react組件并發布到npm

          接下來和大家簡單介紹一下實現細節.

          1. 實現文件上傳組件樣式

          image.png

          我們都知道元素的input文件上傳組件采用的默認樣式非常簡陋, 所以我們需要通過某種方式替換原生樣式, 這里和大家分享一下我實現的方式.

          image.png

          其實很簡單, 就是用定位的方式將一個同樣大小的div覆蓋在input上面, 然后把讓div事件穿透, 能響應input的事件即可. 核心代碼如下:

          <div className="xi-cropper-upload">
                    <input type="file" onChange={handleChange} accept="image/gif,image/jpeg,image/jpg,image/png" />
                    <div className="xi-cropper-file">
                    </div>
          </div>
          

          其次就是需要用戶在上傳完圖片之后, 圖片能展示在上傳區域, 如下:

          image.png

          這塊的完整代碼如下:

          <div className="xi-cropper-upload">
                    <input type="file" onChange={handleChange} accept="image/gif,image/jpeg,image/jpg,image/png" />
                    <div className="xi-cropper-file">
                      {
                        cropData ? <img src={cropData} /> : '+'
                      }
                      {
                        !!cropData && <span className="xi-cropper-del" onClick={handleDel}>?</span> 
                      }
                    </div>
                  </div>
          

          2. 實現突圖片裁切

          圖片裁切這里我采用了 react-cropper 這個庫, 雖然不能直接實現圖片上傳, 但是它的圖片裁切能力還是很強大的. 我們需要實現的效果是圖片上傳后會出現上傳彈窗, 顯示裁切區域, 如下:

          2022-07-16 16.02.04.gif

          這里彈窗的實現我采用了React-Dom的createPortal API, 它可以實現彈窗dom掛載在指定的容器上, 很多組件庫的組件比如抽屜, Modal, DropDown都采用了類似的實現原理, 我之前也寫了一篇文章來介紹如何使用 createPortal 的, 感興趣的朋友可以學習參考一下:

          這塊的核心源碼可以參考github倉庫對應的第134行.

          文件路徑如下: https://github.com/MrXujiang/react-cropper-pro/tree/main/src/crop

          3. 實現圖片壓縮

          圖片壓縮這塊主要是基于產品業務場景來設計, 這里我分了4個檔:

          • 不壓縮

          如下:

          image.png

          這一塊主要是利用了canvascropper 的能力, 我們通過控制canvas對象的寬高比例, 和canvas提供的toBlob 來實現圖片的壓縮, 核心代碼如下:

          if (typeof cropper !== "undefined") {
                setCropData(cropper.getCroppedCanvas().toDataURL());
                const rate = 1 / (4 - imgLevel);
                const { width, height } = cropper.getCropBoxData();
                cropper.getCroppedCanvas({
                  width: width * rate,
                  height: height * rate,
                  imageSmoothingQuality: imgLevelValueMap[imgLevel],
                  fillColor: 'transparent',
                }).toBlob((blob: Blob) => {
                  if(blob) {
                    const time = Date.now();
                    let croppedFile:any = new File([blob], fileRef.current.name, {
                      type: fileRef.current.type,
                      lastModified: Date.now(),
                    });
                    croppedFile.uid = time;
                    onChange && onChange(croppedFile)
                  }else {
                    new Error('圖片裁切失敗');
                  }
                  
                }, fileRef.current.type, rate)
              }
          

          當然有關 canvastoBlob API不熟悉的朋友可以移步MDN:

          https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob

          4. 包裝成react組件并發布到npm

          有關如何實現組件庫以及如何優雅發布到NPM公倉的技術我之前在《趣談前端》 也分享過, 感興趣的朋友可以參考一下:

          應用場景

          最后再來看看應用場景, 目前 react-cropper-pro 已經應用于H5-Dooring 可視化搭建平臺中, 來實現圖片更精準的控制:

          image.png

          感興趣的朋友可以體驗一下, 當然還有很多內容平臺, 因為有富文本或者md等編輯器的寫作能力, 所以也會涉及到對圖片的控制, 所以這些都是 react-cropper-pro 的應用領域.

          最后

          開源不易, 歡迎搭建一起共建, 點個 star, 讓生活更美好.


          主站蜘蛛池模板: 国产伦精品一区二区三区无广告| 国产精品主播一区二区| 亚洲AV无码一区二区三区鸳鸯影院| 亚洲欧洲无码一区二区三区| 国模精品一区二区三区| 乱码人妻一区二区三区| 在线播放一区二区| 国产在线一区二区| 国产美女视频一区| AV无码精品一区二区三区宅噜噜| 人妻少妇精品视频三区二区一区 | 无码人妻精品一区二区| 日韩精品无码人妻一区二区三区| 亚无码乱人伦一区二区| 国产主播在线一区| 亚洲欧美日韩中文字幕在线一区| 色窝窝无码一区二区三区色欲| 亚洲一区日韩高清中文字幕亚洲| 精品国产日韩一区三区| 日本无码一区二区三区白峰美| 精品国产一区二区三区色欲| 国产福利91精品一区二区| 亚洲一区二区三区高清视频| 91无码人妻精品一区二区三区L| 熟女精品视频一区二区三区| 精品人伦一区二区三区潘金莲| 亚洲图片一区二区| 天堂va在线高清一区| 精品一区二区ww| 日韩国产一区二区| 国产精品一区12p| 精品一区二区三区四区| 无码av免费一区二区三区试看 | 精品人妻一区二区三区浪潮在线| 国产精品视频一区二区三区四| 无码人妻一区二区三区在线| 精品国产鲁一鲁一区二区| 亚洲熟女综合一区二区三区| 国产伦精品一区二区三区免.费 | 亚洲AV无码一区二区二三区软件| 亚洲国产美国国产综合一区二区|