需求是編寫一個頭像剪裁工具再封裝成爲一個組件,而後根據功能開始逐步編寫代碼:先是上傳圖片 => 預覽圖片 => 編輯圖片。react
剛開始沒有去考慮兼容性的問題,直接編寫upload部分的代碼,參考了不少代碼還有HTML5 FILE API以後,發現不多有React編寫的這樣的代碼,由於想簡單一點,因此直接就使用canvas
let file = e.target.files[0]; let url = window.URL.createObjectURL(file); console.info(url); 打印出來的結果是: blob:http://localhost:3001/396d3dbb-be52-4fd4-aaf9-50c0c04ecef9
這個是個DOMString類型的返回值,根據MDN:dom
A DOMString containing an object URL that can be used to reference the contents of the specified source object.
而後我想使用canvas去加載這個文件再對這個文件作裁剪的操做,問題就來了,ctx.drawImage(img)不能直接去解析到這個DOMString再加載出來,後來網上發現確實要先轉化成dataURL才能被正常加載,而後就一直嘗試這樣的方案:工具
reader.readAsDataURL(file); 會報錯: Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob
沒法被FileReader.readAsDataURL()順利轉換,最後看了些stackoverflow上的方案,綜合了一下。
代碼以下:this
import React from 'react'; import ReactDOM from 'react-dom'; class App extends React.Component{ constructor(props){ super(props); this.handleChange = this.handleChange.bind(this); } handleChange(e){ console.info(url); if (window.FileReader){ console.info("Support file reader"); let file = e.target.files[0]; let reader = new FileReader(); let img = new Image(); if(file && file.type.match('image.*')){ reader.readAsDataURL(file); }else{ console.info('Not match!') } reader.onload = e => { let ctx = this.canvas.getContext('2d'); img.src = reader.result; ctx.drawImage(img,10,10); } } } render(){ return <div> <input type="file" multiple onChange={this.handleChange}/> <canvas width="500px" height="500px" style={{border:"solid 1px lightgrey"}} ref={canvas=>this.canvas = canvas}/> </div> } } ReactDOM.render(<App/>,document.getElementById('root'));