
canvas 元素默认被网格所覆盖。通常来说网格中的一个单元相当于 canvas 元素中的一像素。栅格的起点为左上角(坐标为(0,0))。所有元素的位置都相对于原点定位。canvas 宽度 * 高度 就是它的像素点数。
可以通过 getImageData() 方法来取得所有的像素点的 RGBA 数据
返回值是 Uint8ClampedArray 类型的一维数组,包含着 RGBA 格式的整型数据,范围在 0 至 255 之间(包括 255)。
有了像素点数据就可以实现一些有趣的事情
// 取色
const handleClick = (event:any) => {
const x = event.offsetX;
const y = event.offsetY;
const { data } = ctx.getImageData(x, y, 1, 1);
const rgb = `rgb(${data[0]}, ${data[1]}, ${data[2]})`;
setTargetColor(rgb);
}
canvas.addEventListener("click", handleClick);
// 颜色替换
const { width, height } = canvas1;
const [tr, tg, tb] = colorStringToArray(targetColor);
const [rr, rg, rb] = colorStringToArray(replaceColor);
for (let h = 0; h < height; h += 1) {
for (let w = 0; w < width; w += 1) {
const position = (width * h + w) * 4;
let r: number = imageData[position];
let g: number = imageData[position + 1];
let b: number = imageData[position + 2];
let a: number = imageData[position + 3];
if (
Math.abs(r - tr) <= tolerance &&
Math.abs(g - tg) <= tolerance &&
Math.abs(b - tb) <= tolerance
) {
r = rr;
g = rg;
b = rb;
}
ctx1.fillStyle = `rgba(${r},${g},${b},${a})`;
ctx1.fillRect(w, h, 1, 1);
}
}
效果

const { width, height } = canvas1;
for (let h = 0; h < height; h += gap) {
for (let w = 0; w < width; w += gap) {
const position = (width * h + w) * 4 * gap;
const r = imageData[position];
const g = imageData[position + 1];
const b = imageData[position + 2];
ctx1.fillStyle = `rgb(${r},${g},${b})`;
ctx1.fillRect(w * gap, h * gap, gap * gap, gap * gap);
}
}
效果

反相
const { width, height } = canvas1;
for (let h = 0; h < height; h += 1) {
for (let w = 0; w < width; w += 1) {
const position = (width * h + w) * 4;
const r = imageData[position];
const g = imageData[position + 1];
const b = imageData[position + 2];
ctx1.fillStyle = `rgb(${255 - r},${255 - g},${255 - b})`;
ctx1.fillRect(w, h, 1, 1);
}
}
效果

黑白
const { width, height } = canvas1;
for (let h = 0; h < height; h += 1) {
for (let w = 0; w < width; w += 1) {
const position = (width * h + w) * 4;
const r = imageData[position];
const g = imageData[position + 1];
const b = imageData[position + 2];
const avg = (r + g + b) / 3;
const color = avg < threshold ? 0 : 255;
ctx1.fillStyle = `rgb(${color},${color},${color})`;
ctx1.fillRect(w, h, 1, 1);
}
}
效果

灰度
const { width, height } = canvas1;
for (let h = 0; h < height; h += 1) {
for (let w = 0; w < width; w += 1) {
const position = (width * h + w) * 4;
const r = imageData[position];
const g = imageData[position + 1];
const b = imageData[position + 2];
const avg = (r + g + b) / 3;
ctx1.fillStyle = `rgb(${avg},${avg},${avg})`;
ctx1.fillRect(w, h, 1, 1);
}
}
效果
