Center Google Maps (V3) on browser print - javascript

I have a map set to 100% of the page width. The map has one marker and is centered on that marker. When I print the browser, I want the map to stay centered on the marker. This is the code I wrote to do so:
var lastPos = map.getCenter();
google.maps.event.addListener(map, "idle", function() {
lastPos = map.getCenter();
console.log(lastPos.toString());
});
google.maps.event.addDomListener(window, "resize", function() {
google.maps.event.trigger(map, "resize");
map.setCenter(lastPos);
console.log("Re-center on " + lastPos.toString());
});
This works when I re-size my browser, but does not work when the browser re-sizes itself before printing. If my browser is above a certain width then the marker is shifted entirely off the page (to the right) when the map is printed.
Here is my test case: http://www-sf.talispoint.com/testmapprint.html

You would need to add a #media print and give the map the size when printing and then you can do what is explained below.
When a map is printed what happens is that the top left corner is kept and the map is adjusted to fit the #media print size.
If you want the center to stay the same you need to manually change the center of the map.
http://jsbin.com/owiwox/33 is an example on how to work around this.
It uses a listener for the print media being applied event and adjusts the center of the map using a ratio on how the map is changed (made smaller)
One thing that you have to take care of is that you might have to make this browser targeted to make it work on all browsers (This solution works well in Chrome)
A good resource for making it work across browsers is:
http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/
The js code from the sample above listens to print requests and shifts the map so that the top left corner has the same center as the big map.
To cut the whole story short, this is how it works
You need to put in the ratio of the map vs printed map (or get the size by checking it from JS)
You assign it to:
var widthRatio = 2;
var heightRatio = 3;
You listen for print media being applied and shift the center so that it does not change
After you finish print , you revert the change.
Still here you have the problem that a part of the map will be cut, but there is not a good solution here, since the zoom level -1 tiles might not be cached so when you zoom out to fit bounds you might get no tiles.

It seems the problem with your 'printing' or 'printer'.
I did a test:
load the test map and make the browser very wide
print preview and saw the problem you described
But: I can change the printing scale from 'Shrint to fit' (default for IE and FF) to say 30% and was able to print the map as seen on the screen.
Another thought is:
You may try to use another CSS for print to limit the map div width, but I am not sure if that will trigger the resize of the map first (you may refer to this post: Javascript Event Handler for Print)

Related

Align non-geographical leaflet map maxBounds to the bottom of the container

I am creating a non-geographical map with leaflet, which shows a ski resort.
JSFiddle: https://jsfiddle.net/exophunk/ruzgeqL4/
I am using map.fitBounds(bounds) to fit the map to the container and map.setMaxBounds(bounds) to make sure you can't pan outside the map.
This works perfect when zooming in, but as long as the map is smaller than the viewport height, I would like to "align" the whole thing to the bottom of the container, so the map never moves away from the bottom of the container. As it is a mountain, it is pretty obvious.
I achieved this by adding an offset to the maxBounds, as you can see in this example (blue box = max bounds):
https://jsfiddle.net/exophunk/05cq3rzt/
The problem with this approach is, that you can now pan into the "empty sky" when zooming in, while I would actually like to keep the maxBounds as in the first example, so it also restricts movement upwards.
I think this would mean I would need to resize the max bounds while zooming in maybe? But there, I messed up coordinate systems and containers and wasn't able to do this properly.
How can I make sure the map always sticks to the container bottom while keeping the original max bounds, if possible?
You can overwrite the default wheel zoom and check if the zoom mousepoint is in the bounds, else zoom to the center of the bounds/map:
map.scrollWheelZoom._performZoomOrg = map.scrollWheelZoom._performZoom;
map.scrollWheelZoom._performZoom = function(e){
var mouse = map.scrollWheelZoom._lastMousePos;
var llpixel = map.containerPointToLatLng(mouse)
if(!bounds.contains(llpixel)){
map.scrollWheelZoom._lastMousePos = map.unproject([container.clientWidth/2, mapHeight]);
}
map.scrollWheelZoom._performZoomOrg();
}
https://jsfiddle.net/falkedesign/c04ngftj/

Google map hide hand icon

