Question

I am doing python project using flask where I used google map api to show the map in the project. I implement html2canvas script to capture the map successfully. But I have marker too in the map which it is not capturing. So I tried using html2canvasPythonProxy Here is my snippet of javascript file of template gpsDataMap:

$(window).load(function(){
      $('#saveMap').click(function(){
          html2canvas(document.getElementById('map'), {
             "logging": true, //Enable log (use Web Console for get Errors and Warnings)
             "proxy":"/surveyApp/gpsDataMap/html2canvas-proxy",
             useCORS:true,
             "onrendered": function(canvas) {
              var img = new Image();
             img.onload = function() {
             img.onload = null;
             document.body.appendChild(img);
           };
            img.onerror = function() {
            img.onerror = null;
            if(window.console.log) {
               window.console.log("Not loaded image from canvas.toDataURL");
                  } else {
            alert("Not loaded image from canvas.toDataURL");
               }
              };
                img.src = canvas.toDataURL("image/png");
               }
            });

        });
    });

And My snippet of python code:

import os
import datetime

from flask import Flask, request, render_template, redirect, url_for, flash, Response
from flask.json import dumps
from flask import json
from flask import g, Blueprint, session, abort
from flask_principal import Identity, identity_changed, identity_loaded, RoleNeed, AnonymousIdentity
from flask_login import LoginManager, login_user, login_required, logout_user
from app import app
from model.user_info import SurveyForms

from flask.ext.pymongo import PyMongo

from inspect import getmembers, isfunction
import formConfig
import formTree
import fieldChoices
from dashboard import dashboardData
from collections import namedtuple
from pymongo import MongoClient
from flask import request


from html2canvasproxy import * #include html2canvasproxy in your application
import urlparse
import re




surveyApp_module = Blueprint('surveyApp_module', __name__)


app.config['MONGO_HOST'] = 'localhost'
app.config['MONGO_PORT'] = 27017
app.config['MONGO_DBNAME'] = 'survey'
mongo = PyMongo(app)

h2c = None
real_path = os.getcwd() + '/static/images'
virtual_path = '/gpsDataMap/images/'

@surveyApp_module.route('/')
@login_required
def show_formList():
    forms = []
    forms = [form.form_name for form in SurveyForms.select().where(SurveyForms.organization_name==session['organization_id'])]
    # strip .xml from string to compare with returnData
    forms =  [form.replace('.xml','') for form in forms]
    returnData = mongo.db.collection_names()
    returnData.pop(returnData.index('system.indexes'))
    intersected_forms = list(set(forms).intersection(returnData))
    if len(intersected_forms):
        return render_template('index_pjj.html', surveyEntries=intersected_forms)
    return render_template('index_pjj.html', surveyEntries=['No Survey'])

@surveyApp_module.route('/dashboard', methods=['POST'])
def dashboard():
    formName = request.form['whichSurvey']
    session['formName'] = formName
    formtree = formTree.formParseDict(formName)
    returnData = dashboardData(formName, mongo.db)
    summaryData = totalSummary(formName, mongo.db)
    jsonData = json.dumps(returnData)
    return render_template('dashboard.html', formName=formName, formTree=formtree, returnData=returnData, summaryData=summaryData, jsonData=jsonData)


@surveyApp_module.route('/gpsDataView', methods=['POST'])
def gpsDataView():
    formName = request.form['whichSurvey']
    gpsFields = formConfig.survey[formName]['gpsField']
    (location, fieldName, fieldSelection, fieldChoicesList) = "", "", "", []
    location = request.form['location']
    fieldName = request.form['fieldName']
    try:
        fieldSelection = request.form['fieldChoices']
    except KeyError:
        pass
    fieldChoicesList = request.form.getlist('fieldChoicesList')
    fieldData = commonFunctions.vizFieldList(formName)
    totalFieldData = commonFunctions.vizFieldListFull(formName)
    locationIdentifiers = fieldChoices.locationFieldChoices(formName, mongo.db)
    returnData = gpsVariate.getDataforGPSMap(formName, mongo.db, gpsFields, location, fieldName, fieldSelection, fieldChoicesList)
    return render_template('gpsDataMap.html', returnData=returnData, formName=formName, fieldData=fieldData, totalFieldData=totalFieldData, locationIdentifiers=locationIdentifiers)



    #Copy html2canvas.js to static folder (If not use cdns)
