3

I'm trying to use the element to draw a static Google Maps image that comes onscreen once a user clicks on a submit button. The html looks like this:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <script type="text/javascript"
    src="https://maps.googleapis.com/maps/api/js?key=MYKEY&sensor=true">
    </script>
    <script type="text/javascript" src="createmap.js">
    </script>
</head>
<body>
    <form onsubmit="display_map(34.1,-76.08168); return false;">
    <input type="submit" value="Submit"/>
    </form>
    <canvas id='map-canvas' />
</body>
</html>

And the display_map() function in createmap.js:

function display_map(center0, center1) {
    var image = new Image();
    image.src = 'http://maps.googleapis.com/maps/api/staticmap?center='
    + center0 + ',' + center1 + '&zoom=13&size=800x800&sensor=false';
    var canvas = document.getElementById('map-canvas');
    var context = canvas.getContext('2d');
    context.drawImage(image, 0, 0);
}

The first time that the user clicks on the submit button, nothing happens. Every subsequent click, however, will load the image (even if the tab is closed and then reopened). Changing the center0 and center1 arguments will reset the page and again force two clicks to display the new image that Google generates. This behavior doesn't seem to be coming from Google Maps, as the same issue occurs when I load an image from my hard drive. This is happening in every browser I've tested (Firefox, IE and Chrome).

Fred the Fantastic
  • 1,295
  • 1
  • 9
  • 11

1 Answers1

2

It's because the first time the image hasn't loaded properly so the canvas doesn't draw anything. The image loads asynchronous in the background so your function will continue regardless.

To handle this scenario try with:

function display_map(center0, center1) {
    var image = new Image();
    image.onload = function() {
        var canvas = document.getElementById('map-canvas');
        var context = canvas.getContext('2d');
        context.drawImage(this, 0, 0);
    }
    image.src = 'http://maps.googleapis.com/maps/api/staticmap?center='
    + center0 + ',' + center1 + '&zoom=13&size=800x800&sensor=false';
}

That the function returns immediately is something that needs to be taken into account in case you do several draw operations to canvas (graphics on top for instance).

For these cases you need to use callbacks so when an image has finished loading you call the next step from within the onload handler with a single extra parameter:

function display_map(center0, center1, callback) {
    var image = new Image();
    image.onload = function() {
        var canvas = document.getElementById('map-canvas');
        var context = canvas.getContext('2d');
        context.drawImage(this, 0, 0);
        callback();
    }
    image.src = 'http://maps.googleapis.com/maps/api/staticmap?center='
    + center0 + ',' + center1 + '&zoom=13&size=800x800&sensor=false';
}

Now you can create a call chain:

function step1() {
    display_map(center0, center1, step2);
}

function step2() {
    /// called when step1 has finished
}