I am using google maps api V3, I am currently showing custom markers as dots of 6x6px and whenmousehover them I am showing infowindow.
I have set cursor to default on the map and on the markers aswell, now when I mousehover on the marker and then I move mouse towards infowindow for a fraction of second it shows hand cursor, which looks quite ugly when I have quite a few markers on the map, I need to avoid this, please let me know how I can avoid this.
Here is my jsfiddle Here hover on bluedots which are markers from bottom to top and you will see little flicker, I don't want to show handicons at all ... I just want default cursors
This is how I have create infowindow
var infowindow = new google.maps.InfoWindow({
content: "infowindow",
cursor: 'default',
});
This CSS has solved my problem...
#map div {
cursor:default !important;
}
I believe this may be a "bug"/"characteristic" of Google Maps API. What is happening is that when moving the cursor upward vertically, it moves off the Marker and onto the transparent bounding box of the InfoBox. However, your MouseOut handler for the Market then removes the InfoBox off of the map.
So the Google Maps API has to then decide what to do when the cursor is over an element that is removed. It SHOULD pick the cursor that you defined as the default in the MapOptions; but it does not. I used both FireFox's and Chrome's Element Inspectors, and saw repeatedly that when the InfoBox got removed, Google Maps API explicitly set the active cursor to the "Hand" instead of leaving it as the "default" in a primary child 'div' of the map.
I added a document.body.style.cursor definition to your initialization code in the JSFiddle just to make sure the Browser itself was not confused about the cursor:
$(document).ready(function () {
mapObjects.domReady = true;
document.body.style.cursor = "default";
});
Even with that added, using the Element Inspector say in Chrome, you will see that the 'div' immediately below the 'div class="gm-style" ...' gets its cursor style explicitly changed to a 'url' of the hand when the InfoBox gets removed. Move the cursor just one pixel more, and the cursor style of that 'div' gets reset back to "default" by the Google Maps API.
So the problem is not with Browser inheritance of the cursor style. The Google Maps API is itself overriding the cursor style for that child 'div', and all its child 'divs', of which the map images are a part (and which the cursor is resting over when the InfoBox gets removed).
You should of-course file a bug report with Google. Maybe they'll fix this in V4 of the Google Maps API.
One possible work-around:
You might try re-positioning the InfoBoxs so they are three, five, or more pixels away from the Marker, and off-center say to the right or left of the Marker. Then when the cursor moves off the Marker (and triggers the MouseOut and the InfoBox removal) its not on top of the hidden portion of the InfoBox, but rather over a Map image tile. Thus it will behave just like moving off the Marker to the right, left, or bottom does now, and won't get overriden by the InfoBox removal. However, if the end-user is moving the cursor fast, or in the direction of the now off-center InfoBox, you'll still get the hand cursor appearing.
Another not really recommended possible work-around:
a. Do the first recommendation (the gap between Marker and InfoBox).
b. Get a handle to that particular 'div' by stepping through the immediate children of the "gm-style" div.
c. In the MouseOut handler, use a SetTimeout with a very short millisecond interval to re-override that 'div's' cursor style back to "default".
This would get rid of the hand cursor even during a fast cursor move over the off-center InfoBox. You'll still get a slight flicker, but it won't stay a hand cursor that way if the end-user stops moving the cursor. But that is monkeying deep into Google's map 'div' structure, and this work-around is not going to be reliable long-term.
Your solution is correct and the issue is with the marker icon being an image. Try changing that using google.maps.symbols
I have created a custom SVG path for your marker on your fiddle and it worked but the infoWindow is still flickering though.
Here is the icon symbol object
icon: {
path: 'M0,0 10,0 10,10 0,10 Z',
scale: 1,
fillColor: '#076EB5',
strokeColor: '#076EB5',
fillOpacity: 1,
}
Nice documentation on the symbols here

GMAPS API V3 Custom InfoWindow: static position

I really want to know if there's a way to make the InfoWindow display on the center of the screen and not above the marker.
Also, how can I get rid of that predefined crappy speech bubble style of the window itself?
When the marker gets clicked, the InfoWindow shall be displayed in the center of the screen with a width of 720px, a black opaque background and a little content (no speech bubble, no pan, just pure css). I cant find anything coming close to what I need.
I included the infobox.js to try to get what I want, but I got 2 problems with this:
It doesn't take my position: absolute and the given top/left values.
After closing the InfoBox once, it won't open again.
Some code that could be relevant:
// creating the box
var ib'.$counter.' = new InfoBox(myOptions);
// box options - just the style part
var myOptions = { boxStyle: { ,width: "720px" ,position:"absolute" ,top:
"-100px" ,left: "100" } };
// add listener - plane js
google.maps.event.addListener(marker'.$counter.', "click",
function() { ib'.$counter.'.show() });
I would really appreciate any kind of help!
Best regards,
Rellston.

