Google Maps and Openlayers 3 integration example - google-maps

I'm using the Open Layers 3 example located at...
http://openlayers.org/en/v3.0.0/examples/google-map.html
...and I have had some success.
The problem I am running into is getting my OL3 vector and MapServer layers to be projected correctly over the web-Mercator Google Map.
I have used the example as a template but it has not worked.
Currently all MapServer and Vector layers are projected as ESPG:4326 but need to be in Web-Mercator to line up with the under lying google map.
Any help is greatly appreciated!!

You could try the OL3-Google-Maps library, one that combines the use of Google Maps API and OpenLayers together, and see if it fits your needs.
It's not a perfect solution, so be sure to read about the Limitations of the library.

The actual answer that I have implemented is here...
If this helps you please up-vote it to off-set the down-votes this received.
http://openlayers.org/en/v3.0.0/examples/google-map.html
If you need to use google imagery in you OpenLayers map this is the way to do it.
If you are using SPA MVC AngularJS architecture make sure that you make your call to the google API in your page early enough and notice that this example loads both a google div and a OpenLayers div then combines them at the end of loading...so if anything errors or stops the loading process after initialization you will see two div's the google div first and the OpenLayers div under it...once all errors are resolved and you process is able to execute ...
olMapDiv.parentNode.removeChild(olMapDiv);
gmap.controls[google.maps.ControlPosition.TOP_LEFT].push(olMapDiv);
you will see the maps combined.
If you are transforming data from EPSG:4326 to EPSG:3857 you will want to change your view projection to...
var view = new ol.View({
projection: 'EPSG:3857',
// make sure the view doesn't go beyond the 22 zoom levels of Google Maps
maxZoom: 21
});
and you will also want to transform and data points you have coming in, I did it like this...
*shape = data points from data base
var geoJsonObj = {
'type': 'Feature',
'geometry': JSON.parse(shape),
'name': 'YourName',
'id': YourName.YourID
}
var vectorSource = new ol.source.Vector({
features: (new ol.format.GeoJSON()).readFeatures(geoJsonObj, { defaultDataProjection: "EPSG:4326", featureProjection:"EPSG:3857"})
});
YourLayer = new ol.layer.Vector({
title: YourName.YourID,
source: vectorSource,
id: YourName.YourID,
name: 'YourName',
label: response.DataList[key].Label,
fill: response.DataList[key].Color,
stroke: defaultStrokeHex,
style: function (feature, resolution) {
var text = resolution * 100000 < 10 ? response.DataList[key].Label: '';
if (text != "") {
styleCache[text] = [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#319FD3',
width: 1
}),
text: new ol.style.Text({
font: '12px Calibri,sans-serif',
text: text,
fill: new ol.style.Fill({
color: '#000'
}),
stroke: new ol.style.Stroke({
color: '#fff',
width: 3
})
}),
fill: new ol.style.Fill({
color: Utility.convertHex(response.DataList[key].Shade, '0.5')
})
})];
}
else if (text == "") {
styleCache[text] = [new ol.style.Style({
fill: new ol.style.Fill({
color: Utility.convertHex(response.DataList[key].Shade, '0.5')
})
})
]
} return styleCache[text];
}
});
There is obviously more than you need in the vector layer example above.
...an addendum to the code above
If you want the ability to turn off the satellite imagery layer below you vector data or map-server layers you can not combine the "olmap" and "gmap" div so comment those lines out and add this style to both you "gmap" and "olmap" div's
<div id="gmap" style="padding: 0px; width: 100vw; height: 90vh;z-index: 0; position:absolute"></div>
<div id="olmap" style="padding: 0px; width: 100vw; height: 90vh;z-index: 1; position:absolute"></div>
the only difference being the "z-index" and now you will have control to set the visibility on your "gmap" div dynamically...

Related

Vue 3 google map circle is not being removed from the map

