考虑现实中的油漆桶,填充一个方形区域,是从一点开始,填充整个区域,碰到边界就停止。很明显,要遍历整个区域,碰到边界就停止,问题是这里的边界怎么判断?从使用角度看,使用油漆桶,油漆桶有一个颜色,然后在canvas画布上点击,点击的点(目标点,startPixel)也有一个颜色,就是要使用油漆桶的颜色填充这个目标点,及其相邻的区域,考虑到canvas画布是一个网格,需要从目标点遍历整个网格,而边界就是相邻的点的颜色不是目标点的颜色。
为什么不使用递归遍历整个网格?测试会报错:Maximum call stack size exceeded。
// 这里包含了一种 newColor==oldColor 的特殊情况。 _floodFillWithQueue(imageData, queue, newColor, oldColor) { let color, pixel; while ((pixel = queue.pop())) { color = this._rgbFromImageDataWithPixel(imageData, pixel.x, pixel.y); if (this._compareColor(color, oldColor) && !this._compareColor(color, newColor)) { this._setColor4ImageDataWithPixel(imageData, pixel.x, pixel.y, newColor); if (pixel.x > 0) queue.push({ x: pixel.x - 1, y: pixel.y }); if (pixel.x < imageData.width - 1) queue.push({ x: pixel.x + 1, y: pixel.y }); if (pixel.y > 0) queue.push({ x: pixel.x, y: pixel.y - 1 }); if (pixel.y < imageData.height - 1) queue.push({ x: pixel.x, y: pixel.y + 1 }); } } }
需要注意canvas画布上点坐标的获得,这需要的是canvas绘图表面的坐标。
// 由于 window.devicePixelRatio 的存在,所以要转化为 canvasEle 上实际的点,即对应imageData中的点 const startPixel = { x: parseInt(this.board.startPoint.x), y: parseInt(this.board.startPoint.y) };
使用1像素的离屏canvas转换hsl格式的颜色为rgb格式的颜色。
_2rgb(color) { this.offscreenContext.fillStyle = color; this.offscreenContext.fillRect(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height); const imgDataOffscreenCanvas = this.offscreenContext.getImageData(0, 0, this.offscreenCanvas.width, this.offscreenCanvas.height); return this._rgbFromImageData(imgDataOffscreenCanvas, 0); }
反馈:您觉得本站怎么样?(此评价不会公开,也不会对博主产生任何实际利益。)
- 非常优秀
- 可以
- 一般
- 垃圾
- 超级恶心