主要的实现就是将图片中你选中的颜色及其周围相似的颜色更换为你选择好的颜色。
原始图:
结果图:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
canvas {
border: 1px solid black;
}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
<br>
<label>新颜色: </label>
<input type="color" id="colorPicker">
<button id="btn">保存</button>
<script>
const btn = document.querySelector('#btn');
btn.addEventListener('click',e=>{
const imageURL = cvs.toDataURL('image/png');
const link = document.createElement('a');
link.href = imageURL;
link.download = 'canvas-image.png';
link.click();
})
const cvs = document.querySelector('canvas');
const ctx = cvs.getContext('2d',{
willReadFrequently:true,
});
const inpColor = document.querySelector('#colorPicker');
function points2Index(x,y) {
return (y*cvs.width+x)*4;
}
function hex2RGBA(hex) {
const r = parseInt(hex.slice(1,3),16);
const g = parseInt(hex.slice(3,5),16);
const b = parseInt(hex.slice(5,7),16);
return [r,g,b,255]
}
function init(){
const img = new Image();
img.crossOrigin = "Anonymous"; // 设置为跨域模式
img.onload = () =>{
cvs.width = img.width;
cvs.height = img.height;
ctx.drawImage(img,0,0);
}
img.src = 'https://inews.gtimg.com/om_bt/OE8piEBa-tbqn-wNvWZl8coi4AlzoUD43upEkoAnIkYL8AA/641';
}
init();
function getColor(x,y,cvsColors) {
const index = points2Index(x,y);
return cvsColors.slice(index,index+4);
}
function diff(color1,color2) {
return (
Math.abs(color1[0]-color2[0])+
Math.abs(color1[1]-color2[1])+
Math.abs(color1[2]-color2[2])+
Math.abs(color1[3]-color2[3])
);
}
cvs.addEventListener('click', e =>{
const clickX = e.offsetX;
const clickY = e.offsetY;
const imgData = ctx.getImageData(0,0,cvs.width,cvs.height);// 获取真个画布的颜色RGBA模式
const cvsColors = imgData.data;
const hex = inpColor.value;
const targetColor = hex2RGBA(hex);
const originColor = getColor(clickX,clickY,cvsColors);
changeColor(clickX,clickY,cvsColors,targetColor,originColor,imgData);
ctx.putImageData(imgData,0,0);
})
function changeColor(x,y,cvsColors,targetColor,originColor,imgData) {
// if(x<0||x>=cvs.width || y<0||y>=cvs.height){
// return;
// }
// const curColor = getColor(x,y,cvsColors);
// if(diff(curColor,targetColor)===0){
// return;
// }
// if(diff(curColor,originColor)>50){
// return;
// }
// const index = points2Index(x,y);
// cvsColors.set(targetColor,index);
// changeColor(x-1,y,cvsColors,targetColor,originColor);
// changeColor(x+1,y,cvsColors,targetColor,originColor);
// changeColor(x,y-1,cvsColors,targetColor,originColor);
// changeColor(x,y+1,cvsColors,targetColor,originColor);
const stack = [[x, y]];
function _changeColor(x,y) {
const i = points2Index(x,y);
const color = getColor(x,y,cvsColors);
if(x<0||x>=cvs.width || y<0||y>=cvs.height){
return;
}
if(diff(color,targetColor)===0){
return;
}
if(diff(color,originColor)>50){
return;
}
cvsColors.set(targetColor,i);
stack.push([x-1,y],[x+1,y],[x,y-1],[x,y+1]);
}
while (stack.length > 0) {
const [cx, cy] = stack.pop(); // 弹出栈顶元素
_changeColor(cx, cy); // 处理该点的颜色
}
ctx.putImageData(imgData,0,0);
}
</script>
</body>
</html>