Question:
How to Add transparent pixels without just doing white pixels?

Like others have said, fillRect will paint on top of what's already there, not replace. That lets you mix transparent colours together like on a real canvas.


You can just use clearRect to erase.


Change the event listeners in mousedown and mousemove to:


if (eraser) {

      ctx.clearRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);

    } else {

      ctx.fillStyle = color;

      ctx.fillRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);

    }


From the> >mozilla docs:

The CanvasRenderingContext2D.clearRect() method of the Canvas 2D API erases the pixels in a rectangular area by setting them to transparent black.


Demo:

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

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

var pixelSize = 10;

var color = '#000000';

var eraser = false;

var fillStack = [];


var fillButton = document.getElementById('fill');


fillButton.addEventListener('click', function () {

  processFillStack();

});


var downloadButton = document.getElementById('download');


downloadButton.addEventListener('click', function () {

  var dataURL = canvas.toDataURL('image/png');

  var link = document.createElement('a');

  link.setAttribute('href', dataURL);

  link.setAttribute('download', 'pixel-art.png');

  link.click();

});


var widthInput = document.getElementById('width');

var heightInput = document.getElementById('height');

var resizeButton = document.getElementById('resize');


resizeButton.addEventListener('click', function () {

  canvas.width = widthInput.value;

  canvas.height = heightInput.value;

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

  ctx.clearRect(0, 0, canvas.width, canvas.height);

});


document.getElementById('eraser').addEventListener('change', function () {

  eraser = this.checked;

});


canvas.addEventListener('mousedown', function (e) {

  if (!fillButton.pressed) {

    var x = Math.floor(e.offsetX / pixelSize);

    var y = Math.floor(e.offsetY / pixelSize);

    if (eraser) {

      ctx.clearRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);

    } else {

      ctx.fillStyle = color;

      ctx.fillRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);

    }

  }

});


canvas.addEventListener('mousemove', function (e) {

  if (e.buttons == 1 && !fillButton.pressed) {

    var x = Math.floor(e.offsetX / pixelSize);

    var y = Math.floor(e.offsetY / pixelSize);

    if (eraser) {

      ctx.clearRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);

    } else {

      ctx.fillStyle = color;

      ctx.fillRect(x * pixelSize, y * pixelSize, pixelSize, pixelSize);

    }

  }

});


var imageInput = document.getElementById('image-input');


imageInput.addEventListener('change', function () {

  var file = imageInput.files[0];

  var reader = new FileReader();

  reader.onload = function (e) {

    var img = new Image();

    img.onload = function () {

      ctx.drawImage(img, 0, 0);

    };

    img.src = e.target.result;

  };

  reader.readAsDataURL(file);

});


function floodFill(x, y, fillColor) {

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

  var pixelStack = [[x, y]];

  var pixelPos, rowStart, rowEnd, up, down, i;

  while (pixelStack.length) {

    pixelPos = pixelStack.pop();

    rowStart = pixelPos[1] * canvas.width * 4;

    rowEnd = rowStart + canvas.width * 4;

    up = false;

    down = false;

    for (i = rowStart; i < rowEnd; i += 4) {

      if (matchColor(imageData.data, i, fillColor)) {

        continue;

      }

      if (

        matchColor(imageData.data, i, getPixelColor(pixelPos[0], pixelPos[1]))

      ) {

        imageData.data[i] = fillColor[0];

        imageData.data[i + 1] = fillColor[1];

        imageData.data[i + 2] = fillColor[2];

        imageData.data[i + 3] = fillColor[3];

        if (pixelPos[1] > 0) {

          if (

            matchColor(

              imageData.data,

              i - canvas.width * 4,

              getPixelColor(pixelPos[0], pixelPos[1] - 1)

            )

          ) {

            if (!up) {

              pixelStack.push([pixelPos[0], pixelPos[1] - 1]);

              up = true;

            }

          } else if (up) {

            up = false;

          }

        }

        if (pixelPos[1] < canvas.height - 1) {

          if (

            matchColor(

              imageData.data,

              i + canvas.width * 4,

              getPixelColor(pixelPos[0], pixelPos[1] + 1)

            )

          ) {

            if (!down) {

              pixelStack.push([pixelPos[0], pixelPos[1] + 1]);

              down = true;

            }

          } else if (down) {

            down = false;

          }

        }

        if (pixelPos[0] > 0) {

          if (

            matchColor(

              imageData.data,

              i - 4,

              getPixelColor(pixelPos[0] - 1, pixelPos[1])

            )

          ) {

            pixelStack.push([pixelPos[0] - 1, pixelPos[1]]);

          }

        }

        if (pixelPos[0] < canvas.width - 1) {

          if (

            matchColor(

              imageData.data,

              i + 4,

              getPixelColor(pixelPos[0] + 1, pixelPos[1])

            )

          ) {

            pixelStack.push([pixelPos[0] + 1, pixelPos[1]]);

          }

        }

      }

    }

  }

  ctx.putImageData(imageData, 0, 0);

}


