开发者

Multiple Canvas Zooms behaving erratically

开发者 https://www.devze.com 2023-01-06 20:16 出处:网络
I\'m running into a problem with the HTML5 Canvas tag and adjusting the scale several times. After zooming twice, the canvas only uses a fraction of the available canvas height & width, even thoug

I'm running into a problem with the HTML5 Canvas tag and adjusting the scale several times. After zooming twice, the canvas only uses a fraction of the available canvas height & width, even though I'm adjusting for the zoom level.

<html>
<head>
<script>

var ctx;
var nScale = 1.00;

function pageLoad() {
    ctx=document.getElementById('cnvUni').getContext('2d');

    // canvas on page load is 500x500
    drawGrid(); // 5 boxes across & 5 down

    zoom(0.5);  // canvas should be now zoomed out to 1000x1000
    drawGrid(); // 10 boxes across & 10 down

    zoom(0.5);  // effective zoom is now 0.25 = 2000x2000
    drawGrid(); // should be 20 boxes across & 20 down

    // NOTE: At this point, the grid is drawing boxes @ 20x20 but only using 1/4 of the 
    // canvas size.
}

function zoom(nZoomLevel) {
    nScale = nZoomLevel * nScale
    ctx.scale(nScale,nScale);
}

function drawGrid() {
    var nWidth, nHeight;
    nWidth = Math.floor(ctx.canvas.width / nScale);
    nHeight = Math.floor(ctx.canvas.he开发者_运维技巧ight / nScale);   

    var nGridSize = 100;
    var nGridY = 0;
    var nGridX = 0;

    // sets a random colour each time grid is drawn.
    ctx.strokeStyle = 'rgb(' + Math.floor(Math.random()*256) + ',' + Math.floor(Math.random()*256) + ',' + Math.floor(Math.random()*256) + ')';

    for (nGridY=0;nGridY < nHeight;nGridY+=nGridSize) {

    for (nGridX=0;nGridX < nWidth;nGridX+=nGridSize) {
        // draw the box;
        ctx.strokeRect(nGridX, nGridY, nGridSize, nGridSize);
    }
    }
}

</script>
</head>
<body onload="pageLoad();">
<canvas id="cnvUni" width="500" height="500">
Canvas doesn't work.
</canvas>
</body>
</html>

If I were to multiply the height & width by 2 when drawing the grid for the last time it'll draw out the entire canvas size, but I can't figure out why that would be required.

What I'm wondering is:

  1. Is there a way to query a canvas context to find out what the scale value (or the calculated height/width) is? Or am I approaching this correctly and keeping track of values myself?

  2. If so, then I assume it must be something with my math that's messing this up; I just can't pinpoint it. I'm sure I'm just too close to this problem and not seeing the issue. Another set of eyes would help.

Any suggestions would be appreciated.

Thanks!


I've got a version working on http://jsfiddle.net/sBXTn/5/ without using save/restore. This is the code change:

nScale = nZoomLevel * nScale
ctx.scale(nZoomLevel, nZoomLevel);

Previously using ctx.scale(nScale, nScale) meant that when you zoomed by 0.25 (0.5 twice) you were zooming by 0.25 on a context that was 1000x1000. This meant it increased the size to 4000x4000. Using nZoomLevel means you are zooming in relation to the dimensions of the current context.


I was way on the wrong track with this one and I feel silly for it. My math was correct in calculating the effective scale value (1 * 0.5 = 0.5, then scaling it by 0.5 again does = 0.25), but what I was doing was calculating the effective width & height by the original width & height, not the updated width & height.

So if I've scaled the original down to 0.5, the dimensions of the original 500x500 would be 1000x1000. Scaling it further by 0.5, the effective scale is 0.25, but the new width & height should be 4000x4000 (found by scaling 1000 by 0.25 and NOT 500 by 0.25).

Here's the updated code:

var ctx;
var nScale = 1.00;
var nEffWidth, nEffHeight;

function pageLoad() {
    ctx=document.getElementById('cnvUni').getContext('2d');

    nEffWidth = ctx.canvas.width;
    nEffHeight = ctx.canvas.height;

    // canvas on page load is 500x500
    drawGrid(); // 5 boxes across & 5 down

    zoom(0.5);  // canvas should be now zoomed out to 1000x1000
    drawGrid(); // 10 boxes across & 10 down

    zoom(0.5);  // effective zoom is now 0.25 = 4000x4000 based on new scaled width/height
    drawGrid(); // should be 40 boxes across & 40 down


}

function zoom(nZoomLevel) {
    nScale = nZoomLevel * nScale
    nEffHeight = nEffHeight / nScale;
    nEffWidth = nEffWidth / nScale;
    ctx.scale(nScale,nScale);
}

function drawGrid() {

    var nGridSize = 100;
    var nGridY = 0;
    var nGridX = 0;

    // sets a random colour each time grid is drawn.
    ctx.strokeStyle = 'rgb(' + Math.floor(Math.random()*256) + ',' + Math.floor(Math.random()*256) + ',' + Math.floor(Math.random()*256) + ')';

    for (nGridY=0;nGridY < nEffHeight;nGridY+=nGridSize) {

    for (nGridX=0;nGridX < nEffWidth;nGridX+=nGridSize) {
        // draw the box;
        ctx.strokeRect(nGridX, nGridY, nGridSize, nGridSize);
    }
    }
}

</script>
</head>
<body onload="pageLoad();">
<canvas id="cnvUni" width="500" height="500">
Canvas doesn't work.
</canvas>
</body>
</html>

Thanks for everyone who took a peek!

0

精彩评论

暂无评论...
验证码 换一张
取 消