Google Maps Style Zoom Control - google-maps

I am using the Google Maps V3 Javascript API and would like to style the zoom control. Though the Google Documentation has information about moving the Custom Controls it doesn't seem to have any for styling the custom controls. https://developers.google.com/maps/documentation/javascript/controls#ControlModification
What I would like to do is be able to style the existing zoom control.
Is there a way to do style the EXISTING control? I would prefer to do this over creating a new custom control.

there's a option for that using google's map API and Custom Control setup, here's a fragment of the code I found:
var map;
var chicago = new google.maps.LatLng(41.850033, -87.6500523);
/**
* The ZoomControl adds +/- button for the map
*
*/
function ZoomControl(controlDiv, map) {
// Creating divs & styles for custom zoom control
controlDiv.style.padding = '5px';
// Set CSS for the control wrapper
var controlWrapper = document.createElement('div');
controlWrapper.style.backgroundColor = 'white';
controlWrapper.style.borderStyle = 'solid';
controlWrapper.style.borderColor = 'gray';
controlWrapper.style.borderWidth = '1px';
controlWrapper.style.cursor = 'pointer';
controlWrapper.style.textAlign = 'center';
controlWrapper.style.width = '32px';
controlWrapper.style.height = '64px';
controlDiv.appendChild(controlWrapper);
// Set CSS for the zoomIn
var zoomInButton = document.createElement('div');
zoomInButton.style.width = '32px';
zoomInButton.style.height = '32px';
/* Change this to be the .png image you want to use */
zoomInButton.style.backgroundImage = 'url("http://placehold.it/32/00ff00")';
controlWrapper.appendChild(zoomInButton);
// Set CSS for the zoomOut
var zoomOutButton = document.createElement('div');
zoomOutButton.style.width = '32px';
zoomOutButton.style.height = '32px';
/* Change this to be the .png image you want to use */
zoomOutButton.style.backgroundImage = 'url("http://placehold.it/32/0000ff")';
controlWrapper.appendChild(zoomOutButton);
// Setup the click event listener - zoomIn
google.maps.event.addDomListener(zoomInButton, 'click', function() {
map.setZoom(map.getZoom() + 1);
});
// Setup the click event listener - zoomOut
google.maps.event.addDomListener(zoomOutButton, 'click', function() {
map.setZoom(map.getZoom() - 1);
});
}
function initialize() {
var mapDiv = document.getElementById('map-canvas');
var mapOptions = {
zoom: 12,
center: chicago,
/* Disabling default UI widgets */
disableDefaultUI: true
}
map = new google.maps.Map(mapDiv, mapOptions);
// Create the DIV to hold the control and call the ZoomControl() constructor
// passing in this DIV.
var zoomControlDiv = document.createElement('div');
var zoomControl = new ZoomControl(zoomControlDiv, map);
zoomControlDiv.index = 1;
map.controls[google.maps.ControlPosition.TOP_LEFT].push(zoomControlDiv);
}
initialize();
you can see a working example here:
http://jsfiddle.net/maunovaha/jptLfhc8/

To style the buttons without only using the API, so allowing you to do more things, create the button controls via the API - as described above in #Picard answer - and attach to the div a cssClass property, then style the button as you wish:
var zoomOutButton = document.createElement('div');
zoomOutButton.className = 'zoom-out-btn';
then to style you simply add your rules:
.zoom-out-btn{ /** your rules **/ }
same with zoomInButton:
var zoomInButton = document.createElement('div');
zoomInButton.className = 'zoom-in-btn';
.zoom-in-btn{ /** your rules **/ }

You'll probably need to use JQuery for this as there aren't really any unique classes or IDs for the control. I used a technique similar to here: Styling standard Zoom control in Google Maps v3
Here's my version:
google.maps.event.addListener(map, 'tilesloaded', function() {
$('#map_canvas').find('img[src="https://maps.gstatic.com/mapfiles/szc4.png"]').parent('.gmnoprint').css('YOUR_STYLE_HERE', 'YOUR_VALUE_HERE');
});
So basically, the above selects the zoom control image, and then steps up one level to get the entire container. You may need to specify a different image than I did, this was for the "Small" version.

Related

Disable zoom with Openlayers