function matchColor(data, i, color) {

  return (

    data[i] == color[0] &&

    data[i + 1] == color[1] &&

    data[i + 2] == color[2] &&

    data[i + 3] == color[3]

  );

}


function getPixelColor(x, y) {

  var imageData = ctx.getImageData(

    x * pixelSize,

    y * pixelSize,

    pixelSize,

    pixelSize

  );

  var r = 0,

    g = 0,

    b = 0,

    a = 0;

  for (var i = 0; i < imageData.data.length; i += 4) {

    r += imageData.data[i];

    g += imageData.data[i + 1];

    b += imageData.data[i + 2];

    a += imageData.data[i + 3];

  }

  var n = imageData.data.length / 4;

  return [

    Math.round(r / n),

    Math.round(g / n),

    Math.round(b / n),

    Math.round(a / n),

  ];

}


function processFillStack() {

  var threads = 4; // number of threads to use

  var stackSize = fillStack.length;

  var chunkSize = Math.ceil(stackSize / threads);

  var chunks = [];

  for (var i = 0; i < threads; i++) {

    chunks.push(fillStack.splice(0, chunkSize));

  }

  for (var i = 0; i < threads; i++) {

    (function (chunk) {

      setTimeout(function () {

        for (var j = 0; j < chunk.length; j++) {

          var x = chunk[j][0];

          var y = chunk[j][1];

          var color = chunk[j][2];

          floodFill(x, y, color);

        }

      }, 0);

    })(chunks[i]);

  }

}



canvas {

  background-color: white;

  border: 1px solid black;

}

#color-picker {

  width: 50px;

  height: 50px;

/*  position: absolute;

  top: 10px;

  left: 10px; */

}

#download {

  display: block;

  margin: 10px auto;

  padding: 10px;

  background-color: black;

  color: white;

  border: none;

  border-radius: 5px;

  cursor: pointer;

}


label, input, button {

  display: block;

  margin: 10px 0;

}


label {

  font-weight: bold;

}


input[type="number"] {

  width: 50px;

}


button {

  padding: 10px;

  background-color: black;

  color: white;

  border: none;

  border-radius: 5px;

  cursor: pointer;

}


#eraser {

  display: none;

}

#eraser + label:before {

  content: "";

  display: inline-block;

  width: 20px;

  height: 20px;

  background-color: white;

  border: 1px solid black;

  margin-right: 5px;

}

#eraser:checked + label:before {

  background-color: black;

}








Import Image:




Suggested blogs:

>How to delete duplicate names from Array in Typescript?

>How to do PHP Decryption from Node.js Encryption

>How to Set up the Android emulator?

>How to Set up the local environment for Angular development?

>How to solve encoding issue when writing to a text file, with Python?

>Step by Step guide to Deploy Terraform in Azure using GitHub Actions

>Testing react components using Hooks and Mocks

>Use Firebase Realtime Database with ASP.NET MVC App

>Use of Singletons in .NET Core in AWS Lambda

>What are common syntax errors and exceptions in Python


Ritu Singh

Ritu Singh

Submit
0 Answers