Canvas determining panning boundary independent of screen res and canvas resize

936 views Asked by At

I've implemented a panning functionality to an animation in a html5 canvas. It is probably the most disgusting implementations of something i've produced, or so it seems haha, but it works and that's good enough for now.

So I set these variables - I'll exclude the Y axis logic, and any save & restores for simplicity.

var translationX = 0; //This is where to start the clipping region

This is my drawing logic. Canvas is the image to be drawn, bCanvas is the 'viewport' to place over the image. When i'm not zoomed in this just displays the entire canvas image. All works as intended here.

function drawBuffer(){

    //If zoomed in I set the clipping region dimensions to half,  
      //having the effect of scaling by 2.

    if(stateManager.getZoomState() == "zoomIn")
        bContext.drawImage(canvas,translationX,translationY,
                           bCanvas.width*0.5,bCanvas.height*0.5,
                           0,0,
                           bCanvas.width,bCanvas.height);


    //Otherwise just draw the image to a scale of 1
    else
        bContext.drawImage(canvas,0,0,bCanvas.width,bCanvas.height);
}

This is the logic for moving the clipping region across the canvas in the X axis, and where the problem lies - in the condition that states when to stop incrementing translationX.

 function moveClippingRegion(){

    if(state is set to zoomed in){

        if(Right arrow key is pressed){

         //This condition admittedly is just the result of hacking away, but it works
          // in the sense that I stop incrementing translationX when 
          //at the edge of the canvas

            if(translationX>= (bCanvas.width -canvas.width) - translationX - 64){
               //The -64 literal is definitely a hacking attempt, 
              //but without the clipping region increments two times more than 
              //it should, thus going off the canvas.

            }
            else
                translationX += 16;

        }
 }

Ok so this all works when the window has not been resized, so what i'm looking for is some direction as to what condition to put in that scales with the bCanvas being resized.

Here's the resize function in case that is of any importance:

     function onResize(){

    bCanvas.width = window.innerWidth *    0.60952380952380952380952380952381;      

    bCanvas.height = window.innerHeight * 0.83116883116883116883116883116883;
    drawBuffer();
}

The drawing canvas's dimensions are 1024 x 768, so those ugly literals just make the bCanvas the same dimensions as the canvas.

This only works on my screen resolution, and when the window hasn't been resized. I'm at my witts end trying to get this to work independent of resolution/ after window resized.

Finally here's an image to help illustrate the problem that's occurring on different resolutions/ after window has been resized, if the window has been resized to a really small size, the clipping region does not even move, which is to be expected with the logc in the if statement in the moveClippingRegion function.:

enter image description here

Thanks for reading this in advance, any help would be greatly appreciated!

2

There are 2 answers

0
MaKR On

I was making a paint type web app when I ran into something similar. You'll need to add/subtract the offset top/bottom and multiply/divide the offset height/width of your elements. There's some strange math involved, and unfortunately will take a lot of time for you to solve. You'll have to just play with numbers until you get it right. Make sure you use offsets, which will give you the actual position instead of what's set in CSS or JS. Set values are not real numbers for calculating element sizes & positions. I'm not sure what to tell you on zoom though, because I added a zoom feature so I could manipulate the sizes. Here's a snippet from my app which will show at least a starting point:

$('#pg'+id).mousemove(function(e) {
    // x and y are globals, x inits to null, mousedown sets x, mouseup returns x to null
    if (x==null) return;
    x = (100/$('#zoom').val())*(e.pageX - $(this).offset().left);
    y = (100/$('#zoom').val())*(e.pageY - $(this).offset().top);

    $('#debug').html(x+', '+y); // constantly update (x,y) position in a fixed div during debugging
});
0
Insyte On

Drawing the canvases out may help you.

Should give you a solution like the one below. Seeing as the zoom rate is x2 (.5) half the zoom canvas and minus the left position from the zoom canvas / 2 from canvas width. Or visa versa (head scratcher :P)

var StepRate; // <- your step increment when moving.
if(translationX >= (canvas.width / 2) - (((zoomCanvas.width - canvas.width) / 2) + StepRate)){}
else
    translationX += StepRate;