To be more precise, what I try to accomplish is that while I Drag a Google Map there\'s a Google Maps Marker that stays fixed
here i have added geo location button map with fixed pin to accurate your location
try it :)
function loadScript(src,callback)
{
var script = document.createElement("script");
script.type = "text/javascript";
if(callback)script.onload=callback;
document.getElementsByTagName("head")[0].appendChild(script);
script.src = src;
}
loadScript('https://maps.googleapis.com/maps/api/js?v=3&sensor=false&callback=initialize');
function initialize()
{
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 13,
});
latitudeTxt=document.getElementById('latitude');
longitudeTxt=document.getElementById('longitude');
marker = new google.maps.Marker({
map: map,
draggable: false,
animation: google.maps.Animation.DROP,
position: {lat: 59.327, lng: 18.067}
});
var position = marker.getPosition();
if(typeof position !== 'undefined')
{
map.setCenter(marker.getPosition());
}
map.addListener('center_changed', () => {
marker.setPosition(map.getCenter())
//get current location when we move the map
var NewMapCenter = map.getCenter();
var latitude = NewMapCenter.lat();
var longitude = NewMapCenter.lng();
latitudeTxt.innerHTML =latitude;
longitudeTxt.innerHTML =longitude;
})
addYourLocationButton(map, marker);
}
function geolocate()
{
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var geolocation = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
map.setCenter(geolocation);
});
}
}
function addYourLocationButton (map, marker)
{
var controlDiv = document.createElement('div');
var firstChild = document.createElement('button');
firstChild.style.backgroundColor = '#fff';
firstChild.style.border = 'none';
firstChild.style.outline = 'none';
firstChild.style.width = '28px';
firstChild.style.height = '28px';
firstChild.style.borderRadius = '2px';
firstChild.style.boxShadow = '0 1px 4px rgba(0,0,0,0.3)';
firstChild.style.cursor = 'pointer';
firstChild.style.marginRight = '10px';
firstChild.style.padding = '0';
firstChild.title = 'Your Location';
controlDiv.appendChild(firstChild);
var secondChild = document.createElement('div');
secondChild.style.margin = '5px';
secondChild.style.width = '18px';
secondChild.style.height = '18px';
secondChild.style.backgroundImage = 'url(https://maps.gstatic.com/tactile/mylocation/mylocation-sprite-2x.png)';
secondChild.style.backgroundSize = '180px 18px';
secondChild.style.backgroundPosition = '0 0';
secondChild.style.backgroundRepeat = 'no-repeat';
firstChild.appendChild(secondChild);
google.maps.event.addListener(map, 'center_changed', function () {
secondChild.style['background-position'] = '0 0';
});
firstChild.addEventListener('click', function () {
var imgX = 0,
animationInterval = setInterval(function () {
imgX = -imgX - 18 ;
secondChild.style['background-position'] = imgX+'px 0';
}, 500);
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
map.setCenter(latlng);
clearInterval(animationInterval);
secondChild.style['background-position'] = '-144px 0';
});
} else {
clearInterval(animationInterval);
secondChild.style['background-position'] = '0 0';
}
});
controlDiv.index = 1;
map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
}
body,html,#map_canvas{height:100%;margin:0;}
#map_canvas .centerMarker{
position:absolute;
/*url of the marker*/
background:url(http://maps.gstatic.com/mapfiles/markers2/marker.png) no-repeat;
/*center the marker*/
top:50%;left:50%;
z-index:1;
/*fix offset when needed*/
margin-left:-10px;
margin-top:-34px;
/*size of the image*/
height:34px;
width:20px;
cursor:pointer;
}
<html>
<body>
<div id="map_canvas" style="height:400px"></div>
<div id="latitude">latitude</div>
<br/>
<div id="longitude">longitude</div>
</body>
</html>
You can listen to the center changes via something like below, you will just have to update your view:
google.maps.event.addListener(map, "dragend", function() {
console.log(map.getCenter().toUrlValue());
});
Current main used solution is for bringing up the InfoWindow only when onclick, I needed it on all the time like it is on Uber, so I replaced even the InfoWindow to a css only solution, updating the view the normal angular route with Ionic
HTML:
<ion-content >
<div id="map" data-tap-disabled="true">
</div>
<div id="centerInfoBubble">
<span>{{locationCtrl.coordinates}}</span>
</div>
<div id="centerMarker"></div>
</div>
</ion-content>
CSS:
#map {
width: 100%;
height: 100%;
}
#centerInfoBubble {
position: absolute;
/*center the marker*/
top: 38%;
left: 22.5%;
z-index: 1;
width: 50%;
height: 6%;
border-radius: 20px;
border: 1px solid #111;
background-color: #444444;
color: #fff;
padding: 0.5% 5%;
cursor: pointer;
}
#centerMarker {
position: absolute;
/*url of the marker*/
background: url(http://maps.gstatic.com/mapfiles/markers2/marker.png) no-repeat;
/*center the marker*/
top: 45%;
left: 45%;
z-index: 1;
height: 10%;
width: 10%;
cursor: pointer;
}
Controller:
myModule.controller('LocationCtrl',['$scope','$cordovaGeolocation',function($scope,$cordovaGeolocation){
$scope.locationCtrl = {
coordinates : null
};
var options = {timeout: 10000, enableHighAccuracy: true};
var marker;
$cordovaGeolocation.getCurrentPosition(options).then(function(position){
var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
var mapOptions = {
center : latLng,
zoom : 16,
mapTypeId : google.maps.MapTypeId.ROADMAP,
mapTypeControl : false,
streetViewControl : false,
zoomControl : false
};
$scope.map = new google.maps.Map(document.getElementById("map"), mapOptions);
$scope.locationCtrl.coordinates = $scope.map.getCenter().toUrlValue();
google.maps.event.addListener($scope.map, "dragend", function() {
$scope.locationCtrl.coordinates = $scope.map.getCenter().toUrlValue();
$scope.$apply();
});
}, function(error){
console.log("Could not get location");
});
}]);
I don't know if there are performance issues with this yet, but looks quite smooth on the device, hope it helps someone
Rather than injecting an HTML component as suggested in @Dr.Molle's answer, why don't you use a CSS only solution.
It is simpler, more efficient and doesn't require you to even touch the DOM (so there won't be any problems if Google changes their implementation).
Also since Google Maps doesn't apply any styles on the container element (#map
) the solution is pretty safe.
#map {
position: relative;
}
#map:after {
width: 22px;
height: 40px;
display: block;
content: ' ';
position: absolute;
top: 50%; left: 50%;
margin: -40px 0 0 -11px;
background: url('https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi_hdpi.png');
background-size: 22px 40px; /* Since I used the HiDPI marker version this compensates for the 2x size */
pointer-events: none; /* This disables clicks on the marker. Not fully supported by all major browsers, though */
}
Here is a jsFiddle.
Here is how to do it as smooth as possible, and you can also get latlng at the same time.
var map;
var marker;
var myInterval = setInterval(move, 1000 / 60);
function handleEvent(event) {
var latlng = map.getCenter();
document.getElementById('lat').value = latlng.lat();
document.getElementById('lng').value = latlng.lng();
}
// Initialize and add the map
function initMap() {
var uluru = { lat: -25.344, lng: 131.036 };
map = new google.maps.Map(
document.getElementById('map'), { zoom: 4, center: uluru });
marker = new google.maps.Marker({
position: uluru,
map: map,
animation: google.maps.Animation.DROP
});
map.addListener('center_changed', handleEvent);
document.getElementById('lat').value = "-25.344";
document.getElementById('lng').value = "131.036";
}
function move(){
try {
var latlngMAP = map.getCenter();
var latlngMARKER = marker.getPosition();
tempLAT = lerp (latlngMARKER.lat(), latlngMAP.lat(), 0.1);
tempLNG = lerp (latlngMARKER.lng(), latlngMAP.lng(), 0.1);
var latlng = { lat: tempLAT, lng: tempLNG };
marker.setPosition(latlng);
} catch{
}
}
function lerp(start, end, amt) {
return (1-amt)*start+amt*end
}
If this can help, what I did is :
const myLatLng = {lat: 42, lng: 42};
map = new google.maps.Map(document.getElementById('map'), {
center: myLatLng,
zoom: 14,
});
marker = new google.maps.Marker({
position: myLatLng,
map: map,
});
map.addListener('center_changed', () => {
marker.setPosition(map.getCenter())
})
A different approach, that did not use a real google.maps.Marker
:
after the map has been initialized, inject a div into the map-container, give it a className(e.g. centerMarker
), the further things will be done via CSS:
.centerMarker{
position:absolute;
/*url of the marker*/
background:url(http://maps.gstatic.com/mapfiles/markers2/marker.png) no-repeat;
/*center the marker*/
top:50%;left:50%;
z-index:1;
/*fix offset when needed*/
margin-left:-10px;
margin-top:-34px;
/*size of the image*/
height:34px;
width:20px;
cursor:pointer;
}
Demo: http://jsfiddle.net/doktormolle/jcHqt/