需求是編寫一個頭像剪裁工具再封裝成為一個元件,然後根據功能開始逐步編寫程式碼:先是上傳圖片 => 預覽圖片 => 編輯圖片。
剛開始沒有去考慮相容性的問題,直接編寫upload部分的程式碼,參考了很多程式碼還有HTML5 FILE API之後,發現很少有React編寫的這樣的程式碼,因為想簡單一點,所以直接就使用
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:
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上的方案,綜合了一下。
程式碼如下:
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`));