Daniel J F
Daniel J F

Reputation: 1064

Canvas: fit drawing to canvas size without changing the coordinates

Let's say we're dynamically drawing a fractal on a canvas. Since we don't know how big the fractal is going to be, at some point we'd need to scale (zoom out) the canvas to fit our fractal in there.

How do we do that? How to scale it:

  1. Properly, so that it perfectly fits the drawing we have, and
  2. So that the coordinates stay the same, and our fractal calculation doesn't need to use the scale value (meaning, return x, not return x * scale, if possible)
  3. What if the fractal grows in all directions and we have negative values?

See the tiny example below.

var $canvas = document.querySelector('canvas'),
    ctx     = $canvas.getContext('2d'),
    lastX   = 0,
    lastY   = 0;

    drawLoop();


function drawLoop() {
    var newX = lastX + 30,
        newY = lastY + 30;

    ctx.beginPath();
    ctx.moveTo(lastX, lastY);
    ctx.lineTo(newX, newY);
    ctx.stroke();

    lastX = newX;
    lastY = newY;

    setTimeout(drawLoop, 1000);
}
<canvas width="100" height="100" style="border: 1px solid #ccc;"></canvas>

Upvotes: 2

Views: 1135

Answers (1)

Blindman67
Blindman67

Reputation: 54039

You can scale, translate, and rotate the drawing coordinates via the canvas transform.

If you have the min and max coordinates of your drawing

Example:

const min = {x: 100, y: 200};
const max = {x: 10009, y: 10000}; 

You can make it fit the canvas as follows

const width = canvas.width;
const height = canvas.height;

// get a scale to best fit the canvas
const scale = Math.min(width / (max.x - min.x), height / (max.y - min.y));

// get a origin so that the drawing is centered on the canvas
const top = (height - (max.y - min.y)) / 2;
const left = (width - (max.x - min.x)) / 2;

// set the transform so that you can draw to the canvas
ctx.setTransform(scale, 0, 0, scale, left, top);

// draw something
ctx.strokeRect(min.x, min.y, max.x - min.x, max.y - min.y);

If you do not know the size of the drawing area at the start then you will need to save drawing coordinates as you go. When the min and max change you then recalculate the transform, clear the canvas and redraw. There is no other way if you do not know the size at the beginning.

Upvotes: 5

Related Questions