Canvas 图像处理之 getImageData
我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
<canvas>
元素用于生成图像。它本身就像一个画布,JavaScript 通过操作它的 API,在上面生成图像。它的底层是一个个像素,基本上<canvas>
是一个可以用 JavaScript 操作的位图(bitmap)。
getImageData()
方法用来读取<canvas>
的内容,返回一个 ImageData 对象,包含了每个像素的信息,语法如下:
ctx.getImageData(sx, sy, sw, sh)
接受四个参数,分别是 sx
和sy
是读取区域的左上角坐标,sw
和sh
是读取区域的宽度和高度。
getImageData()
返回的是一个ImageData
对象,有三个属性:
ImageData.data
:一个一维数组。该数组的值,依次是每个像素的红、绿、蓝、alpha
通道值(每个值的范围是0~255
),因此该数组的长度等于图像的像素宽度 x 图像的像素高度 x 4
。这个数组不仅可读,而且可写,因此通过操作这个数组,就可以达到操作图像的目的。ImageData.width
:浮点数,表示 ImageData 的像素宽度。ImageData.height
:浮点数,表示 ImageData 的像素高度。
兔年祝福粒子效果
在过几天将迎来兔年,提前祝大家兔飞猛进!具体的步骤是编写HTML、CSS和JavaScript。使用 getImageData()
方法扫描图像获取像素信息,计算每个区域的相对亮度,创建一个简单的粒子系统,并根据粒子当前移动区域的亮度调整每个粒子的速度和不透明度。
这里使用的素材是一个很可爱的兔子形象,很生动。
颜色选择器
将在画布上绘制所有颜色。首先,需要添加一个画布标签来绘制颜色。将以下 HTML 添加到您的 HTML 中。
<div class="container">
<h1>颜色选择器:Color Picker</h1>
</div>
<div class="container">
<div class="color-picker"></div>
</div>
接下来,需要在画布上绘制所有颜色。要在画布上绘制颜色,需要获取画布的 context
、width
和 height
。这些变量将用于创建线性渐变和绘制矩形框。
1. 获取画布的 context、width、height
const [width, height] = [container.offsetWidth, container.offsetHeight];
[canvas.width, canvas.height] = [width, height];
2. 涂红、绿、蓝
在这里绘制没有透明度的颜色。例如红色,绿色,蓝色。下面是在一个框中绘制所有颜色的 Javascript 代码。
const gradientH = context.createLinearGradient(0, 0, width, 0);
gradientH.addColorStop(0, "rgb(255, 0, 0)"); // red
gradientH.addColorStop(1/6, "rgb(255, 255, 0)"); // yellow
gradientH.addColorStop(2/6, "rgb(0, 255, 0)"); // green
gradientH.addColorStop(3/6, "rgb(0, 255, 255)");
gradientH.addColorStop(4/6, "rgb(0, 0, 255)"); // blue
gradientH.addColorStop(5/6, "rgb(255, 0, 255)");
gradientH.addColorStop(1, "rgb(255, 0, 0)"); // red
context.fillStyle = gradientH;
context.fillRect(0, 0, width, height);
3.滤镜画布与线性梯度
接下来,会发现浅色和深色。例如,浅红色,深红色。为此将使用带有透明度的白色和黑色。这是使它变暗或变亮的 Javascript 代码。
const gradientV = context.createLinearGradient(0, 0, 0, height);
gradientV.addColorStop(0, "rgba(255, 255, 255, 1)"); // white
gradientV.addColorStop(0.5, "rgba(255, 255, 255, 0)");
gradientV.addColorStop(0.5, "rgba(0, 0, 0, 0)"); // transparent
gradientV.addColorStop(1, "rgba(0, 0, 0, 1)"); // black
context.fillStyle = gradientV;
context.fillRect(0, 0, width, height);
最后,当点击画布时,需要点击颜色。这里使用的技术是定位鼠标单击事件的 x/y
位置。然后,在 x/y
位置使用 getImageData
函数获取该位置的红色、绿色和蓝色值。
canvas.addEventListener('click', e => pickColor(e, canvas, circle, selected));
function pickColor(event, canvas, circle, selected) {
const rect = event.target.getBoundingClientRect();
const x = event.clientX - rect.left;
const y = event.clientY - rect.top;
const context = canvas.getContext('2d');
const imgData = context.getImageData(x, y, 1, 1);
const [r, g, b] = imgData.data;
const [h, s, l] = rgb2hsl(r, g, b);
const selectedColor = l < 0.5 ? '#FFF' : '#000';
circle.style.top = (y - 6) + 'px';
circle.style.left = (x - 6) + 'px';
circle.style.borderColor = selectedColor;
selected.innerText = Object.values(toCss(r,g,b,h,s,l))
.toString().replace(/\)\,/g, ') ');
selected.style.backgroundColor = toCss(r,g,b,h,s,l).hex;
selected.style.color = selectedColor;
canvas.dispatchEvent(new CustomEvent('color-selected', {
bubbles: true, detail: {r, g, b, h, s, l}
}));
}
完整代码如下:
总结
getImageData
常用的场景就是制作颜色选择器、像素粒子效果和图片的灰度。
转载自:https://juejin.cn/post/7189645395638059045