i'm using OpenLayers to display custom OSM maps on my website.
I've some points to respect: the map have to be fix (meaning that we can't drag it or zoom it).
I have a problem with the zoom, i can't manage to disable zoom with the mouse. Does anyone has a tip?
map = new OpenLayers.Map('map');
map.events.remove("move");
map.events.remove("movestart");
map.events.remove("moveend");
map.events.remove("zoomend");
map.events.remove("mouseover");
map.events.remove("mouseout");
map.events.remove("mousemove");
map.events.remove("zoomstart");
var nav = new OpenLayers.Control.Navigation({
defaultDblClick: function(event) { return ; }
});
map[index].addControl(nav);
Also, if someone has a tip to remove all Navigation events easier than that, it would be greatly appreciated.
Disable the default controls on your map by passing an empty array:
var map = new OpenLayers.Map('map', { controls: [] });
For OpenLayers3 the interaction array also needs to be empty.
var map = new ol.Map({
controls: [],
interactions: []
});
Simplifying approach of Mahdi results in
var i, l, c = map.getControlsBy( "zoomWheelEnabled", true );
for ( i = 0, l = c.length; i < l; i++ ) {
c[i].disableZoomWheel();
}
This way disabling zoom on mouse wheel doesn't require to customize options on constructing map e.g. by creating map without any control (though this was somewhat requested by Lght). In addition re-enabling zoom works equivalently.
In addition, by searching controls matching enabled property zoomWheelEnabled rather than class name it's supporting custom controls derived from OpenLayers.Control.Navigation.
You can do the following also:
map = new OpenLayers.Map({
// options here ...
}
var Navigation = new OpenLayers.Control.Navigation({
'zoomWheelEnabled': false,
'defaultDblClick': function ( event ) {
return;
}
});
map.addControl(Navigation);
var NavigationControls = map.getControlsByClass('OpenLayers.Control.Navigation')
, i;
for ( i = 0; i < NavigationControls.length; i++ ) {
NavigationControls[i].disableZoomWheel();
}
Found here.
For other options like disable dragging, you can take a look at the documentation and customize the above code.
Here is another easy way to restrict the zoom event based on some logic. Because OpenLayers doesnt provide a 'beforezoom'
map.zoomToProxy = map.zoomTo;
map.zoomTo = function (zoom,xy){
// if you want zoom to go through call
map.zoomToProxy(zoom,xy);
//else do nothing and map wont zoom
};
How this works:
For any kind of zooming activity, OpenLayers API ultimately calls the function called zoomTo. So before overriding it, we copy that function to a new function called 'zoomToProxy'. The we override it and add our conditional zoom logic. If we want the zoom to happen we just call new proxy function :)
You could reset the controls array and then add the Zoom and TouchNavigation to it.
var map_controls = [];
map_controls.push( new OpenLayers.Control.Zoom() );
map_controls.push( new OpenLayers.Control.TouchNavigation() );
var map = new OpenLayers.Map({
div: "map",
controls: map_controls
});
Hope it helps ! :)

Get non-wrapping map bounds in Google Maps API V3

