23

I'm using html2canvas to save my online map as an image (See the Save as Image link). I've tried it in Firefox, Chrome and Opera.

It tends to work more often if you do not alter the default map. If you zoom and then pan the map, it is less likely to work. The map will pan, but html2canvas will use the old center point and map bounds. And html2canvas will fail to load map tiles for the new map bounds.

The map pans correctly, but html2canvas uses the old center point and map bounds. Why is this?

To support getting images from different domains I have the setting:

useCors: true;

I have tried the following solutions

-Manually changing the map type. Sometimes this fixes it.

-Triggering the browser resize event - not useful.

-Using setTimeout() to wait 2000 ms to ensure the tiles are loaded - not useful

-Using a proxy (html2canvas_proxy_php.php) - not useful

-Using the google maps idle event to wait for the map to be idle before saving - not useful

Aaron Kreider
  • 1,705
  • 5
  • 22
  • 44
  • I might be running into a problem with the Same Origin Policy. But then I'm not sure why this would be sporadic. I'm accessing images and javascript from different servers. – Aaron Kreider Jun 04 '14 at 20:28
  • If I add the "allowTaint:true" parameter, then it saves my image map layer but doesn't save the underlying map layer. – Aaron Kreider Jun 04 '14 at 20:44
  • I might need to wait for the map pan to finish loading image tiles, before I try to save the image. – Aaron Kreider Jun 04 '14 at 21:13
  • What's up with the down-voting? Is it because the issue is sporadic? – Aaron Kreider Jun 04 '14 at 22:56
  • did you try http://www.nihilogic.dk/labs/canvas2image/ canvas2image? – mboeckle Jun 13 '14 at 16:13
  • You should provide your script for image saving so it can be debugged. I think the problem is that you have set a specific size for the image? For me it always comes up saying the pixel size is "Natural: 1351 × 579 pixels" – eikooc Jun 15 '14 at 07:32
  • Eikoc: it's javascript - so you can see it. I don't specify an image size. The image size is based on the browser window. – Aaron Kreider Jun 16 '14 at 19:53
  • Changing the map type sometimes helps. I think there is a problem with image caching or loading. Can I make Google reload all the map tiles? This had some ideas on tile reloading: http://stackoverflow.com/questions/12173508/google-maps-v3-how-to-force-reloading-of-tiles – Aaron Kreider Jun 16 '14 at 20:53

5 Answers5

66

Apparently, the problem seems to stem from html2canvas not being able to render css transforms, at least in chrome (I could only reproduce the problem in chrome, on OSX). The container that holds the tiles, is translated using -webkit-transform. So what we could do is to grab the values that the container is shifted, remove the transform, assign left and top from the values we got off transform then use html2canvas. Then so the map doesn't break, we reset the map's css values when html2canvas is done.

So I pasted this into the javascript console at your site and at it seemed to work

//get transform value
var transform=$(".gm-style>div:first>div").css("transform")
var comp=transform.split(",") //split up the transform matrix
var mapleft=parseFloat(comp[4]) //get left value
var maptop=parseFloat(comp[5])  //get top value
$(".gm-style>div:first>div").css({ //get the map container. not sure if stable
  "transform":"none",
  "left":mapleft,
  "top":maptop,
})
html2canvas($('#map-canvas'),
{
  useCORS: true,
  onrendered: function(canvas)
  {
    var dataUrl= canvas.toDataURL('image/png');
    location.href=dataUrl //for testing I never get window.open to work
    $(".gm-style>div:first>div").css({
      left:0,
      top:0,
      "transform":transform
    })
  }
});
mfirdaus
  • 4,574
  • 1
  • 25
  • 26
  • Brilliant! I got it to save the image in a new window too. Solution works in Firefox, Chrome, and Opera. – Aaron Kreider Jun 18 '14 at 19:03
  • Worked great for me too on Ionic. – jeudyx Jul 25 '15 at 08:59
  • can you please provide a jsfiddle. I works partially for me. It trims the map. Thank you. – Demian Flavius Sep 13 '15 at 11:08
  • This is working for mapview, any idea why streetview is broken? – JavaScripter Dec 07 '15 at 03:43
  • 1
    @JavaScripter StreetView by default uses webgl, then 3d transforms on images which html2canvas can't process. Easy fix is to set streetview mode/rendering to `html4`. Example here: https://jsfiddle.net/L0c3mL53/ – mfirdaus Dec 14 '15 at 03:30
  • @mfirdaus thank you for this. I will try this approach. In addition to the problem with Googlemap, I found in IE 9 ,10, in ROADMAP mode using your solution, html2canvas returns only partial view: https://github.com/niklasvh/html2canvas/issues/345. Do you have any idea? I have the same log as this guy: http://stackoverflow.com/questions/32175248/html2canvas-not-working-with-ie-google-map-getting-rendered-as-a-blank-image – JavaScripter Dec 14 '15 at 05:00
  • @mfirdaus here is the screenshots of what I got from IE9 IE10---- https://github.com/niklasvh/html2canvas/issues/750 – JavaScripter Dec 14 '15 at 13:11
  • @mfirdaus, i got undefined in transform,can u tell me what wrong i m doing ? – Nilesh Feb 06 '18 at 14:48
  • This used to work up to version (v=3.30), now it is not working anymore since the div scructure changed. Moreover, it is also using translate. Has anyone figured how to use the same hack idea on version 3.32? – jeanadam May 11 '18 at 19:31
8

After a Google Maps update the solution of mfirdaus stop working, the new solution is this:

var transform = $(".gm-style>div:first>div:first>div:last>div").css("transform")
var comp = transform.split(",") //split up the transform matrix
var mapleft = parseFloat(comp[4]) //get left value
var maptop = parseFloat(comp[5])  //get top value
$(".gm-style>div:first>div:first>div:last>div").css({ //get the map container. not sure if stable
  "transform": "none",
  "left": mapleft,
  "top": maptop,
})

is the same but u need to change de selector from

.gm-style>div:first>div

to

.gm-style>div:first>div:first>div:last>div

Hands up

3

In my case i just allowed Cross Origin Resource Sharing (CORS) in the html2Canvas configuration and it worked for me.

useCORS:true,

For more info you can refer to the html2Canvas Documentation: http://html2canvas.hertzen.com/configuration

Amit Anand
  • 265
  • 2
  • 6
2

I have the same problem, but I used Leaflet Map instead of Google Map.

The code is below

var transform=$(".leaflet-map-pane").css("transform");
if (transform) {
    var c = transform.split(",");
    var d = parseFloat(c[4]);
    var h = parseFloat(c[5]);
    $(".leaflet-map-pane").css({
        "transform": "none",
        "left": d,
        "top": h
    })
}           


html2canvas(document.body).then(function(canvas){
    $(".leaflet-map-pane").css({
        left: 0,
        top: 0,
        "transform": transform
    })
   }
// Here is used html2canvas 1.0.0-alpha.9
Nilesh
  • 1,013
  • 14
  • 21
0

Use this code for updated Google Maps.

  // @ts-ignore html2canvas defined via script
  html2canvas($('#shareScreen')[0], {
    useCORS: true,
    allowTaint: false,
    backgroundColor: null,
    ignoreElements: (node) => {
      return node.nodeName === 'IFRAME';
    }
  }).then((canvas) => {
    var dataUrl = canvas.toDataURL('image/png');
    console.log(dataUrl)
    this.shareLoader = false;
  });
Mushahid
  • 18
  • 1
  • 10