how to create a padding around the edge of a google map

I have a very busy Google Maps app that I have built and I'm trying to create a "buffer zone" around the outside edge of the map so that the google map commands won't put things there. My solution was to create invisible divs and add them to the map as controls, one for each of the edges. This seems to work great as all of the google commands see them and adjust accordingly, and the map appears normally. For example, fitBounds ensures my bounds is not under the invisible layers. For the top where I have a control bar it's a perfect solution, but for the other edges where there is nothing, it creates a problem - I can't click on the map or info windows under these controls as they take the click event.
So I'm looking for one of 2 solutions:
1) can I make my invisible controls pass clicks through to the map, or;
2) is there a better way to pad the edge of the map; something that doesn't involve a much of math every time I want to call a fitBounds or panTo would be preferred as I automate a lot of map motion
Cheers
I managed to solve this.
The best way to add padding to your maps is with invisible controls. It creates the padding that all other map functions obey without any additional coding when call them. Here is how to do it for everyone else who needs this.
First.. I create a function to simplify creating the divs.
function createDummyDiv(w, h){
var out = $(document.createElement('div')).addClass('dummy-div').css('width', w).css('height', h);
return out[0];
}
Then I add the controls as needed. In this case I have the normal zoom control in the LEFT_CENTER position, so I had to create 2 for the left side. This creates a 10% padding on the left, right and bottom, and a 55px padding at the top under my own control bar.
map.controls[google.maps.ControlPosition.TOP_CENTER].push(createDummyDiv('100%', '55px'));
map.controls[google.maps.ControlPosition.LEFT_TOP].push(createDummyDiv('10%', '45%'));
map.controls[google.maps.ControlPosition.LEFT_BOTTOM].push(createDummyDiv('10%', '45%'));
map.controls[google.maps.ControlPosition.RIGHT_CENTER].push(createDummyDiv('10%', '100%'));
map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(createDummyDiv('100%', '10%'));
The.. the final fix to my problem is to put them behind the map layer with css.
.dummy-div{ z-index: -100 !important; }
I hope this helps someone else
Try to give the invisible DIV a negative z-index, e.g. -10
For me, fitBounds api worked itself with second parameter (padding)
Add padding to google map bounds

How to set default view in OpenLayers, WITHOUT restricting bounds?

Based on samples, I can see that you can set a default view in OpenLayers by saying something along the lines of:
var bounds = new OpenLayers.Bounds(-125, 25, -65, 50);
var map = new OpenLayers.Map('map', {restrictedExtent: bounds });
However, this also (as the name implies), restricts me to be able to ONLY navigate within these bounds. I can zoom out and see things outside of these bounds, but I can't then zoom back onto them, or scroll to them.
I've tried not having any restrictedExtent (or making it the entire map), but then I can't get it to focus on the area I want. I tried using:
map.setCenter(new OpenLayers.LonLat(0,0), 3);
console.log(map.getCenter());
To set the zoom and the center...but it doesn't seem to do ANYTHING, other than set the variable "center" which I can then read from map.getCenter() (if I don't set it, it's null, if I do set it, I can see it...but the map itself stays fully extended and it's center doesn't seem to change at all...)
The Map layer I am using is:
OpenLayers.Layer.OSM.Mapnik
with displayOutsideMaxExtent set to true... I'm really at a loss here.
My goal is to have a default region of the world zoomed in to and in view (such as the United States), with the option of viewers being able to go outside the default to view things.
I think I've figured it out. For whatever reason, the zoom was never changing, but the center apparently WAS moving (it was just so zoomed out I couldn't tell). Add to the fact that I needed to transform the center to use the google projection, and it seems to work just fine.
What I ended up doing was:
var lonlat = new OpenLayers.LonLat(20,37).transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913"));
map.setCenter(lonlat);
map.zoomTo(4);

Categories