If you zoom a google map out the world will start to repeat horizontally. Using .getBounds() seems to return the longitude at the edges of the displayed map image. But I would like to get minimum and maximum longitudes for the current view of the real world.
For example in this image .getBounds() says that the longitude ranges between 116 and 37 degrees (giving a width of -79 degrees!). The range I'm looking for is -244 to +37.
(or even -180 to +37 as this is the extremes of the world that is viewable around the map centre.)
And another example. Here I'm looking for -180 to +180 ...
You can try it for yourself here...
http://jsfiddle.net/spiderplant0/EBNYT/
(Apologies if this has been answered before - I did find some old similar questions but none seemed to have satisfactory answers).
I ran into the same issues today, but I think I finally figured it out.
In the first scenario above, you can use map.getBounds().toSpan() to get the width in longitude.....as long as the map did not wrap around.
For the second scenario where the map wraps around, I extended the google.maps.OverlayView() to get the google.maps.MapCanvasProjection object. From there you can call the function getWorldWidth().
It will give you the world width in pixel, then you can compare it with your map container's width. If your container is bigger, your map has wrapped around.
Don't know if the function is meant for this but it works.
The answer proposed by user1292293 worked for me (Google map api V3)
Extension of google.maps.OverlayView()
function MyMapOverlay() {}
MyMapOverlay.prototype = new google.maps.OverlayView();
MyMapOverlay.prototype.onAdd = function() {};
MyMapOverlay.prototype.draw = function() {};
MyMapOverlay.prototype.onRemove = function() {};
Add overlay to the map
var map = new google.maps.Map(domContainer, {...});
var overlay = new MyMapOverlay();
overlay.setMap(map);
check if map wraps around:
var proj = overlay.getProjection();
var wwidth = 0;
if (proj) wwidth = proj.getWorldWidth();
var mapsWrapsAround=false;
if (__wwidth > 0 && __wwidth < domContainer.width()) mapsWrapsAround = true;
I used the answer from rebpp to prevent the map from wrapping by setting the getWorldWidth. Here's the MapWrappingPrevent I created.
To use this just call
var wrapPreventer = new MapWrappingPrevent(_map);
/* This class prevents wrapping of a map by adjusting the max-width */
function MapWrappingPrevent(map) {
var self = this;
this.setMap(map);
map.addListener('zoom_changed', function () {
self.onZoomChanged();
});
}
MapWrappingPrevent.prototype = new google.maps.OverlayView();
MapWrappingPrevent.prototype.onAdd = function () { this.onZoomChanged(); };
MapWrappingPrevent.prototype.draw = function () { };
MapWrappingPrevent.prototype.onRemove = function () { };
MapWrappingPrevent.prototype.onZoomChanged = function () {
var proj = this.getProjection();
if (proj) {
var wrappingWidth = proj.getWorldWidth();
$(this.getMap().getDiv()).css({'max-width': wrappingWidth + 'px'})
}
};

google map v3 how fitbounds with zoom on user's location

I am using google v3, i want to fitbounds with center on userPinLoc object, i have the following code
var bounds = new google.maps.LatLngBounds();
bounds.extend(userPinLoc)// wants to center on userPinLocation
for (i in nearestEntitiesToZoom) {
entity = nearestEntitiesToZoom[i];
var googleLatLng = new google.maps.LatLng(entity.latitude,entity.longitude);
bounds.extend(googleLatLng);
}
bounds.extend(userPinLoc);
//googleMap.setCenter(userPinLoc) this not working
googleMap.fitBounds(bounds);
any quick fix after update i am pasting new code
function setInitialZoom() {
mapZoom = googleMap.getZoom();
var bounds = new google.maps.LatLngBounds();
bounds.extend(userPinLoc);
for (i in nearestEntitiesToZoom) {
entity = nearestEntitiesToZoom[i];
var googleLatLng = new google.maps.LatLng(entity.latitude,entity.longitude);
bounds.extend(googleLatLng);
}
google.maps.event.addDomListener(googleMap, 'bounds_changed', function() {
googleMap.setCenter(userPinLoc);
});
googleMap.fitBounds(bounds);
setTimeout(function() {
google.maps.event.clearListeners(googleMap, 'bounds_changed');
}, 3000);
}
Remove the setCenter from where it is currently. You need to have an event listener for when the map's bounds change. I think when you call fitBounds, you have to wait for it to redraw before you can adjust the centre. One way would be to use a timeout, but you can simply add this to your initialize function:
google.maps.event.addDomListener(googleMap, 'bounds_changed', updateCenter);
And then create a new function to update the centre, which takes the userPinLoc value (needs to be a global variable):
function updateCenter() {
googleMap.setCenter(userPinLoc);
}

How to create a text overlay in Google Maps API v3 that does not pan?

I'm using Google Maps API v3. I would like to create a text overlay on a map that does not move when the map is panned. Is the best approach to manipulate the DOM elements accessible from the MapPanes object or is it best to create a custom control even though it would not do much other than display text?
The simplest way that I found worked for me was a few lines of JavaScript added after I created a new map. So, after this:
map = new google.maps.Map('myMapDivId', mapOptions);
add this:
var myTitle = document.createElement('h1');
myTitle.style.color = 'white';
myTitle.innerHTML = 'Hello World';
var myTextDiv = document.createElement('div');
myTextDiv.appendChild(myTitle);
map.controls[google.maps.ControlPosition.BOTTOM_CENTER].push(myTextDiv);
You will probably want to style the text to look nicer.
An alternative is to put the div in your HTML:
<div id="myTextDiv" style="color: white; position: absolute;">
<h1>Hello World</h1>
</div>
and then do this in your JavaScript:
var myControl = document.getElementById('myTextDiv');
map.controls[google.maps.ControlPosition.TOP_CENTER].push(myControl);
NOTE an important difference: If you use the HTML route to define your div, you must set the position style to absolute in the HTML to avoid rendering problems.
From you're describing, the best approach would be a custom control. Docs for that are here. Custom controls can be as simple or a complicated as you want.
One reason why you would want to muck around with the map panes is if you wanted such a 'control' to lie underneath the markers / shadows / polylines etc. I'm doing this right now to show a crosshairs in the center of the map at all times. But because I keep it as an overlay, I choose the panes in such a way that the markers are above it, so they can continue to be clicked and interacted with - using the mapPane. Here's how I'm doing it:
var CrosshairOverlay = function(map){
this._holder = null;
this.setMap(map);
};
CrosshairOverlay.prototype = new google.maps.OverlayView();
CrosshairOverlay.prototype.onAdd = function(){
var map = this.getMap();
var holder = this._holder = $('<div>').attr('id', 'crosshair')[0];
var crosshairPaper = this._paper = R(holder, 150, 150);
// ... all your drawing and rendering code here.
var projection = this.getProjection();
var wrappedHolder = $(holder);
var updateCrosshairPosition = function(){
var center = projection.fromLatLngToDivPixel(map.getCenter());
wrappedHolder.css({left:center.x-75, top:center.y-75});
}
_.each(['drag','dragend','bounds_changed','center_changed','zoom_changed','idle','resize'], function(event){
google.maps.event.addListener(map, event, updateCrosshairPosition);
});
google.maps.event.addListener(map, 'maptypeid_changed', function(){
_.defer(updateCrosshairPosition);
});
this.getPanes().mapPane.appendChild(holder);
};
CrosshairOverlay.prototype.draw = function(){
};
CrosshairOverlay.prototype.onRemove = function(){
this._holder.parentNode.removeChild(this._holder);
this._holder = null;
};
The reason the maptypeid_changed has its own handler with a defer is because that event is fired before the map properly sets itself up when changing the type. Just run your function after the current event loop.

Google Map Click Event Issue with Kohana PHP

So this gets auto generated through the controller and I think I'm just overlooking something but the output is just like this
google.load("maps", "2.x", {"language" : "en"});
function initialize() {
if (GBrowserIsCompatible()) {
// Initialize the GMap
var map = new google.maps.Map2(document.getElementById("map"));
map.addControl(new google.maps.SmallMapControl());
map.setCenter(new google.maps.LatLng(30.226632, -97.935056), 10, G_NORMAL_MAP);
// Build custom marker icons
var tinyIcon = new google.maps.Icon();
tinyIcon.image = "http://labs.google.com/ridefinder/images/mm_20_red.png";
tinyIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";
tinyIcon.iconSize = new google.maps.Size(12,20);
tinyIcon.shadowSize = new google.maps.Size(22,20);
tinyIcon.iconAnchor = new google.maps.Point(6,20);
tinyIcon.infoWindowAnchor = new google.maps.Point(5,1);
// Show map points
var m1 = new google.maps.Marker(new google.maps.LatLng(35.2602340, -93.7939480), {icon:tinyIcon,bouncy:1});
google.maps.Event.addListener(m1, "click", function()
{
m1.openInfoWindowHtml(
'1<br />test,TX'
);
});
map.addOverlay(m1);
var m2 = new google.maps.Marker(new google.maps.LatLng(35.2810510, -93.8246510), {icon:tinyIcon,bouncy:1});
google.maps.Event.addListener(m2, "click", function()
{
m2.openInfoWindowHtml(
'test<br />test,Texas'
);
});
map.addOverlay(m2);
}
google.setOnLoadCallback(initialize);
So when i go to use a trigger event
google.maps.event.trigger(markers[m3], 'click');
Nothing happens, and I cant figure out the correct trigger to make it do so...
Based on the code sample you posted there is no markers[m3] defined, wouldn't you need to use google.maps.event.trigger(m2, 'click'); ? (m3 isn't defined at all in that code sample)