Openlayers Print Function - javascript

I would like to create a print button for my Openlayers map which grabs the map image and creates a nice image file. I have tried http://dev.openlayers.org/sandbox/camptocamp/canvas/openlayers/examples/exportMapCanvas.html
but it seams like it is experimental. I have also looked at http://trac.osgeo.org/openlayers/wiki/Printing
but I don't want any server involved. I also checked out http://html2canvas.hertzen.com/ but can't get it to work. I get the following error, Uncaught TypeError: Cannot read property 'images' of undefined, html2canvas.js
<button onclick="printFunction()">Click me</button>
function printFunction() {
html2canvas(('#map'), {
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png")
window.open(img);
}
});
};

Try
function printFunction() {
html2canvas(document.getElementById("map"), {
onrendered: function (canvas) {
var img = canvas.toDataURL("image/png")
window.open(img);
}
});
This works for me. The hashtag identification only works for jQuery, took me a while to figure that out :-)
There is a slight problem though. The html2canvas did not render the background WMS layer - only the map window and markers, so some tweaking still needs to be done.
Update :
I have done some fiddling with this, and I do not think that it will work with openlayers. Since the openlayers map is a composition of many divs, it seems that the html2canvas is not capable of drawing all of them properly. Specifically a WMS layer, which, when attempted to be drawn on its own, returns an error. You can try rendering one of the children divs in the map, but that has not worked for me. Although, if you are only using simple vector graphic, it could work for you.

Ok, I've spent a few hours on this now and the best I've come up with is an enhancement on #Kenny806 's answer, which is basically this one.
It does seem to pick up WMS and Vector layers:
function exportMap() {
var mapElem = document.getElementById('map'); // the id of your map div here
// html2canvas not able to render css transformations (the container holding the image tiles uses a transform)
// so we determine the values of the transform, and then apply them to TOP and LEFT
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(mapElem, {
useCORS: true,
onrendered: function(canvas) {
mapImg = canvas.toDataURL('image/png');
// reset the map to original styling
$(".gm-style>div:first>div").css({
left:0,
top:0,
"transform":transform
});
// do something here with your mapImg
// e.g. I then use the dataURL in a pdf using jsPDF...
// createPDFObject();
}
});
}
Notes
Only tested on Chrome and Firefox
This is a hacky solution (unfortunately I am struggling to find other options for my situation)
If you have the option to use Openlayers 3, there seems to be better canvas support, and I've also seen a convincing toBlob example: http://codepen.io/barbalex/pen/raagKq

WMS draw works fine but you have to implement a Proxy for downloading WMS tiles using AJAX. See the PHP proxy example of html2canvas for the implementation details of the "proxy" (which is not a http proxy".

Related

PIXI.JS Newbie, looking for advice and troubleshoot of a textureCache, loader issue

ive ventured into the world of PIXI and JS, new programming language for me, liking the way it is right now but i have an issue.
I am a bit confused with the TextureCache and the loader. If you look at part of my code i try to add 3 different images to the screen. Ive been following the 'Get Started section' of the pixi website. I wanted to add their cat image, which i have, the tileset image (all of it)* and then a tile of the tileset image.
The issue is, i create 3 new sprite instances and the tileset image shows the area ive set for the tile(rocket) when i want it to show the whole tileset. Ive loaded in the tileset iin the cahce and the loader.
Why does tile show the cropped image and not the whole image?
Am i using the cache correctly to just store images?
Am i using the resources method properly to locate the image FROM the cache or the loader?
Is there any point of the cache?
my thoughts**
when you use the rectangle method, it destroys the original image and the cropped version is now tileset1 (the name of my image)?
<html>
<body>
<script src="pixi.js"></script>
<script>
//Aliases
let Application = PIXI.Application,
loader = PIXI.loader,
resources = PIXI.loader.resources,
Sprite = PIXI.Sprite,
Rectangle = PIXI.Rectangle,
TextureCache = PIXI.utils.TextureCache;
let app = new PIXI.Application({
width: 1000,
height: 600,
antialias: true,
transparent: false,
resolution: 1
}
);
//Add the canvas that Pixi automatically created for you to the HTML document
document.body.appendChild(app.view);
TextureCache["tileset1.png","images/3.png"];
//load an image and run the `setup` function when it's done
loader.add(["images/3.png","tileset1.png"]).load(setup);
//This `setup` function will run when the image has loaded
function setup() {
let texture = TextureCache["tileset1.png"];
let rectangle = new Rectangle(96,64,32,32);
texture.frame = rectangle;
//Create the cat sprite, use a texture from the loader
let card = new Sprite(resources["images/3.png"].texture);
let tile = new Sprite(resources["tileset1.png"].texture);
let rocket = new Sprite(texture);
card.scale.set(0.06,0.06);
tile.x=400;
tile.y=400;
rocket.x=100;
rocket.y=100;
//Add the cat to the stage
app.stage.addChild(card);
app.stage.addChild(tile);
app.stage.addChild(rocket);
app.renderer.render(app.stage);
}
</script>
</body>
</html>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pixi.js/5.2.4/pixi.js"></script>
Is there any point of the cache? - this question seems to be most important from your questions :)
Searching around about "pixi.js" and "TextureCache" gives following answers for example:
https://github.com/pixijs/pixi.js/issues/4053
MySecret commented on May 23, 2017:
the docs has no specs about PIXI.utils.TextureCache
...
englercj commented on May 26, 2017
This is intentional, it is not meant as a public-facing API. It is an internal cache used by some texture creation methods.
https://www.html5gamedevs.com/topic/17788-loader-and-texturecache-tutorial-anywhere/
xerver - Pixi.js Moderator:
Here is the loader: https://github.com/englercj/resource-loader
The code is really well documented, and there are examples on the readme. The pixi examples also use the loader a few times: http://pixijs.github.io/examples/
The TextureCache is an internal mechanism, there is rarely any reason you should even know it exists.
https://www.html5gamedevs.com/topic/25575-pixiloaderresources-or-texturecache/
xerver - Pixi.js Moderator:
Dont do this:
let e = PIXI.utils.TextureCache[player.img];
Instead use the resources the loader loaded for you:
let e = PIXI.loader.resources[player.img].texture;
...
TLDR: Usually TextureCache shouldnt be used directly :)
See also:
this explanation: https://www.html5gamedevs.com/topic/9255-pixijs-caching/?tab=comments#comment-55233
http://pixijs.download/release/docs/PIXI.BaseTexture.html#.addToCache
^ example of usage: https://jsfiddle.net/themoonrat/br35x20j/