Vue 3 google map circle is not being removed from the map
I am currently migrating from Vue 2 to Vue 3.
In Vue 2 I could remove circles,
but in Vue 3 I run into the problem that the circles first disappear when removed.
But when zoom-in and zoom-out they reappear.
I do use the .setMap(null) method for removing the circles.
I use the circles to show a geofence for a POI (point of interest) and
This geofence also has a marker in the centre and I can remove the marker without any problems.
Has anyone else encountered the same problem?
Is this a problem people also run into in other frameworks?
How I create the map circles and markers
public LoadPoiMarkersAgain (
googleMapLoader: IGoogleMapLoader
): HTMLMapMarker[] {
const markers: HTMLMapMarker[] = []
for (let i = 0; i < googleMapLoader.mapPoiData.length; i++) {
const marker = createHTMLMapMarker({
latlng: new google.maps.LatLng(
{
lat: googleMapLoader.mapPoiData[i].latitude,
lng: googleMapLoader.mapPoiData[i].longitude
},
null,
true
),
map: googleMapLoader.map,
data: googleMapLoader.mapPoiData[i],
html: this.CreatePoiMarkerHTML(
googleMapLoader,
googleMapLoader.mapPoiData[i]
)
})
const markerCircle = new google.maps.Circle({
strokeColor: '#FF0000',
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: '#FF0000',
fillOpacity: 0.35,
map: googleMapLoader.map,
center: new google.maps.LatLng(
{
lat: googleMapLoader.mapPoiData[i].latitude,
lng: googleMapLoader.mapPoiData[i].longitude
},
null,
true
),
radius: googleMapLoader.mapPoiData[i].radius
})
this.AddClickListenerToPoiMarker(marker, map)
markers.push(marker)
markerCircle.set('poiId', googleMapLoader.mapPoiData[i].poiId)
googleMapLoader.mapCircles.push(markerCircle)
}
return markers
}
How I remove the circles
public RemoveMapMarkersData (
googleMapLoader: IGoogleMapLoader
): void {
if (googleMapLoader.mapCircles.length > 0) {
googleMapLoader.mapCircles.forEach(
(element: google.maps.Circle) => {
element.setMap(null)
}
)
googleMapLoader.mapCircles = []
}
// Some more code to remove markers
}
What i have tried
attempt 1
I tried using
element.setVisible(false)
This does not work either.
attempt 2
I tried changing the order for when the circle is removed versus the marker.
This does not work either.
attempt 3
I also tried removing the circle
Immediately after, I added them to the map.
That does seem to work.
public LoadPoiMarkersAgain (
googleMapLoader: IGoogleMapLoader
): HTMLMapMarker[] {
// previous code
googleMapLoader.mapCircles.forEach((circle: google.maps.Circle) => {
circle.setMap(null)
})
// previous code
}
Could it be that Vue 3,
Is not passing the references correctly to my method?
Package
enter link description here
Google documentation
Google docs remove circle
Google docs remove marker
Extra
I have a gif that demonstrates the problem.
When I drag the map it should remove the circle.
But when zooming in and out, the circle reappears.
https://i.gyazo.com/b7310cc4d748da36e026104aff6cb2fe.gif
I have also created two sandboxes to demonstrate the problem:
(When you move your mouse out of the map, the circles will be removed)
Vue 2
Vue 2 + google maps
Vue 3
Vue 3 + google maps
I believe I encountered the same issue whilst migrating from Vue 2 to Vue 3, where markers were successfully being removed upon setVisible(false) but were then reappearing upon zoom.
Seeing console errors relating to Proxy led me to believe that the cause of the issue was due to the differences in the reactivity systems of Vue 2 and Vue 3 (helpful article on Vue 3 reactivity).
For me the fix was to use markRaw() when creating the map, which essentially returns the Map Object itself without converting to a proxy.
<script>
import { markRaw } from 'vue'
export default {
methods: {
initMap () {
map = markRaw(new google.maps.Map(document.getElementById("map"), {...}))
}
}
}
</script>
Sadly enough I could not fix the problem in proper way,
but I have a place holder solution for now.
My place holder solution is to remove the map when removing the circles and markers. After removing the map I render / reinitialise the map again.
Vue 3 - remove map when removing circles
If I can remove the circles and markers as intended by google,
Then I will post an update on this again.

How do I add Polylines to a Google Map app in Flutter?

