5

I have an image of a map in a canvas that I would like to act like the google map interface using HTML5 and jQuery. I would like to perform the following actions:

• Double click on pan in without changing the size of the containing div

• Click on a building to bring up a pop up of information on that building

• Click and drag to pan

The code I have right now is the image in the canvas. I have found several codes that show "zooming" on the image, but either resize the container div or aren't a smooth and responsive way to do it, it just jumps to a larger size and I would like the zooming to be animated.

There will be several buildings that are "pinned" on the map that the user can click on to bring up information about that building.

The code is as follows:

JS:

$( document ).ready( function() {
var canvas = document.getElementById( 'canvas' );
var context = null;
var map = null;

if( canvas.getContext )
{
    context = canvas.getContext( '2d' );

    $( '#map' ).load( function( evt ) {
        context.drawImage( evt.currentTarget, 10, 10 );
    } );

    map = new Image();
    map.onload = function() {
        context.drawImage( this, 20, 20 );
    };
    map.src = 'images/asu_poly_map.png';
} else {
    alert( 'Your browser does not support canvas.' );
}
} );

HTML:

<div id="map">

<canvas id="canvas" width="1055" height="600"></canvas>

</div>

CSS:

#map {
margin:0 auto;
margin-top : 180px;
width : 1200px;
}

EDITED TO ADD: I'm assuming it would be something similar to this, but can't figure out how to apply it to an image from the server being drawn onto the canvas.

Zoom in on a point (using scale and translate)

Community
  • 1
  • 1
Jen
  • 156
  • 1
  • 3
  • 17

1 Answers1

6

Boom! I combined a bunch of StackOverflow references into something that works for you: http://jsfiddle.net/CMse5/1/

Here is the code:

HTML:

<div id="map">
    <canvas id="canvas" width="300" height="300"></canvas>
</div>

CSS:

canvas {
    border: 1px solid black;
}

JS:

$( document ).ready( function() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var scale = 1.5;
var originx = 0;
var originy = 0;
var imageObj = new Image(); 
    imageObj.src = 'http://placehold.it/300x300';

function draw(){
    // From: http://goo.gl/jypct
    // Store the current transformation matrix
    context.save();

    // Use the identity matrix while clearing the canvas
    context.setTransform(1, 0, 0, 1, 0, 0);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // Restore the transform
    context.restore();

    // Draw on transformed context    
    context.drawImage(imageObj, 0, 0, 300, 300);

}
setInterval(draw,100);

canvas.onmousewheel = function (event){
    var mousex = event.clientX - canvas.offsetLeft;
    var mousey = event.clientY - canvas.offsetTop;
    var wheel = event.wheelDelta/120;//n or -n


    //according to Chris comment
    var zoom = Math.pow(1 + Math.abs(wheel)/2 , wheel > 0 ? 1 : -1);

    context.translate(
        originx,
        originy
    );
    context.scale(zoom,zoom);
    context.translate(
        -( mousex / scale + originx - mousex / ( scale * zoom ) ),
        -( mousey / scale + originy - mousey / ( scale * zoom ) )
    );

    originx = ( mousex / scale + originx - mousex / ( scale * zoom ) );
    originy = ( mousey / scale + originy - mousey / ( scale * zoom ) );
    scale *= zoom;
}

} );

Also, you mention animating the zooming in a smooth fashion. To do this, you will need to ease the zooming each frame. So, within your draw function, each frame you will want to ease between an original scale to the new one. You will definitely want to change to requestAnimationFrame, so that you get a better framerate.

It may be simpler to use a canvas/DOM hybrid, and use CSS3 transformations and animation on an image, which takes care of all the easing for you. You could overlay any necessary canvas things if needed.

Dan
  • 1,729
  • 1
  • 18
  • 25
  • Note that it's better to use a requestAnimationFrame for animation loops instead of setInterval. – Dan Apr 21 '13 at 20:21
  • http://jsfiddle.net/CMse5/4/ -- with requestAnimationFrame loop, very smooth drawing with continuous mousewheels, such as Apple trackpad. – Dan Apr 21 '13 at 21:54
  • I placed my image in there and I'm not getting it to do anything. – Jen Apr 23 '13 at 01:52
  • http://jsfiddle.net/CMse5/4/ Here's the link. I'm not sure if there's a setting I need to change or something? When I double click on the image nothing happens. :/ – Jen Apr 23 '13 at 01:52
  • That's a duplicate link. Did you save the fiddle? – Dan Apr 23 '13 at 02:45
  • Currently it only works on mousewheel events. I'm able to see your image and zoom in/out with it via the mouse wheel. – Dan Apr 23 '13 at 06:18
  • Oh, I see. Unfortunately, I need it to be usable on laptops with a mousepad. Thank you though! – Jen Apr 23 '13 at 17:03