1

I am making a drawing app in Ionic 4, In this app, I added the number 1 image in canvas using drawImage and the rest of the image background is transparent. If the user(kids) draw outside of the number 1 image, the percentage will decrease. For this, I search but didn't find anything but I found click to find is pixel is transparent or not.

isTransparent(x, y) { // x, y coordinate of pixel
let alpha = this.ctx.getImageData(x, y, 1, 1).data[3]; // 3rd byte is alpha

if (alpha === 0) {
  this.accuracy = 0;
  console.log("Transparent image clicked!");
} else {
  this.accuracy = 100;
  console.log("image clicked!");
}
}

The code sample I added on GitHub and here is live Demo.

user9088454
  • 1,076
  • 1
  • 15
  • 45
  • I'm not sure I understand your question; however, according to https://github.com/gokujy/ioniccanvas.github.io/blob/aa9c9ea44f745d5843cc1f1a9f88bd7d4709d354/src/app/pages/draw/draw.page.ts#L71-L89 `isTransparent` would always be `false`, because you draw the stroke (line 84) at the same coordinate *before* calling `isTransparent`. – ZER0 Nov 12 '19 at 15:23

1 Answers1

3

For that you will need a reference to the canvas, a reference to the drawing context of that canvas and choose when to update the percentage:

1) retrieve the canvas (for instance with getElementById):

var canvas = document.getElementById('id_of_the_canvas');

2) retrieve the drawing context

var ctx = canvas.getContext('2d');

3) retrieve the image data (all the image data)

var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

4) decide at which point you consider a pixel transparent (transparency threshold) and compute the ratio between transparent and non transparent pixel, use imageData.data for faster computation:

var pixelCount = canvas.width * canvas.height;
var arrayElemsCount = pixelCount * 4; // for components (rgba) per pixel.
var dataArray = imageData.data;
// 0 is completely transparent, set to 0.5 to
// allow for instance semi transparent pixels to be accounted for
var threshold = 0;
var transparentPixelCount = 0;
// remember fourth (index = 3) byte is alpha
for (var i = 3; i < arrayElemsCount; i+= 4) {
    var alphaValue = dataArray[i];
    if (alphaValue <= threshold) {
        transparentPixelCount++;
    }
}
var transparencyPercentage = (transparentPixelCount / pixelCount) * 100;

This operation is computationaly intensive so choose well when to execute it: either after some time ellapsed since the last drawing operation (debounce during drawing) or at regular interval during drawing (throttle during drawing).

remix23
  • 2,632
  • 2
  • 11
  • 21
  • What if it is a linear gradient, not an image? in this case getImageData can't be used – Joe Methven Sep 21 '22 at 16:49
  • The question has nothing to do with backgrounds or css coloring. It is specifically about canvas manipulation, on which you can always use getImageData. – remix23 Sep 26 '22 at 08:27