&引用;“铲斗加注”;Javascript或coffeescript中的算法
我正在编写一个小coffeescript/js应用程序,允许用户设计图标(16x16像素或32X32像素)。 图标实际上是一个带有彩色单元格的二维数组。单元格可以有颜色,也可以为空 我希望用户能够用“桶油漆”工具填充空白单元格 意思是&引用;“铲斗加注”;Javascript或coffeescript中的算法,javascript,coffeescript,Javascript,Coffeescript,我正在编写一个小coffeescript/js应用程序,允许用户设计图标(16x16像素或32X32像素)。 图标实际上是一个带有彩色单元格的二维数组。单元格可以有颜色,也可以为空 我希望用户能够用“桶油漆”工具填充空白单元格 意思是 如果用户单击空白单元格,则单击的单元格旁边的所有空白单元格都将填充choosen颜色,直到它到达彩色单元格为止 >P>如果用户点击一个彩色单元格,所有与单击的单元格相邻的共享相同颜色的单元格将被填充,但不是空白的,也不是彩色的(具有另一种颜色)。 该应用程序
- 如果用户单击空白单元格,则单击的单元格旁边的所有空白单元格都将填充choosen颜色,直到它到达彩色单元格为止
(注:我不使用html画布绘制)因为这只是16x16或32x32,所以您可以使用递归解决方案: 假设您的起点是将像素x/y从颜色A更改为颜色B(A或B可以为空) 在伪代码中:
function floodfill(x,y,A,B) {
if ((x<0) || (x>15) || (y<0) || (y>15)) return;
if (get_color(x,y)!=A) return;
set_color(x,y,B);
floodfill(x-1,y-1,A,B);
floodfill(x-1,y,A,B);
floodfill(x-1,y+1,A,B);
floodfill(x,y-1,A,B);
floodfill(x,y+1,A,B);
floodfill(x+1,y-1,A,B);
floodfill(x+1,y,A,B);
floodfill(x+1,y+1,A,B);
}
功能泛洪填充(x、y、A、B){
如果((x15)|(y15))返回;
如果(获取颜色(x,y)!=A)返回;
设置颜色(x,y,B);
漫灌(x-1、y-1、A、B);
漫灌(x-1、y、A、B);
洪水填充(x-1,y+1,A,B);
漫灌(x、y-1、A、B);
漫灌(x,y+1,A,B);
漫灌(x+1,y-1,A,B);
漫灌(x+1,y,A,B);
洪水填充(x+1,y+1,A,B);
}
我不完全确定您在寻找哪种类型的建议,但您应该看看泛洪填充算法
在维基百科上:好吧,下面是我如何用咖啡脚本解决我的问题。 这是一个使用canvas的示例。 脚本应该在任何有canvas元素且id为canvas的页面上运行,由于stackoverflow问题,我不得不创建自己的堆栈
log = ->
console.log arguments
class Point
constructor:(@x,@y)->
class BucketFiller
MAXITERATION:100000
factor:1
fill : (ctx,pixel, colCible, colRep)->
P = []
max = @MAXITERATION
if @getColorAtPixel(ctx,pixel)!=colCible then return null
P.push(pixel)
while P.length > 0 and max >=0
--max
currentpixel = P.pop()
@fillRect(ctx,currentpixel.x,currentpixel.y,@factor,@factor,colRep)
if @isInCanvas(ctx,currentpixel)
if @getColorAtPixel(ctx,@up(currentpixel)) == colCible then P.push(@up(currentpixel))
if @getColorAtPixel(ctx,@down(currentpixel)) == colCible then P.push(@down(currentpixel))
if @getColorAtPixel(ctx,@right(currentpixel)) == colCible then P.push(@right(currentpixel))
if @getColorAtPixel(ctx,@left(currentpixel)) == colCible then P.push(@left(currentpixel))
return
fillRect:(ctx,x,y,width,height,color)->
ctx.fillStyle = color
ctx.fillRect(x,y,width,height)
return
down :(pixel)->
return {x:pixel.x,y:pixel.y-@factor}
up:(pixel)->
return {x:pixel.x,y:pixel.y+@factor}
right :(pixel)->
return {x:pixel.x+@factor,y:pixel.y}
left :(pixel)->
return {x:pixel.x-@factor,y:pixel.y}
getColorAtPixel:(ctx,pixel)->
try
imageData = ctx.getImageData(pixel.x,pixel.y,1,1)
catch e
return null
return @rgbArrayToCssColorString(imageData.data)
rgbArrayToCssColorString:(array)->
result = "rgb(#{array[0]},#{array[1]},#{array[2]})"
return result
isInCanvas : (ctx,pixel)->
result = ((0 <= pixel.x <= ctx.canvas.width) and (0 <= pixel.y <= ctx.canvas.height))
return result
main=->
buckfiller = new BucketFiller()
log("start")
canvas = document.getElementById("canvas")
ctx = canvas.getContext("2d")
penPosition = new Point(2,10)
fillColor = "rgb(255,0,0)"
colCible = buckfiller.getColorAtPixel(ctx,penPosition)
try
buckfiller.fill(ctx,penPosition,colCible,fillColor)
catch e
log e
window.onload=->
main()
log=->
console.log参数
类点
构造函数:(@x,@y)->
木桶填料
最大迭代次数:100000
系数:1
填充:(ctx、像素、colCible、colRep)->
P=[]
max=@MAXITERATION
如果@getColorAtPixel(ctx,pixel)=colCible然后返回null
P.push(像素)
当P.length>0且max>=0时
--马克斯
currentpixel=P.pop()
@fillRect(ctx,currentpixel.x,currentpixel.y,@factor,@factor,colRep)
如果@isInCanvas(ctx,currentpixel)
如果@getColorAtPixel(ctx,@up(currentpixel))==colCible,则P.push(@up(currentpixel))
如果@getColorAtPixel(ctx,@down(currentpixel))==colCible,则P.push(@down(currentpixel))
如果@getColorAtPixel(ctx,@right(currentpixel))==colCible,则P.push(@right(currentpixel))
如果@getColorAtPixel(ctx,@left(currentpixel))==colCible,则P.push(@left(currentpixel))
返回
fillRect:(ctx、x、y、宽度、高度、颜色)->
ctx.fillStyle=颜色
ctx.fillRect(x,y,宽度,高度)
返回
向下:(像素)->
返回{x:pixel.x,y:pixel.y-@factor}
向上:(像素)->
返回{x:pixel.x,y:pixel.y+@factor}
右:(像素)->
返回{x:pixel.x+@因子,y:pixel.y}
左:(像素)->
返回{x:pixel.x-@因子,y:pixel.y}
getColorAtPixel:(ctx,pixel)->
尝试
imageData=ctx.getImageData(pixel.x,pixel.y,1,1)
抓住e
返回空
return@rgbArrayToCssColorString(imageData.data)
rgbArrayToCssColorString:(数组)->
result=“rgb(#{array[0]},#{array[1]},#{array[2]})”
返回结果
isInCanvas:(ctx,像素)->
结果=((0)为了让事情更清楚,你可以这样称呼它:floodfill(clickX,clickY,originalColor,fillColor)
。大概你有一些识别颜色的方法(包括空的),以及一些填充单个像素的方法,这些像素将取代设置颜色
,因此它基本上应该是一个简单的解决方案。很好,链接,谢谢,我不知道该算法有一个名称。