Javascript 画布整体填充未填充到边缘
我正在使用泛洪填充算法来填充画布上绘制的圆圈。我遇到的问题是算法没有填充到圆的边缘 以下是基于以下内容的算法: 我认为这可能与以下事实有关:圆圈没有填充颜色,画布的背景不是白色,而是透明的黑色。我尝试将画布背景更改为白色,但也没有效果。使用泛光填充创建遮罩 前几天我碰巧做了一次泛光填充,解决了抗锯齿边的问题 我没有直接绘制画布,而是绘制一个字节数组,然后用于创建掩码。遮罩允许设置alpha值 填充可以有Javascript 画布整体填充未填充到边缘,javascript,html,canvas,flood-fill,Javascript,Html,Canvas,Flood Fill,我正在使用泛洪填充算法来填充画布上绘制的圆圈。我遇到的问题是算法没有填充到圆的边缘 以下是基于以下内容的算法: 我认为这可能与以下事实有关:圆圈没有填充颜色,画布的背景不是白色,而是透明的黑色。我尝试将画布背景更改为白色,但也没有效果。使用泛光填充创建遮罩 前几天我碰巧做了一次泛光填充,解决了抗锯齿边的问题 我没有直接绘制画布,而是绘制一个字节数组,然后用于创建掩码。遮罩允许设置alpha值 填充可以有公差和公差褪色,控制如何处理接近公差值的颜色 当起始颜色和公差之间的像素差大于(公差-公差淡入
公差
和公差褪色
,控制如何处理接近公差值的颜色
当起始颜色和公差之间的像素差大于(公差-公差淡入度)
时,我将该像素的alpha设置为255-((差异-(公差-公差淡入度))/tolerance fade)*255
,这将在线条边缘创建一个良好的平滑混合。虽然它并不适用于所有高对比度情况,但它是一种有效的解决方案
下面的示例显示了使用和不使用公差Fade
的结果。蓝色不带公差衰减
,红色带公差
设置为190,公差衰减设置为90
您将不得不对设置进行调整,以获得满足您需求的最佳结果
函数showExample(){
var canvas=document.createElement(“canvas”);
画布宽度=200;
画布高度=200;
var ctx=canvas.getContext(“2d”);
document.body.appendChild(画布);
ctx.fillStyle=“白色”
ctx.fillRect(0,0,canvas.width,canvas.height)
ctx.lineWidth=4;
ctx.strokeStyle=“黑色”
ctx.beginPath();
ctx.arc(100100,90,0,数学PI*2);
ctx.arc(120100,60,0,数学PI*2);
ctx.stroke();
ctx.fillStyle=“蓝色”;
洪水填充。填充(100100,1,ctx)
ctx.fillStyle=“红色”;
洪水填充。填充(40100190,ctx,空,空,90)
}
//洪水从https://github.com/blindman67/FloodFill2D
var floodFill=(函数(){
“严格使用”;
常数范围={
排名:0,
左:0,,
底部:0,
右:0,,
}
var keepMask=false;//如果为true,则填充区域的掩码将作为画布图像返回
var extentOnly=false;//如果为true,则返回填充范围
var copyPixels=false;//如果为true,则创建填充像素的副本
var cutPixels=false;//如果为true和copyPixels为true,则删除填充的像素
var useBoundingColor=false;//设置要填充的颜色。不会填充此颜色
var useCompareColor=false;//posY使用CompareColour而不是在posX处获取像素
变量红、绿、蓝、阿尔法;//如果需要,比较颜色
var画布,ctx;
功能泛光填充(posX、posY、公差、上下文2D、对角线、面积、公差衰减){
变量w、h、涂漆、x、y、ind、sr、sg、sb、sa、imgData、数据、数据32、RGBA32、堆栈、堆栈位置、左看、右看、i、colImgDat、差异、检查颜色;
容差衰减=容差衰减!==未定义和容差衰减!==空?容差衰减:0;
对角线=对角线!==未定义和对角线!==空?对角线:假;
面积=面积!==未定义和面积!==空?面积:{};
面积.x=面积.x!==未定义?面积.x:0;
area.y=area.y!==未定义?area.y:0;
area.w=area.w!==未定义?area.w:context2D.canvas.width-area.x;
area.h=area.h!==未定义?area.h:context2D.canvas.height-area.y;
//兽医区在画布上。
如果(面积x<0){
面积.w=面积.x+面积.w;
面积x=0;
}
if(面积y<0){
面积.h=面积.y+面积.h;
面积y=0;
}
if(area.x>=context2D.canvas.width | | area.y>=context2D.canvas.height){
返回false;
}
if(area.x+area.w>context2D.canvas.width){
area.w=context2D.canvas.width-area.x;
}
if(area.y+area.h>context2D.canvas.height){
area.h=context2D.canvas.height-area.y;
}
如果(面积w=h){
return false;//填充起始区域以外的区域。不要执行任何操作
}
如果(公差===255&&toleranceFade==0&&!keepMask){//fill all
如果(扩展){
extent.left=area.x;//设置区段
范围右=面积x+w;
extent.top=面积.y;
范围.bottom=面积.y+h;
}
context2D.fillRect(区域x,区域y,w,h);
返回true;
}
如果(公差衰减>0){//如果启用,则添加一个,以获得正确的步数
公差衰减+=1;
}
imgData=context2D.getImageData(area.x、area.y、area.w、area.h);
data=imgData.data;//要填充的图像数据;
data32=新的uint32阵列(data.buffer);
painted=new-uint8clampedaray(w*h);//用于标记绘制区域的字节数组;
函数checkColorAll(ind){
如果(ind<0 | |绘制[ind]>0){//测试边界
返回false;
}
var ind4=ind公差){
返回false;
}
返回真值
}
//检查边界颜色
函数checkColorBound(ind){
如果(ind<0 | |绘制[ind]>0){//测试边界
返回false;
}
var ind4=ind0){//测试边界
返回false;
}
var ind4=ind公差){
返回false;
}
function paintLocation(startX, startY, r, g, b) {
var colorLayer = context1.getImageData(0, 0, canvasWidth, canvasHeight);
pixelPos = (startY * canvasWidth + startX) * 4;
startR = colorLayer.data[pixelPos];
startG = colorLayer.data[pixelPos + 1];
startB = colorLayer.data[pixelPos + 2];
var pixelStack = [
[startX, startY]
];
var drawingBoundTop = 0;
while (pixelStack.length) {
var newPos, x, y, pixelPos, reachLeft, reachRight;
newPos = pixelStack.pop();
x = newPos[0];
y = newPos[1];
pixelPos = (y * canvasWidth + x) * 4;
while (y-- >= drawingBoundTop && matchStartColor(colorLayer, pixelPos, startR, startG, startB)) {
pixelPos -= canvasWidth * 4;
}
pixelPos += canvasWidth * 4;
++y;
reachLeft = false;
reachRight = false;
while (y++ < canvasHeight - 1 && matchStartColor(colorLayer, pixelPos, startR, startG, startB)) {
colorPixel(colorLayer, pixelPos, r, g, b);
if (x > 0) {
if (matchStartColor(colorLayer, pixelPos - 4, startR, startG, startB)) {
if (!reachLeft) {
pixelStack.push([x - 1, y]);
reachLeft = true;
}
} else if (reachLeft) {
reachLeft = false;
}
}
if (x < canvasWidth - 1) {
if (matchStartColor(colorLayer, pixelPos + 4, startR, startG, startB)) {
if (!reachRight) {
pixelStack.push([x + 1, y]);
reachRight = true;
}
} else if (reachRight) {
reachRight = false;
}
}
pixelPos += canvasWidth * 4;
}
}
context1.putImageData(colorLayer, 0, 0);
}
function matchStartColor(colorLayer, pixelPos, startR, startG, startB) {
var r = colorLayer.data[pixelPos];
var g = colorLayer.data[pixelPos + 1];
var b = colorLayer.data[pixelPos + 2];
return (r == startR && g == startG && b == startB);
}