JSFiddle - React, Tailwind, and code Playground

by Nicolas Merinian

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="canvas"></canvas>
<button id="button">Scale Down Canvas</button>

JavaScript

// Set the canvas's resolution and size (not CSS).
canvas.width = 100;
canvas.height = 100;

// Fill the entire canvas with black.
const ctx = canvas.getContext("2d");
ctx.fillStyle = "#000000";
ctx.fillRect(0, 0, 100, 100);
ctx.fillStyle = "#ff0000";
ctx.fillRect(40, 40, 20, 20);

// create a pixel buffer for one transparent pixel
const imageData = ctx.getImageData(0, 0, 1, 1);
const pixel32 = new Uint32Array(imageData.data.buffer);
pixel32[0] = 0;
ctx.putImageData(imageData, 50, 50);

// Scale down the canvas preserving the transparent pixel's relative location.
$("#button").click(function() {
  ScaleCanvas(100, 100, .5, .5);
});

// Create a newly scaled canvas from the original and then delete the original.
function ScaleCanvas(width, height, xScale, yScale) {

  // Get the true overlay's current image data.
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);

  // Create an in-memory canvas at the new resolution.
  const newCanvas = $("<canvas>")
    .attr("width", width)
    .attr("height", height)[0];

  // Draw the true overlay's image data into the in-memory canvas.
  newCanvas.getContext("2d").putImageData(imageData, 0, 0);

  // Update the size/resolution of the true overlay.
  ctx.canvas.width = width;
  ctx.canvas.height = height;

  // Scale the true overlay's context.
  ctx.scale(xScale, yScale);

  // Draw the in-memory canvas onto the true overlay.
  ctx.drawImage(newCanvas, 0, 0);
}