Question

I'm creating a mobile webapp game that lets the user swipe over the screen to clear it. I am trying to write a smart function that detects when nearly the whole canvas is transparent.

I have an interval that calls the function below each second, to do the check. The way it is supposed to work is that I take a sector of the canvas that is 20px wide, and as tall as the canvas is.

This function should run quite smooth, but for some reason, the getImageData function, returns to many pixels. My sector is always 20px wide and has the same height, so it should return the same amount of pixels each time. Of course, since getImageData returns a higher and higher number, my loop gets slower and slower.

Does anyone know what causes this? have I misunderstood the getImageData function in the way it works?

isCanvasTransparent: function (fromX, toX, currentIteration) {

        if(currentIteration < this.clearedIterations) { // If a sector is already clear, we dont need to check it again
            this.isCanvasTransparent(fromX + 20, toX + 20, currentIteration + 1);
            return;
        } else {
            var data = this.context.getImageData(fromX, 0, toX, parseInt(this.canvas.style.width)).data;
            var counter = 0;
            var i = 0;

            // For some reason, the length increases, but the diff between fromX and toX is always 20
            console.log(data.length); 

            for(i=0;i<(data.length);i+=4) { 
                if(data[i+3]!==0){
                    counter++;
                    // I stop iterating, since there are too many non transparent pixels
                    if(counter > 10) {
                        break;
                    }
                }
            }

            // I accept that 10 pixels in each sector is not transparent
            if((counter < 10) && !this.alerted) {
                this.clearedIterations++; // Here we increase clearedIterations, since this sector is clear

                // There are no more iterations, so we are done
                if(currentIteration === this.maxIterations) {
                     // this is the interval that calls isCanvasTransparent(0, 20, 0)
                     // in the first place. The interval is called each second. But as soon the whole view
                     // is transparent, we clear it, so that isCanvasTransparent is no longer called
                    clearInterval(this.checkCanvasTimeout);
                    this.alerted = true;
                    TouchHelpers.removeTouchEvents();
                    this.levelCompleted();
                    return;
                } else {
                    // this sector is clear, but we need to check the next one, since we are not at the end
                    this.isCanvasTransparent(fromX + 20, toX + 20, currentIteration + 1);
                }
            }
        }
    },
Was it helpful?

Solution

It's not certain without seeing how you set fromX/toX, but it looks like you're not giving getImageData the proper parameters.

context.getImageData has these parameters:

  • x: starting x coordinate to extract,
  • y: starting y coordinate to extract,
  • width: extract a block this many pixels wide,
  • height: extract a block this many pixels high

[ Addition: based on additional info ]

If you want equal sized chunks of pixel data, your first call is

var data=getImageData(0,0, 20, canvas.height).data;

And your second call would be:

// Note: the width arguement remains at 20, not increase to 40

var data=getImageData(20,0, 20, canvas.height).data;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top