@surveyApp_module.route('/gpsDataMap/html2canvas.js')
def html2canvas_js():
    return app.send_static_file('html2canvas.js')



@surveyApp_module.route('/gpsDataMap/html2canvas-proxy')
def html2canvas_proxy():
    print ("is this proxy really calling ");
    h2c = html2canvasproxy(request.args.get('callback'), request.args.get('url'))
    h2c.userAgent(request.headers['user_agent'])
    # import pdb;pdb.set_trace()


    if request.referrer is not None:
        h2c.referer(request.referrer)

    h2c.route(real_path, virtual_path)

    r = h2c.result()
    # print r['mime']
    # print r['data']

    return Response(r['data'], mimetype=r['mime'])




 # Get images saved by html2canvasproxy
@surveyApp_module.route('/gpsDataMap/html2canvas/images/<image>')
def images(image):
    res = html2canvasproxy.resource(real_path, image)

    if res is None:
        return '', 404

    else:
        return res['data']

Here is my main.py script:

from app import app, db


from auth import *
from admin import admin
from model import *
from view import *
from filters.user_privilege import check_privilege
from filters.form_filter import filter_type

# custom filters
app.jinja_env.filters['check_privilege'] = check_privilege
app.jinja_env.filters['filter_type'] = filter_type


from surveyApp import surveyApp_module
app.register_blueprint(surveyApp_module, url_prefix='/surveyApp')

from view.accounts.login import login_module
app.register_blueprint(login_module)


if __name__ == '__main__':
    app.run(port=5555)

While doing so I get the following things in my console:

html2canvas: Preload starts: finding background-images html2canvas.js:21
html2canvas: Preload: Finding images html2canvas.js:21
html2canvas: Preload: Done. html2canvas.js:21
html2canvas: start: images: 1 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 2 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 3 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 4 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 5 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 6 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 7 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 8 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 9 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 10 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 11 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 12 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 13 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 14 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 15 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 16 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 17 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 18 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 19 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 20 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 21 / 23 (failed: 0) html2canvas.js:21
html2canvas: start: images: 22 / 23 (failed: 0) html2canvas.js:21
GET http://127.0.0.1:5555/home/bhim/app/surveyApp_bhim/images/a0af53c02bd2f2aed37f1d895edcf3485117c512.png 404 (NOT FOUND) html2canvas.js:2249
html2canvas: start: images: 23 / 23 (failed: 1) html2canvas.js:21
Finished loading images: # 23 (failed: 1) html2canvas.js:21
html2canvas: Error loading background: html2canvas.js:21
html2canvas: Renderer: Canvas renderer done - returning canvas obj 

UPDATED: The debugger result:

folder => images,
timeout => 30,
mimetype => application/javascript,
ua => Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:29.0) Gecko/20100101 Firefox/29.0,
host => 127.0.0.1:5555,
scheme => http,
ref => ,
url => http://www.google.com,
callback => console.log,
default_callback => console.log,
status => 0,
routePath => /static/images/,
savePath => /home/bhim/app/surveyApp_bhim/static/images/,
prefix => htc_,
real_extension => ,
mimes => ['image/bmp', 'image/windows-bmp', 'image/ms-bmp', 'image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'text/html', 'application/xhtml', 'application/xhtml+xml']

UPDATED Screenshot of the images of google map

Google Map view that need to be capture ScreenShot of Map by html2canvaspythonproxy The marker is not being captured.

Was it helpful?

Solution

1) Use useCORS:true or use proxy, never use both at the same time.

2) Your routes are different, see:

  • virtual_path = '/gpsDataMap/images/'

  • @surveyApp_module.route('/gpsDataMap/html2canvas/images/<image>')

3) Your proxy route, seems to be wrong (in your Javascript):

  • "proxy":"/surveyApp/gpsDataMap/html2canvas-proxy",

  • @surveyApp_module.route('/gpsDataMap/html2canvas-proxy')


You do not realize all errors, why the userCORS with the "PROXY" get confused.

