在本文中,将简单介绍 <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 函数获取该位置的红色、绿色和蓝色值。 ini 复制代码 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
常用的场景就是制作颜色选择器、像素粒子效果和图片的灰度。