Create js animation of a horizontal spritesheet

I have gone through the docs and sample only to be lost in outdated docs. Apparently there is no samples for the latest version of createjs.
I need to smooth scroll a horizontal spritesheet. So that the middle of images are shown before the new image is entirely in the "window". So the place in the page doesnt move only what is displayed from the single column horizontal spritesheet is different. And we do not switch between images we scroll up and down.
I am at my wits end with this.
this.sprite = new createjs.BitmapAnimation(spriteSheet);
that line gives an error
not a constructor
this.sprite = createjs.BitmapAnimation(spriteSheet);
gives an error
not a function
here is the sprite sheet
https://github.com/nydehi/asp.net-mvc-example-invoicing-app/blob/master/screenshots/1.png
i am doing this now and no error but nothing is displayed.
<script type="text/javascript" src="createjs-2014.12.12.min.js"></script>
<script>
function init() {
var data = {
images: ["1.png"],
frames: {width:15, height:20},
animations: {
stand:0,
run:[1,5],
jump:[6,8,"run"]
}
};
var spriteSheet = new createjs.SpriteSheet(data);
var animation = new createjs.Sprite(spriteSheet, "run");
var stage = new createjs.Stage("demoCanvas");
stage.addChild(animation);
animation.gotoAndPlay("run"); //walking from left to right
stage.update();
}
</script>
You're probably using a more recent version of CreateJS (around version 0.8.2) which no longer has a BitmapAnimation class on it.
Older versions (0.6.0) had it, but it was most likely replaced by the SpriteSheet class.
Check here for the most recent documentation.
The earlier comments about BitmapAnimation being deprecated long ago are right. Your updated code sample looks fine otherwise.
I think you are just missing something to update the stage when contents change. Your sample just has the one update, but because your image is loaded using a string path, it is not ready yet when you call stage.update().
Any time contents change, you need to tell the stage to refresh. Typically, this is manually controlled when contents change, or constantly using the Ticker.
createjs.Ticker.on("tick", function(event) {
// Other updates
// Update the stage
stage.update(event);
});
// Or a handy shortcut if you don't need to do anything else on tick:
createjs.Ticker.on("tick", stage);

html2canvas is not capturing true google map on chrome [duplicate]

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
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
})
}
});
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 🙂
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
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
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;
});

html2canvas does not work with Google Maps Pan

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
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
})
}
});
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 🙂
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
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
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;
});

KineticJS: How to convert a Stage into a HTML5 Canvas Element?

I have a KineticJS stage with a lot of layers.
I found this post: How to copy a kineticjs stage to another canvas
It says that I get a canvas element from a layer as
var canvasElement = layer.getCanvas().getElement();
Is it also possible to export a stage into a canvas?
In your use case you can do this:
In hard way you can create custom canvas element (or Kinetic.Layer), then conver Stage to Image, draw the image to canvas (layer) then pass it to plugin.
But this way should also work. I just saw plugin source. It is very simple (js part). I edited it:
stage.toDataURL({
callback : function(data) {
var imageData = data.replace(/data:image\/png;base64,/,'');
return cordova.exec(function() {
// done callback
}, function() {
// fail callback
}, "Canvas2ImagePlugin","saveImageDataToLibrary",[imageData])
}
});

Categories