圖片資源存儲在本地時默認沒有域名,而canvas的getImageData方法受同源策略限制,使用getImageData處理本地圖片時瀏覽器會判定爲跨域而報錯。
解決方法:
使用FileReader對象的readAsDataURL讀取指定的Blob中的內容,讀取完成後,FileReader對象的result屬性中將包含一個data: URL格式的Base64字符串以表示所讀取文件的內容。將result賦值給Image對象的src然後加載到canvas上就能使用getImageData對圖像進行操作。
核心代碼:
document.querySelector("#File").onchange = function(){
var Reader = new FileReader(); // 創建文件讀取對象
Reader.readAsDataURL(this.files[0]); //讀取Blob,獲取DataURL
Reader.onload = function(){
let img = new Image();
img.src = Reader.result; //將result賦值給Image對象的src
img.onload = function(){
cxt.drawImage(img,0,0,canvas.width,canvas.height);
let imageData = cxt.getImageData(0,0,canvas.width,canvas.height);
console.log(imageData);
}
}
}
示例代碼
<!DOCTYPE html>
<html>
<head>
<title>圖像濾鏡</title>
<meta charset="utf-8">
<style type="text/css">
main{
width: 1400px;
margin: 0 auto;
}
canvas{
box-shadow: 0 0 5px gray;
display: inline-block;
margin-left: 50px;
}
</style>
</head>
<body>
<main>
<canvas id="mycanvas" width="400" height="250"></canvas>
<canvas id="filter" width="400" height="250"></canvas>
<form style="margin: 20px 0 0 42px">
上傳本地圖片:<input type="file" id="File" name="file"/><br/>
</form>
</main>
<script type="text/javascript">
let canvas = document.getElementById('mycanvas');
let cxt = canvas.getContext("2d");
let filter = document.getElementById('filter');
let filter_cxt = filter.getContext("2d");
window.onload = function(){
document.querySelector("#File").onchange=function(){
var Reader=new FileReader();
Reader.readAsDataURL(this.files[0]);
Reader.onload=function(){
let img = new Image();
img.src = Reader.result;
img.onload = function(){
cxt.drawImage(img,0,0,canvas.width,canvas.height);
let imageData = cxt.getImageData(0,0,canvas.width,canvas.height);
console.log(imageData);
let data = imageData.data;
for(let i=0;i<data.length;i+=4){
let grayscale = data[i]*0.3+data[i+1]*0.6+data[i+2]*0.1;
data[i] = grayscale;
data[i+1] = grayscale;
data[i+2] = grayscale;
}
filter_cxt.putImageData(imageData,0,0);
cxt.font = "20px Calibri";
cxt.fillText("原圖",10,30);
filter_cxt.font = "20px Calibri";
filter_cxt.fillStyle = "white";
filter_cxt.fillText("黑白",10,30);
}
}
}
}
</script>
</body>
</html>
效果圖: