I am using Bing Maps v8 and I would like to get the Infobox to be a little smart on where it shows.
Here is a CodePen of what I have. If you hover over the pushpin, you'll notice that the infobox shows towards the top and is thus cut off from view.
function loadMapScenario() {
var map = new Microsoft.Maps.Map(document.getElementById('myMap'), {
credentials: 'Your Key Here',
center: new Microsoft.Maps.Location(51.50632, -0.12714)
});
var pinLocation = new Microsoft.Maps.Location(51.663088, -0.204133);
var pushpin = new Microsoft.Maps.Pushpin(pinLocation, null);
var infobox = new Microsoft.Maps.Infobox(pinLocation, { title: 'Map Center', description: 'London, UK', visible: false });
infobox.setMap(map);
Microsoft.Maps.Events.addHandler(pushpin, 'mouseover', function () { infobox.setOptions({ visible: true }) });
map.entities.push(pushpin);
}
Is there a way to make that smart, so that it always shows towards the centre of the map, this way it'll always be in view.
I have found this which moves the map about so that the infobox is within view, but that is not what I'm after. I don't want the map moving about, just the infobox to show towards the centre of the map.
There is a custom infobox module available that provides this exact functionality. It will reposition itself so that it is always in view. You can find this module here: http://bingmapsv7modules.codeplex.com/wikipage?title=Custom%20Infobox%20Control
It is supported in Bing Maps V7 and V8.
Related
First off, I'm trying to create something like this using Angular.js: https://foursquare.com/explore?mode=url&near=San%20Francisco%2C%20CA&q=comedy
In summary, here are the tools I've tried:
Mapbox.js
Leaflet.js
Angular-Leaflet directive
For each, I've attempted to create a directive that would manage a list of locations that is associated with a map displaying those locations such that, when the user hovers over a list item, a tooltip appears above the location's marker on the map, and when they hover atop the location's marker on the map, a tooltip appears above that marker. (If this isn't clear, just visit the link above.) Hyperlinks, image, etc. should be able to appear within the tooltip. None of the above seem to give me the map portion of this functionality straight out of the box. Also, in order to even get markers to appear on the map, I have to essentially break away from idiomatic Angular, since the markers are vector items that are generated via the Leaflet/Mapbox toolkit. Writing this code feels wrong. Yes, I'm able to see the marker, but I can't really associate them with anything in the DOM. I'm confused.
I'm just at a loss for how to create a smart, interactive map that is associated with other elements on my page. Libraries like Angular-leaflet allow you to get a map on your page pretty easily, but customization is PAINFUL (or so it seems). Is Angular.js, in combination with any of the above three tools, the way to go? Is there something I'm simply failing to understand?
in angular-leaflet-directive, you can bind marker events.
here is an example that implements the dragend event (taken from here). you should be able to use the mouseover event, get the hovered marker from the events arguments and show it's popup.
var app = angular.module("demoapp", ["leaflet-directive"]);
app.controller('MarkersSimpleController', [ '$scope', function($scope) {
var mainMarker = {
lat: 51,
lng: 0,
focus: true,
message: "Hey, drag me if you want",
draggable: true
};
angular.extend($scope, {
london: {
lat: 51.505,
lng: -0.09,
zoom: 8
},
markers: {
mainMarker: angular.copy(mainMarker)
},
position: {
lat: 51,
lng: 0
},
events: {
markers: [ 'dragend' ]
}
});
$scope.$on("leafletDirectiveMarker.dragend", function(event, args){
$scope.position.lat = args.model.lat;
$scope.position.lng = args.model.lng;
});
} ]);
I want my open layers map to fit the full screen. I want users to be able to navigate inside, zoom, and drag it.
Here's a fiddle to work on : http://jsfiddle.net/mhicauber/t8K4p/1/
My problème is that I don't understand some values I'm giving at map creation :
mapLayer = new OpenLayers.Layer.Image(
'My map',
'http://tchanca.com/private/Masse1080.jpg',
OpenLayers.Bounds.fromString("-160,-90.0,160,90.0"), new OpenLayers.Size(screenSize.width, screenSize.height), {
maxExtent: OpenLayers.Bounds.fromString("-160,-90.0,160,90.0")
});
With those values, user is able to drag a part of the map out of screen. If I change the maxExtent values to 0,0,0,0, well, map is contained in the screen and can't be dragged outside but as soon as I zoom in, I'm unable to drag the map.
What are the -160,-90.0,160,90.0 values refering to please ? What code should I put to :
make the map fit the screen at loading
allow user to zoom and drag it
but restrict dragging to screen size ?
Thank you very much. And please excuse my lack of knowledge on cartography, I'm pretty noob on the subject...
For those of you who come here and are using OpenLayers 3, here is some information that might be useful.
There is no more restrictedExtent. Instead you have to set the 'extent' option in your layers and view.
There is also no more OpenLayers.Bounds. Instead you use ol.extent, which is a an array with 4 values.
Example:
var maxExtent = ol.proj.transformExtent([-122.445717,47.576989,-122.218094,47.71623], 'EPSG:4326', 'EPSG:3857')
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'watercolor'
}),
extent: maxExtent
}),
new ol.layer.Tile({
source: new ol.source.Stamen({
layer: 'terrain-labels'
}),
extent: maxExtent
})
],
target: 'map',
view: new ol.View({
center: ol.proj.transform(
[-122.333407, 47.607436], 'EPSG:4326', 'EPSG:3857'),
extent: maxExtent,
zoom: 14
})
});
I think the property you're actually looking for is restrictedExtent. The restrictedExtent controls the portion of the map the user is able to pan around. If you don't restrict the zoom level then the user will still be able to zoom out to view the rest of the map, but they won't be able to pan the map.
Firstly, rather than using OpenLayers.Bound.FromString("-160,-90.0,160,90.0"), you should probably use new OpenLayers.Bounds(-160, -90, 160, 90).
In the case of (-160, -90, 160, 90) (possibly the whole map?), this means the user is free to pan around those coordinates, if this is the whole map then it's not restricting anything.
In the case of restricting the extent to (0, 0, 0, 0) - the centre of the map, the user is not able to pan anywhere - the map is always fixed over the center spot - but they may still zoom freely because that is not controlled by restrictedExtent.
The values in (-160, -90, 160, 90") are coordinates in degrees - it's a bounding box (left, bottom, right, top). There are all sort of different coordinate systems that can be used, you can explicitly specify which coordinate system you're going to use with projection: "EPSG:3857".
In the case of a custom map layer like yours, they're just coordinates in relation to the bounds you pass in when creating the layer.
To solve your problem:
I create the map layer with the bounds new OpenLayers.Bounds(-180,-90.0,180,90.0) and set a restrictedExtent on the map (rather than the layer) with the same bounding box.
map = new OpenLayers.Map('map', {
controls: [],
restrictedExtent: new OpenLayers.Bounds(-180, -90, 180, 90)
});
mapLayer = new OpenLayers.Layer.Image(
'My map',
'http://tchanca.com/private/Masse1080.jpg',
new OpenLayers.Bounds(-180,-90.0,180,90.0),
new OpenLayers.Size(screenSize.width, screenSize.height),
{}
);
map.addLayer(mapLayer);
Since your mapLayer occupies the full extent of the map the user can't zoom out beyond it to see any white margin, and also can't pan outside it since nothing exists beyond it.
JSFiddle
Here is another approach for OpenLayers3. Depending on what you want to refer to the easiest way is to get the extent directly from your desired projection (ol.proj.Projection) or layer (any class of ol.layer) using the getExtent() function. In case of EPSG:3857 this works:
var map = new ol.Map({
...
view: new ol.View({
...
extent: ol.proj.get("EPSG:3857").getExtent()
})
});
I created a very basic answer here at this gist: https://gist.github.com/cfh294/e4495b9ff6d989db950ccd2573422808#file-restrictedextent-js
The "meat and potatoes":
map.on("movestart", function(evt) {
panStartCenter = view.getCenter();
});
map.on("moveend", function(evt) {
var panEndCenter = view.getCenter();
var x = panEndCenter[0];
var y = panEndCenter[1];
});
// if the center no longer resides in the max extent, snap the map back to where it was
// before the pan
if (!(ol.extent.containsXY(maxExtent, x, y))) {
view.setCenter(ol.Coordinate(panStartCenter));
}
});
Hi i am currently working on angular Google maps https://github.com/dylanfprice/angular-gm
i am facing difficulties in setting the bounds and map center
<gm-map gm-map-id="'infoWindows'" gm-center="options.map.center" gm-zoom="options.map.zoom" gm-bounds="bounds" gm-map-options="options.map" class="map">
<gm-markers gm-objects="clinics"
gm-get-lat-lng="{ lat: object.practice.latitude, lng: object.practice.longitude }"
gm-get-marker-options="{ title: object.practice.name }"
gm-on-click="clk = object; infoWindow.open(marker.getMap(), marker);">
</gm-markers>
</gm-map>
make sure your map is already loaded.
therefor it is highly recommended to use promises.
var gmapPromise = angulargmContainer.getMapPromise('<mapId>');
gmapPromise.then(function(gmap) {
$scope.myGoogleMap = gmap;
});
In your case would be 'infoWindows'.
as there is to less context in your question, i can't really give you an answer what is wrong with your particular code but i'll give you some snippet which is always useful:
$scope.updateGoogleMap = function(map, options) {
// triggers a resize of the map and sets the correct center position
// requires a google map object and a google maps mapOptions object
$timeout(function(){
google.maps.event.trigger(map, 'resize');
map.setOptions(options);
});
};
a Google Maps mapOption object looks like this:
{
center: new google.maps.LatLng(47.123, 10.123),
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
as ng-hide/show lead to some google maps resize misbehaviour, you might wanna call this when toggling views.
**by the way, if your are using the gm-map-options tag with a valid google.maps.MapOptions, you don't need the the extra 'gm-bounds', 'gm-zoom' or 'gm-center' arguments
I've got one instance of google maps with fully customized options in my app.The users are able to switch to street view if they want to and come back all with the same instance of the map.
Is there a way to customize streetview controls when creating the map instance, along with the other map options?
I can not see any documentation on how to do that on the main map, while if you directly instantiate a the street view on a separate dom element you can do that like this:
var panoramaOptions = {
zoomControl: false,
linksControl: false,
panControl: false
}
var panorama = new google.maps.StreetViewPanorama(document.getElementById("map_streetview"), panoramaOptions)
mymap.setStreetView(panorama)
Any hint?
You may access the streetView-property of a map(no matter if custom or default) by using the getStreetView()-method of the map.
Use the setOptions()-method of the streetView to set the options:
mymap.getStreetView().setOptions(panoramaOptions);
I'm converting an application that uses v2 of the google maps api to v3. As part of this I've had to upgrade the MarkerManager to the v3 version too.
I have a bit of an odd issue in that Markers are not showing until the user zooms the map, then they appear.
If I then zoom back to the original zoom level the markers remain, so it is not a min\max zoom issue. There are no errors reported in firebug\javascript console and if I put a breakpoint or console.log at the location where the marker is added, it's definitely being added.
The application is fairly large, so I can't put all the source here, but the code where the markers are added is as follows:
console.log("Adding Marker");
markerManager.addMarker(marker, 1, 19);
markerManager.refresh();
And the code where marker is created is similar to this:
var latLng = new google.maps.LatLng(y, x);
var marker = new MarkerWithLabel({
position: latLng,
title: "title",
labelClass: "marker",
labelContent: "Test",
icon: icon,
labelAnchor: new google.maps.Point(26, 32)
});
and icon is just a google.maps.MarkerImage. MarkerManager and MarkerWithLabel are documented here:
http://google-maps-utility-library-v3.googlecode.com/svn/tags/markermanager/1.0/docs/reference.html
http://google-maps-utility-library-v3.googlecode.com/svn/tags/markerwithlabel/1.1.7/docs/reference.html
EDIT: I should add that before doing anything with the marker manager after creating it I have the following, so I'm not trying to add anything until it's loaded:
google.maps.event.addListenerOnce(markerManager, 'loaded', function () {
Anybody have any suggestions on where my mistake is likely to be?
I've found a fix for this, though I'm not really sure what other ramifications there might be to this. Basically in markermanager.js I replaced the following (~line 130)
google.maps.event.addListener(map, 'dragend', function () {
me.onMapMoveEnd_();
});
google.maps.event.addListener(map, 'zoom_changed', function () {
me.onMapMoveEnd_();
});
with this and the markers appear as expected. I'm still open to other ideas as I'd prefer not to be editing the markermanager file and I'm not sure of the performance (or other) impact of doing this
google.maps.event.addListener(map, 'idle', function () {
me.onMapMoveEnd_();
});
EDIT: Looking at the markermanager.js dev version, the have all 3 events in there. So it may just be worth using v1.1 if anybody else has this issue:
http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markermanager/src/markermanager.js