尝试用一个图像来遮罩另一个图像,然后对结果中的像素颜色进行统计,但统计结果不正确

前端开发 2026-07-09

我用一个黑色圆形作为一个100×100的红色矩形的遮罩,总像素数为10,000。遮罩效果很好,能得到一个漂亮的红色圆形,但当我尝试统计结果中的所有红色像素时,得到的是10,000(原始矩形),而我应该得到一个更小的数值(来自圆形的像素)。

我知道需要把遮罩以某种方式扁平化,我也找到了若干做法的示例,但都不起作用。为了避免在这个示例里把我尝试过的所有方法都堆砌在一起,我就只解释问题,我觉得再多写几行代码就可以解决。

window.addEventListener("load", (event) => {
    console.log("Page is fully loaded");
    init();
});
function init() {
    //var myCanvas = document.querySelector("#myCanvas");
    var redColorCount=0;
    var stage = new createjs.Stage("myCanvas");
    // 1. Create your masked graphic (or container)
    var shape = new createjs.Shape();
    shape.graphics.beginFill("red").drawRect(0, 0, 100, 100);  // Red Square

    var maskShape = new createjs.Shape();
    maskShape.graphics.beginFill("#000").drawCircle(50, 50, 50); //Black Circle for mask
    console.log(maskShape.x);
    shape.mask = maskShape;

    shape.cache(0, 0, 100, 100); 

    var cacheCanvas = shape.cacheCanvas;
    var ctx = cacheCanvas.getContext("2d");
    var imageData = ctx.getImageData(0, 0, 100, 100).data;

    console.log(imageData);
    stage.addChild(shape);
    shape.uncache();
    stage.update();
    console.log("Length: "+imageData.length);
    for (var i = 0; i < imageData.length; i += 4) {
        if ((imageData[i] == 255) && (imageData[i+1] == 0) && (imageData[i+2] == 0)){
            redColorCount++;
        }
    }
    console.log("redColorCount: "+redColorCount);
}
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>
<canvas id="myCanvas" width="500" height="350"></canvas>

解决方案

正如Yogi在注释中所说的,这里不需要 create.js 包装器来实现你想要的效果。 标准的Canvas API就足够了,它的用法就像使用create.js一样简单。

现在,考虑到你正处在一个庞大的代码库中,无法全部改动,并且鉴于我已经对create.js的源代码深入研究过,下面给出一个临时的解决方案。

首先,似乎没有一种简单的方法(一个选项或一个函数调用)可以让 shadowCanvas 应用 mask。对于主画布,遮罩是通过下述方法应用的 shape.updateContext (由 ShapeDisplayObject 继承)在 shape.draw 之前,在清空的画布上被调用。

因此,为了让阴影画布应用遮罩,你需要对它进行操作,超出其作用域:

// ..........
shape.cache(0, 0, 100, 100);
var cacheCanvas = shape.cacheCanvas;
var ctx = cacheCanvas.getContext("2d"); // original code up to here

ctx.clearRect(0, 0, 100, 100);
shape.updateContext(ctx);
shape.updateCache();

var imageData = ctx.getImageData(0, 0, 100, 100).data; // back to original code
// .........

堆栈片段:

window.addEventListener("load", (event) => {
    //console.log("Page is fully loaded");
    init();
});
function init() {
    //var myCanvas = document.querySelector("#myCanvas");
    var redColorCount=0;
    var stage = new createjs.Stage("myCanvas");
    // 1. Create your masked graphic (or container)
    var shape = new createjs.Shape();
    shape.graphics.beginFill("red").drawRect(0, 0, 100, 100);  // Red Square

    var maskShape = new createjs.Shape();
    maskShape.graphics.beginFill("#000").drawCircle(50, 50, 50); //Black Circle for mask
    shape.mask = maskShape;

    shape.cache(0, 0, 100, 100);
    var cacheCanvas = shape.cacheCanvas;
    // document.body.appendChild(cacheCanvas);
    var ctx = cacheCanvas.getContext("2d");

    ctx.clearRect(0, 0, 100, 100);
    shape.updateContext(ctx);
    shape.updateCache();
    var imageData = ctx.getImageData(0, 0, 100, 100).data;

    //console.log(imageData);
    stage.addChild(shape);
    shape.uncache();
    stage.update();
    for (var i = 0; i < imageData.length; i += 4) {
        if ((imageData[i] == 255) && (imageData[i+1] == 0) && (imageData[i+2] == 0) && (imageData[i+3] >= 128)){
            redColorCount++;
        }
    }
    console.log("redColorCount: "+redColorCount+" Length: "+imageData.length);
}
<canvas id="myCanvas" width="200" height="110"></canvas>
<script src="https://code.createjs.com/1.0.0/createjs.min.js"></script>

更新:当然,总有一种办法可以使用主画布从(var ctx = myCanvas.getContext("2d"))获取 ImageData,但那很显然,可能不是你需要的。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章