Fix all routes (routes are their virtual paths) and fix your javascript (don't use userCORS:), see:

$(window).load(function(){
    $('#saveMap').click(function(){
        html2canvas(document.getElementById('map'), {
                "logging": true, //Enable log (use Web Console for get Errors and Warnings)
                //useCORS:true, "COMMENTED", remove useCORS
                "proxy": YOUR_FIXED_ROUTE,
                "onrendered": function(canvas) {
                    var img = new Image();
                    img.onload = function() {
                        img.onload = null;
                        document.body.appendChild(img);
                    };

                    img.onerror = function() {
                        img.onerror = null;
                        if(window.console.log) {
                            window.console.log("Not loaded image from canvas.toDataURL");
                        } else {
                            alert("Not loaded image from canvas.toDataURL");
                        }
                    };
                    img.src = canvas.toDataURL("image/png");
                }
        });
    });
});

See, this is absolute path mixed with "routes":

GET http://127.0.0.1:5555/home/bhim/app/surveyApp_bhim/images/a0af53c02bd2f2aed37f1d895edcf3485117c512.png 404 (NOT FOUND) html2canvas.js:2249

The route of proxy response for any reason is wrong, use this:

1) Edit your code, like this:

@surveyApp_module.route('/gpsDataMap/html2canvas-proxy')
def html2canvas_proxy():
    print ("is this proxy really calling ");
    h2c = html2canvasproxy(request.args.get('callback'), request.args.get('url'))
    h2c.userAgent(request.headers['user_agent'])

    if request.referrer is not None:
        h2c.referer(request.referrer)

    if request.args.get('debug_vars'): #Added
        return Response((',\n'.join(h2c.debug_vars())), mimetype='text/plain') #Added

    h2c.route(real_path, virtual_path)

    r = h2c.result()
    return Response(r['data'], mimetype=r['mime'])

2) Run in browser:

http://127.0.0.1:5000/gpsDataMap/html2canvas-proxy?callback=console.log&url=http://www.google.com&debug_vars=1

3) Get results and post in your queston.

OTHER TIPS

please try this first it may work for you.

<script src="http://maps.googleapis.com/maps/api/js?key=AIzaSyDY0kkJiTPVd2U7aTOAwhc9ySH6oHxOIYM&sensor=false">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.js"></script> 
<script type="text/javascript" src ="http://code.jquery.com/jquery-1.9.0.min.js"></script>
<script type="text/javascript" src="html2canvas.js?rev032"></script> 



<script type="text/javascript">

function initialize()
    {
    var mapProp = {
          center:new google.maps.LatLng(51.508742,-0.120850),
          zoom:5,
          mapTypeId:google.maps.MapTypeId.ROADMAP
      };
    var map=new google.maps.Map(document.getElementById("googleMap"), mapProp);
}

google.maps.event.addDomListener(window, 'load', initialize);

 $(window).load(function(){

    $('#load').click(function(){

            html2canvas($('#googleMap'), {
            useCORS: true,
                onrendered: function (canvas) {
                var dataUrl= canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");

                window.location.href = dataUrl;
                                    }
            });

    });
});
</script>
</head>

<body>
<div id="googleMap" style="width:500px;height:380px;"></div>
<input type="button" value="Save" id="load"/>
</body>

To save markers (workaround for html2canvas):

(Source#1) : http://humaan.com/custom-html-markers-google-maps/
(Source#2) : http://jsfiddle.net/BCr2B/99/

Its quick and quite simple to implement your own markers, which then circumvents the tainted problems.

function HTMLMarker(lat, lng, col) {
    this.lat = lat;
    this.lng = lng;
    this.col = col;
    this.pos = new google.maps.LatLng(lat, lng);
}

HTMLMarker.prototype = new google.maps.OverlayView();
HTMLMarker.prototype.onRemove = function() {}
HTMLMarker.prototype.onAdd = function() {}
HTMLMarker.prototype.draw = function() {
    var self = this;
    var div = this.div;

    if(!div) {
        div = this.div = document.createElement('div');
        div.className = 'marker';
        div.style.position = 'absolute';
        div.style.width = '32px';
        div.style.height = '32px';

        switch(this.col) {
            case "green":
                div.innerHTML = '<img src="/images/green-dot.png">';
                break;
            case "yellow":
                div.innerHTML = '<img src="/images/yellow-dot.png">';
                break;
            case "red":
                div.innerHTML = '<img src="/images/red-dot.png">';
                break;
        }

        var panes = this.getPanes();
        panes.overlayImage.appendChild(div);
    }


    var position = this.getProjection().fromLatLngToDivPixel(this.pos);
    div.style.left = position.x - 16 + "px";
    div.style.top = position.y - 32 + "px";
}

Then just add:

var htmlMarker = new HTMLMarker(data[gps].Latitude, data[gps].Longitude, "green");
markersArray.push(htmlMarker.setMap(map));

When you export in this way, the map markers are added successfully as they come from a local source.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top