I have a map app that I am building in Flutter and I want to add a campus map, which will be an overlay from a remote kml file eventually. In the first instances I just want to show something on the map, so I grabbed some co-ordinates form that kml file and added them to a List.
List<LatLng> building = [
LatLng(-2.2320211911239767, 53.475459515730925),
LatLng(-2.231763699058547, 53.47504046853617),
LatLng(-2.231605784002795, 53.47507219654),
LatLng(-2.2317965561189794, 53.47536812388608),
LatLng(-2.2317697340288305, 53.47537251389184),
LatLng(-2.231845506433501, 53.475498626591325),
];
I have a set of type markers and a set of type polyline
final Set<Marker> _residences = {};
final Set<Polyline> _campusOverlay = {};
I have this code in my _onMapCreated method
setState(() {
//Show Sample Building Marker
/* _residences.add(
Marker(
markerId: MarkerId('Building'),
position: _userLocation,
infoWindow: InfoWindow(
title: 'This is the title', snippet: 'This is a snippet'),
icon: BitmapDescriptor.defaultMarker,
),
);*/
_campusOverlay.add(
Polyline(
polylineId: PolylineId('Building'),
visible: true,
points: building,
width: 2,
color: Colors.red,
),
);
});
In my GoogleMap widget, I have added the markers and polylines properties.
GoogleMap(
onMapCreated: _onMapCreated,
polylines: _campusOverlay,
markers: _residences,
...
...
The marker(commented out atm) shows with no problems, but the polyline doesn't. I have seen a number of articles with this code, and I have no build errors, so I am confused as to why nothing is shown.
Am I missing something really obvious here?
[EDIT] -> Added screenshot. The co-ordinates were added to google maps (proper) and this is was is expected.
The issue wasn't with the code, but more the co-ordinates. I grabbed them from a remote KML file that I have access to. Below is an example.
-2.2346792602577352,53.46763821573774,0
I have restricted the map to my city and these co-ordinates are in the middle of the Indian ocean. These seem to be the correct way around.
53.46763821573774, -2.2346792602577352
What I can't understand is how the KML file shows the the overlay at the correct place at the moment. Not the final answer to my problem as I want to read this remote KML file and display the overlay, but for the time being, this is answered for what I wanted to do.

How to remove one marker from markerCluster

I am using Ionic 3 with #ionic-native/google-maps (https://github.com/ionic-team/ionic-native-google-maps/blob/master/documents/README.md).
I am using markerCluster to populate the map with markers.
At the moment, to update the markers, I am performing a map.clear(), as it can be seen in the code below.
The problem I have is that the markers are "flashing" when the map is clearing and the new one are created. By "flashing", I am trying to say that you can see how it disappears and appears again.
Is there a way to remove a marker from markerCluster, instead of clearing the map?
I am using this code to show on map some locations with some updates.
E.g.:
the pin is green if available
the pin is blue if in used
remove pin if offline
So, I am calling the WS to get the status every few seconds and update the pins icons based on the status.
I have tried markerCluster.remove(), instead of map.clear(), but the pin is not removed from the map.
this.map.clear();
markerCluster = this.map.addMarkerClusterSync({
markers: this.markers,
icons: [
{
min: 2,
max: 9,
url: this.assetsPath + "images/pin_cluster.png",
label: {
color: "black",
fontSize: 15,
},
size: { width: 40, height: 40 }
}],
boundsDraw: false
});

custom control position for street view google map

I am using street view on my site with pancontrols and zoomControls in it. For now google provides us some defined positions like RIGHT_CENTER etc. I want my custom position using css, I have taken help from this link Google Maps API V3 custom controls position but it is not working may be because it is for Road map and I need for street view. The code which I have used for calling street view is
function initialize() {
var fenway = new google.maps.LatLng(42.345573, -71.098326);
var panoOptions = {
position: fenway,
pov: {
heading: 280.19,
pitch: -22.444,
zoom:0.2
},
addressControl: false,
panControlOptions: {
position: google.maps.ControlPosition.RIGHT_CENTER
},
panControl: true,
zoomControlOptions: {
style: google.maps.ZoomControlStyle.SMALL,
position: google.maps.ControlPosition.RIGHT_CENTER
},
enableCloseButton: false
};
var panorama = new google.maps.StreetViewPanorama(
document.getElementById('map-canvas'), panoOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);
Thanks in Advance.
Check Custom Street View examples and this CUSTOM STREET VIEW FIDDLE
AFAIK you must link your panorama to the image of the streetview, thats nice if you want to make your own street view, if you want to get a google one, you must get the URL to force the view enter in streetview.
function getCustomPanoramaTileUrl(pano, zoom, tileX, tileY) {
// Note: robust custom panorama methods would require tiled pano data.
// Here we're just using a single tile, set to the tile size and equal
// to the pano "world" size.
return 'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQTaHe0F0J39SXbiRF43pz2wtyfD6kypCMrLxhWPkq9EACNgwO0iaMbJFM';
}
You have everything that you need to do this in the answer that you linked to above. You can pick from one of two choices:
The hack... This isn't recommended because if google maps decides to
change their layout, your code will break. To do this for
streetview, inspect the streetview window to find which 'gmnoprint'
you want to move. As an example, putting this after the panorama
load, moves the controls:
setTimeout( function() {
$($('div.gmnoprint')[4]).css({left: '-300px', background: 'red'});
}, 1000);
The best way to do it, as suggested at Google Maps API V3 custom controls position is to hide the streetview controls, create your own controls, and put them wherever you like. This takes much more effort, but it will not break when the streetview layout changes.

OpenLayers, how restricting WMS layer extent

I'm able to create an OpenLayers Map with maxExtent and restrictedExtent properties.
Also I have play with WMS layer and its maxExtent property, but the problem comes when use singleTile in the WMS layer.
What I want is to have a WMS layer that gets only one image from server but restricted to the bounds I want. Because this I used singleTile=true, ratio=1 and maxExtend=my_desired_extent.
But it always request the whole map view.
Any ideas how to achieve it.
Thanks in advance.
Next code shows a map with a base layer and a costline line layer I would like to use in singleTile mode and limiting the are they must request to WMS:
<script type="text/javascript" src="http://openlayers.org/api/2.11/OpenLayers.js"></script>
<div id="map" style="width: 700px; height: 500px;"></div>
<script type="text/javascript">
var map = new OpenLayers.Map("map");
var wms = new OpenLayers.Layer.WMS("OpenLayers WMS Basic", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'basic'
});
map.addLayer(wms);
var restricted = new OpenLayers.Layer.WMS("Coast Line", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'coastline_01,coastline_02'
},
{
opacity: 0.6,
singleTile: true,
ratio: 1,
isBaseLayer: false,
maxExtent: OpenLayers.Bounds.fromString("-10,-90,30,90")
});
map.addLayer(restricted);
map.setCenter(new OpenLayers.LonLat(0,40), 3);
</script>
I'm looking at OpenLayers source and seems what I want is not implemented so I need to create some WMS subclass or redefine some WMs layer methods.
I would appreciate any help.
Thanks.
If you are looking at restricting the whole map to the extent your talking about and not allowing users to pan outside of the extent you can try something like the following.
var extent = new OpenLayers.Bounds({-10,-90,30,90});
function init() {
var options = {
restrictedExtent: extent
};
map = new OpenLayers.Map('map', options);
var restricted = new OpenLayers.Layer.WMS("Coast Line", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'coastline_01,coastline_02'
},
{
opacity: 0.6,
singleTile: true,
ratio: 1,
isBaseLayer: false
});
map.addLayer(restricted);
The difference here is that I have set the extent on the whole map not just the layer. Note that you will need to control the maximum zoom level as well. If you don't a user can still zoom out and data passed the extents will be shown though they will not be able to pan the view on the map.
If you want the map to pan outside of the extent specified but just not that layer then there are a number of approaches.
If you have access the the WMS server that the layer is served from you could add a setting there to restrict the extent of the layer server.
Check this link http://docs.geoserver.org/latest/en/user/webadmin/data/layers.html and read the "Bounding Boxes Section"
If you don't have access to the WMS server and you just want to restrict the area that is requested from the WMS server from the client side you could try using the OpenLayers.layer.WMS class with a different strategy. See below for an example:
var myfilter = new OpenLayers.Filter.Spatial({
type: OpenLayers.Filter.Spatial.BBOX,
value: OpenLayers.Bounds.({-10,-90,20,90})})
var filterStrategy = new OpenLayers.Strategy.Filter({filter: myFilter});
var restricted = new OpenLayers.Layer.WMS("Coast Line", "http://labs.metacarta.com/wms/vmap0",
{
layers: 'coastline_01,coastline_02'
},
{
opacity: 0.6,
singleTile: true,
ratio: 1,
isBaseLayer: false,
strategies: [filterStrategy]
});
map.addLayer(restricted);
Please note that I have not tested this code and it may take a little refining to get it to work.