i am getting only normal polygon line when my marker is placed on map.
#ionic/cli-utils : 1.19.2
ionic (Ionic CLI) : 3.20.0
global packages:
cordova (Cordova CLI) : 8.0.0
local packages:
#ionic/app-scripts : 3.1.8
Cordova Platforms : android 7.0.0
Ionic Framework : ionic-angular 3.9.2
System:
Android SDK Tools : 26.1.1
Node : v8.10.0
npm : 5.6.0
OS : Windows 10
Environment Variables:
ANDROID_HOME : C:\Users\w2s-pc\AppData\Local\Android\Sdk
Misc:
backend : pro
Code:
import { NavController } from 'ionic-angular';
import{LatLng,GoogleMaps,GoogleMap,GoogleMapsEvent,GoogleMapOptions,
CameraPosition,MarkerOptions,Polyline,Polygon,PolygonOptions,
Spherical,Marker} from '#ionic- native/google-maps';
import { Component } from "#angular/core/";
import { Geolocation } from '#ionic-native/geolocation';
#Component({
selector: 'home',
templateUrl: 'home.html'
})
export class HomePage {
map: GoogleMap;
me: any;
locations = []
constructor() { }
ionViewDidLoad() {
this.loadMap();
}
loadMap() {
let mapOptions: GoogleMapOptions = {
// camera: {
// target: {
// lat: this.me._x,
// lng: this.me._y
// },
// zoom: 18,
// tilt: 30,
// },
MyLocation:true,
MyLocationButton:true,
disableDefaultUI: true,
mapType: "MAP_TYPE_HYBRID",
};
let map= this.map = GoogleMaps.create('map_canvas', mapOptions);
// var div = document.getElementById("map_canvas");
// var map = new GoogleMaps()
// Wait the MAP_READY before using any methods.
this.map.on(GoogleMapsEvent.MAP_READY)
.subscribe(() => {
console.log('Map is ready!');
this.map.setMyLocationEnabled(true)
this.map.setMyLocationButtonEnabled(true)
this.map.on(GoogleMapsEvent.MAP_CLICK).subscribe((location: any) => {
console.log(location);
this.locations.push(new LatLng(location[0].lat, location[0].lng));
console.log(location);
let PolyLineInfo;
this.map.addPolygon({
'points' : this.locations ,
'strokeColor' : '# AA00FF' ,
'fillColor' : '# 00FFAA' ,
'strokeWidth' : 4 ,
'editable' :true,
}).then((info: Polyline) => {
// info.setPoints
PolyLineInfo = info;
}
);
this.map.addMarker({
animation: 'DROP',
draggable: true,
position: {
lat: location[0].lat,
lng: location[0].lng,
},
customInfo: this.locations.length - 1
})
.then(marker => {
marker.on(GoogleMapsEvent.MARKER_DRAG_END)
.subscribe((marker) => {
let index = marker[1].get("customInfo");
this.locations[index] = new LatLng(marker[0].lat, marker[0].lng);
PolyLineInfo.remove();
console.log(this.locations[0]);
console.log(this.locations[1]);
console.log(this.locations[2]);
let dis = Spherical.computeSignedArea(this.locations);
console.log(dis);
let km = Spherical.computeLength(this.locations);
console.log(km);
this.map.addPolygon({
'points' : this.locations ,
'strokeColor' : '# AA00FF' ,
'fillColor' : '#FF0000' ,
'strokeWidth' : 4 ,
'editable' :true,
}).then((info: Polyline) => {
PolyLineInfo = info;
}
);
});
})
});
});
}
}
i need to do like this using ionic version 3 on Google Map
https://github.com/mapsplugin/cordova-plugin-googlemaps-doc/blob/master/v2.0.0/class/Polygon/getPoints/README.md
var GORYOKAKU_POINTS = [
{lat: 41.79883, lng: 140.75675},
{lat: 41.799240000000005, lng: 140.75875000000002},
{lat: 41.797650000000004, lng: 140.75905},
{lat: 41.79637, lng: 140.76018000000002},
{lat: 41.79567, lng: 140.75845},
{lat: 41.794470000000004, lng: 140.75714000000002},
{lat: 41.795010000000005, lng: 140.75611},
{lat: 41.79477000000001, lng: 140.75484},
{lat: 41.79576, lng: 140.75475},
{lat: 41.796150000000004, lng: 140.75364000000002},
{lat: 41.79744, lng: 140.75454000000002},
{lat: 41.79909000000001, lng: 140.75465}//,
//{lat: 41.79883, lng: 140.75673}
];
var mapDiv = document.getElementById("map_canvas");
// Create a map with specified camera bounds
var map = plugin.google.maps.Map.getMap(mapDiv, {
camera: {
target: GORYOKAKU_POINTS
}
});
map.addEventListener(plugin.google.maps.event.MAP_READY, function() {
addEditablePolygon(map, GORYOKAKU_POINTS, function(polygon) {
// To do something...
});
});
function addEditablePolygon(map, points, callback) {
// Add a polygon
map.addPolygon({
'points': points,
'strokeColor' : '#AA00FF',
'fillColor' : '#00FFAA',
'width': 10
}, function(polygon) {
// polygon.getPoints() returns an instance of the BaseArrayClass.
var mvcArray = polygon.getPoints();
// Add draggable markers
mvcArray.map(function(latLng, cb) {
map.addMarker({
position: latLng,
draggable: true
}, cb);
}, function(markers) {
// If a marker is dragged, set the position of it to the points of the Polygon.
markers.forEach(function(marker, idx) {
marker.on(plugin.google.maps.event.MARKER_DRAG, function(position) {
mvcArray.setAt(idx, position);
});
});
callback(polygon);
});
});
}
Related
I am creating a marker where the map is clicked and I want to know if this marker is inside or outside the polygon. I use the containsLocation function for this, but I keep getting the following error "TypeError: b.get is not a function". Thank you in advance for your answers.
function App() {
const refPoly = useRef(null);
const [position, setPosition] = useState(null);
const center = {
lat: 25.774,
lng: -80.19,
};
const containerStyle = {
position: "absolute",
width: "70%",
height: "70%",
};
const bermudaTriangle = [
{ lat: 25.774, lng: -80.19 },
{ lat: 18.466, lng: -66.118 },
{ lat: 32.321, lng: -64.757 },
];
const google = window.google;
const onHandleClickMap = (event) => {
setPosition({ lat: event.latLng.lat(), lng: event.latLng.lng() });
console.log(
google.maps.geometry.poly.containsLocation(event.latLng, bermudaTriangle)
);
};
return (
<div className="App">
<LoadScript
googleMapsApiKey={GOOGLE_MAPS_API_KEY}
id="script-loader"
libraries={["geometry"]}
>
<GoogleMap
mapContainerStyle={containerStyle}
center={center}
zoom={18}
onClick={onHandleClickMap}
>
<Polygon
ref={refPoly}
paths={bermudaTriangle}
strokeColor="#0000FF"
strokeOpacity={0.8}
strokeWeight={2}
fillColor="#0000FF"
fillOpacity={0.35}
/>
{position && <Marker position={position} />}
</GoogleMap>
</LoadScript>
</div>
);
}
I had the same issue; I solved it like this:
Instead of:
const bermudaTriangle = [
{ lat: 25.774, lng: -80.19 },
{ lat: 18.466, lng: -66.118 },
{ lat: 32.321, lng: -64.757 },
];
...I wrote the bermudaTriangle like this:
const bermudaTriangle = new window.google.maps.Polygon({
paths: polygons[0].paths,
});
console.log(window.google.maps.geometry.poly.containsLocation(
{ lat: event.latLng.lat(), lng: event.latLng.lng() },
bermudaTriangle)
);
Hey vue-ers!
I am using vue2-google-maps with all its glories and so far I have managed a lot except for custom buttons within an info-window. So far I can click on a marker and it shows the related custom info-window with the right info. The only thing I am missing now is making those buttons work. For example the close button: I can click on it and it speaks to the component method but does not close it. The close button works the same as selecting the markers, but at the same time it's not? The values update to false, but not being updated in the maps, while I select a marker it updates like a charm. So I am quite stuck here and fairly confused, any help, ideas and tips are appreciated!
Here is my code for reference:
Template
<gmap-map
id="map"
:center="center"
:zoom=13
:options="{
disableDefaultUI: true,
zoomControl: true,
clickableIcons: true,
}">
<gmap-marker
v-for="(location, index) in locations"
:position="{lat: location.latitude, lng: location.longitude}"
:icon="location.icon"
:zone="location.zone"
:jettyNumber="location.jettyNumber"
:selected="location.selected"
:zIndex="location.zIndex"
#mouseover="mouseOverMarker(index)"
#mouseout="mouseOutMarker(index)"
#click="openInfoWindow(index)"
:label="{
text: location.jettyNumber.toString(),
color: '#fff',
fontSize: '13px',
fontFamily: 'din_round_otbold'
}">
<gmap-info-window
:opened="location.infoBoxOpen">
<div class="infoWindow" style="width: 300px;">
<div id="dock-zone" :class="getZoneClass(location.zone)">{{ getZoneClassText(location.zone) }}</div>
<h2 id="infoWindow-location">{{ location.name }}</h2>
<div id="close-btn" #click="closeInfoWindow(index)"></div>
<a class="btn btn-primary google-maps-infowindow-button">Kies als <b>{{ inputData.label }}</b></a>
<span></span>
</div>
</gmap-info-window>
</gmap-marker>
</gmap-map>
Component Script
import $ from "jquery";
export default {
data: function(){
return {
icons: {
stopInner: {
icon: process.env.VUE_APP_PUBLIC_URL + '/Assets/images/pinpoint_on_map_inner.svg'
},
stopOuter: {
icon: process.env.VUE_APP_PUBLIC_URL + '/Assets/images/pinpoint_on_map_outer.svg'
},
stopOutside: {
icon: process.env.VUE_APP_PUBLIC_URL + '/Assets/images/pinpoint_on_map_outside.svg'
},
stopSelected: {
icon: process.env.VUE_APP_PUBLIC_URL + '/Assets/images/pinpoint_on_map_active.svg'
}
},
locations: [],
center: {lat: 51.9004, lng: 4.46849},
inputData: {}
};
},
methods: {
initMap(locations, inputData) {
// Set maps specific data
for(var i = 0; i < locations.length; i++) {
locations[i].selected = false;
locations[i].infoBoxOpen = false;
locations[i].zIndex = locations[i].jettyNumber;
locations[i].icon = this.getIcon(locations[i].zone);
}
this.inputData = inputData;
this.locations = locations;
},
getIcon(zone) {
switch(zone){
case "centre":
return this.icons.stopInner.icon;
break;
case null:
return this.icons.stopOutside.icon;
break;
default:
return this.icons.stopOuter.icon;
break;
}
},
getZoneClass(zone) {
switch(zone){
case "centre":
return "centrum";
break;
case null:
return "buiten";
break;
default:
return "";
break;
}
},
getZoneClassText(zone) {
if(zone){
return zone;
}else{
return "outside";
}
},
// TODO: Not really setting the zindex, need to dig deeper
mouseOverMarker(locationIndex) {
this.locations[locationIndex].zIndex = 99998;
},
mouseOutMarker(locationIndex) {
this.locations[locationIndex].zIndex = this.locations[locationIndex].jettyNumber;
},
openInfoWindow(location){
this.center = {lat: location.latitude, lng: location.longitude};
this.setSelectedLocation(location);
},
setSelectedLocation(selectedLocationIndex){
this.unselectLocations();
// Set selected
this.locations[selectedLocationIndex].zIndex = 88888;
this.locations[selectedLocationIndex].icon = this.icons.stopSelected.icon;
this.locations[selectedLocationIndex].selected = true;
this.locations[selectedLocationIndex].infoBoxOpen = true;
this.center = {
lat: this.locations[selectedLocationIndex].latitude,
lng: this.locations[selectedLocationIndex].longitude
};
this.alterDefaultInfoWindowStyle();
},
unselectLocations() {
for(var i = 0; i < this.locations.length; i++) {
this.locations[i].icon = this.getIcon(this.locations[i].zone);
this.locations[i].zIndex = this.locations[i].jettyNumber;
this.locations[i].selected = false;
this.locations[i].infoBoxOpen = false;
}
},
alterDefaultInfoWindowStyle() {
// TODO: a very nasty fix, need a better way to handle this
setTimeout(function(){
var iwOuter = $('.gm-style-iw');
iwOuter.parent().parent().css({ top: '20px' });
iwOuter.css({ top: '0px' });
iwOuter.css({ left: '26px' });
var iwBackground = iwOuter.prev();
iwBackground.css({ 'display': 'none' });
var iwCloseBtn = iwOuter.next();
iwCloseBtn.hide();
iwOuter.children().eq(0).css({ overflow: 'visible' });
}, 10);
},
closeInfoWindow(selectedLocationIndex) {
this.unselectLocations();
},
closeMaps() {
this.$emit('close-maps')
}
}
}
Since the appearance of info window is determined by locations[index].infoBoxOpen the standard close handler (#closeclick) needs to be implemented as well, like this:
<gmap-info-window
:opened="location.infoBoxOpen"
#closeclick="location.infoBoxOpen=false">
...
</gmap-info-window>
I would also propose to modify the way how info window is created. Instead of creating info window per marker, to create only a single instance of info window. In addition to performance benefits it would make it more clear to manage info window state, for example:
<gmap-map :center="center" :zoom="zoom" ref="map">
<gmap-marker
:key="index"
v-for="(location,index) in locations"
:position="{lat: location.lat,lng:location.lng}"
:clickable="true"
#click="openInfoWindow(location)"
/>
<gmap-info-window v-if="selectedLocation !== null" :position="{lat: selectedLocation.lat,lng:selectedLocation.lng}" :opened="infoBoxOpen" #closeclick="closeInfoWindow()">
<div class="infoWindow">
<h2 id="infoWindow-location">{{ selectedLocation.name }}</h2>
<button #click="closeInfoWindow()">Close</button>
</div>
</gmap-info-window>
</gmap-map>
export default {
data: () => ({
zoom: 5,
center: { lat: 59.339025, lng: 18.065818 },
selectedLocation: null,
infoBoxOpen: false,
locations: [
{
Id: 1,
name: "Oslo",
lat: 59.923043,
lng: 10.752839
},
{
Id: 2,
name: "Stockholm",
lat: 59.339025,
lng: 18.065818
},
{
Id: 3,
name: "Copenhagen",
lat: 55.675507,
lng: 12.574227
},
{
Id: 4,
name: "Berlin",
lat: 52.521248,
lng: 13.399038
},
{
Id: 5,
name: "Paris",
lat: 48.856127,
lng: 2.346525
}
]
}),
methods: {
openInfoWindow(location) {
this.selectedLocation = location
this.infoBoxOpen = true;
},
closeInfoWindow() {
this.infoBoxOpen = false;
}
}
};
Here is a demo that demonstrates how to manage info window per multiple markers
I'm going to initalize infowindows (for google map markers) through angular controller (i'm using ng-map module)
NgMap.getMap().then (map) ->
$scope.map = map
for marker in markers
latLng = new (google.maps.LatLng)(marker.latitude, marker.longitude)
#initialize infoWindows through google map api, not ng-map module
contentString = 'is an example string'
infoWindow = new (google.maps.InfoWindow)(content: contentString)
$scope.dynMarkers.push new (google.maps.Marker)(position: latLng)
marker.addListener 'click', ->
infoWindow.open map, marker
$scope.markerClusterer = new MarkerClusterer(map,$scope.dynMarkers, {})
I have an error in console:
marker.addListener is not a function
I can't use an ng-map 'infowindow' DOM element in my view.
What's wrong?
marker object needs to be of google.maps.Marker type, try to replace:
$scope.dynMarkers.push new (google.maps.Marker)(position: latLng)
marker.addListener 'click', ->
infoWindow.open map, marker
with
markerObject = new (google.maps.Marker)(position: latLng) #<-Marker object
$scope.dynMarkers.push markerObject
markerObject.addListener 'click', ->
infoWindow.open map, markerObject
Example
angular.module('mapApp', ['ngMap'])
.controller('mapController', function ($scope, NgMap) {
NgMap.getMap().then(function (map) {
$scope.map = map;
$scope.dynMarkers = [];
$scope.markers.forEach(function (marker) {
var latLng = new google.maps.LatLng(marker.latitude, marker.longitude);
var contentString = 'is an example string'
var infoWindow = new (google.maps.InfoWindow)({ content: contentString });
var dynMarker = new google.maps.Marker({ position: latLng });
$scope.dynMarkers.push(dynMarker);
google.maps.event.addListener(dynMarker, 'click', function () {
infoWindow.open(map,dynMarker);
});
});
var mcOptions = { imagePath: 'https://cdn.rawgit.com/googlemaps/js-marker-clusterer/gh-pages/images/m' };
$scope.markerClusterer = new MarkerClusterer(map, $scope.dynMarkers, mcOptions)
});
$scope.markers = [
{ id: 1, name: 'Oslo', latitude: 59.923043, longitude: 10.752839 },
{ id: 2, name: 'Stockholm', latitude: 59.339025, longitude: 18.065818 },
{ id: 3, name: 'Copenhagen', latitude: 55.675507, longitude: 12.574227 },
{ id: 4, name: 'Berlin', latitude: 52.521248, longitude: 13.399038 },
{ id: 5, name: 'Paris', latitude: 48.856127, longitude: 2.346525 }
];
});
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script src="https://rawgit.com/allenhwkim/angularjs-google-maps/master/build/scripts/ng-map.js"></script>
<script src="https://googlemaps.github.io/js-marker-clusterer/src/markerclusterer.js"></script>
<div ng-app="mapApp" ng-controller="mapController">
<ng-map default-style="true" zoom="3" center="59.339025, 18.065818">
</ng-map>
</div>
Let's say I have a bunch of markers (over 100) I want to add from this:
module.exports = [
{ value: 'Varrock', lng: 22.5, lat: -15.52249812756166, popular: 1 },
{ value: 'Lumbridge', lng: 25.9661865234375, lat: -43.644025847699496, popular: 1 },
{ value: 'Monastery', lng: -4.0924072265625, lat: -5.714379819235291 },
{ value: 'Edgeville', lng: 2.4884033203125, lat: -6.0094592380595495, popular: 1 },
{ value: 'Varrock Palace', lng: 22.412109375, lat: -6.882800241767556 },
{ value: 'Digsite', lng: 46.043701171875, lat: -17.266727823520508 },
{ value: 'River Salve', lng: 54.931640625, lat: -14.083301314706778 },
{ value: 'Morytania', lng: 64.610595703125, lat: -13.501814172428656 },
{ value: 'Mort Myre Swamp', lng: 59.820556640625, lat: -22.740723091194727 }
];
It uses browserify to get it. So, I do this:
var locations = require('./locations');
What would be the best way to add all of those into LayerGroup()? I mean, because doing var fairy = L.layerGroup([One, Two, Three...]); by hand would get tiresome.
So how would I go about adding all of those markers into a new layer (so I can toggle them on/off)
How about adding an empty L.LayerGroup, looping over your array and adding them to that layer?
var locations = [];
var layer = L.layerGroup().addTo(map);
locations.forEach(function (location) {
L.marker([location.lat, location.lng])
.bindPopup(location.value)
.addTo(layer);
});
Working example on Plunker: http://plnkr.co/edit/Q0DGqs?p=preview
Currently, I am displaying 500-600 Markers on Google map, with their names as tooltip. Now,
I need to display the tool-tip of all overlapping markers as comma-separated i.e. Marker1, Marker2, Marker3 etc. if Marker1, Marker2, Marker3 are overlapped on map.
I found many other different examples on google map at internet especially at GeoCodeZip, but not of my requirement.
if this requirement is once filled, Am afraid of performance issues on zoom changed events, as tooltip needed to be updated (if overlapping is changed).
Update1 : I have already show Overlapping Marker spiderfier to client but not acceptable.
Does anyone have right path or working example ?
Thanks
-Anil
The core of this is to find the pixel distance between LatLngs. Then before adding each marker check the pixel distance between it and any existing markers. If there is another marker nearby add to the title otherwise create a new marker. jsFiddle
function init() {
var mapOptions = {
center: new google.maps.LatLng(0, -0),
zoom: 4,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map-canvas'),mapOptions);
// to get the pixel position from the latlng
// https://stackoverflow.com/questions/1538681/how-to-call-fromlatlngtodivpixel-in-google-maps-api-v3
var overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
google.maps.event.addListenerOnce(map, 'idle', function() {
if (overlay.getProjection()) {
var points = [
{ latlng: new google.maps.LatLng(40, -100), title: '1' },
{ latlng: new google.maps.LatLng(40.125, -100.125), title: '2' },
{ latlng: new google.maps.LatLng(40.25, -100.25), title: '3' },
{ latlng: new google.maps.LatLng(40.5, -100.5), title: '4' },
{ latlng: new google.maps.LatLng(40.75, -100.75), title: '5' },
{ latlng: new google.maps.LatLng(41, -101), title: '6' },
{ latlng: new google.maps.LatLng(35, -95), title: '7' },
{ latlng: new google.maps.LatLng(45, 105), title: '8' },
{ latlng: new google.maps.LatLng(25, -115), title: '9' },
{ latlng: new google.maps.LatLng(55, -85), title: '10' },
{ latlng: new google.maps.LatLng(30, -34), title: '11' }
];
// for each point
var markers = [];
points.forEach(function (point) {
var nearby = false;
var pointPixelPosition = overlay.getProjection().fromLatLngToContainerPixel(point.latlng);
markers.forEach(function(marker) {
var markerPixelPosition = overlay.getProjection().fromLatLngToContainerPixel(marker.getPosition());
// check for marker 'near by'
if (Math.abs(pointPixelPosition.x - markerPixelPosition.x) < 10 || Math.abs(pointPixelPosition.y - markerPixelPosition.y) < 10) {
nearby = true;
marker.setTitle(marker.getTitle() + ', ' + point.title);
}
});
// create new marker
if (!nearby) {
markers.push(new google.maps.Marker({ map: map, position: point.latlng, title: point.title }));
}
});
}
map.setCenter(new google.maps.LatLng(39.8282, -98.5795));
});
}