mapbox moveend trigger on click only - mapbox

Ive build a map with custom markers and popups just like in this mapbox-tutorial. Besides I have a custom menu with links to fly to those locations and open the associated popups with moveend-event. This works fine so far.
Now I also have a link which zooms out again to fit all markers in viewport. But this also triggers the moveend-event if it gets clicked.
To understand what I mean: See fiddle and click "Washington" then "SF" then "Show all". I dont understand why moveend triggers with "Show all".
Heres a fiddle
HMTL
<div id="map"></div>
<div id="menu">
<span class="link" data-lat="-77.032" data-lng="38.913" data-id="#marker0">Washington</span>
<span class="link" data-lat="-122.414" data-lng="37.776" data-id="#marker1">San Francisco</span>
<span class="showall">Show all</span>
</div>
JS
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-100, 37.8],
zoom: 0
});
var bounds = new mapboxgl.LngLatBounds();
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-77.032, 38.913]
},
properties: {
title: 'Mapbox',
description: 'Washington, D.C.'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.414, 37.776]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}
]
};
geojson.features.forEach(function(marker, index) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
el.id = 'marker' + index;
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({
offset: 25
}) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
bounds.extend(marker.geometry.coordinates);
});
function fitmarkers() {
map.fitBounds(bounds, {
padding: 120,
speed: 1.6
});
}
fitmarkers();
function triggermarker(id) {
map.on('moveend', function() {
$(id).trigger('click');
});
}
function fadeoutpopup() {
if ($('.mapboxgl-popup').length) {
$('.mapboxgl-popup').fadeOut(300, function() {
$(this).remove();
});
};
}
$('.link').click(function() {
$('span').removeClass('active');
$(this).addClass("active");
fadeoutpopup();
var markerid = $(this).data('id');
map.flyTo({
center: [$(this).data('lat'), $(this).data('lng')],
zoom: 11,
speed: 3
});
triggermarker(markerid);
});
$('.showall').click(function(f) {
fitmarkers();
fadeoutpopup();
});

What browser are you using? Why would triggering a moveEnd be a problem? In case you already are moving, this movement has to end, so that the new movement can start (zoom out to show all markers)
When checking your fiddle, it did only work for me after changing the padding to a smaller value than 120:
function fitmarkers(){
map.fitBounds(bounds, {padding: 10, speed: 1.6});
}
Please see the working code below:
(Please be aware, that you have shared your Mapbox access token. I have removed it from below code, but others could use it to generate cost for you)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Display a map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v2.0.0/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.0.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
#menu {
position:absolute;
top:0;
padding:20px 40px;
color:#FFF;
background-color:rgba(0,0,0,0.9);
}
#menu span {
margin:0 20px 0 0;
cursor:pointer
}
.link.active {
pointer-events:none;
color:orange
}
.marker {
background-image: url('https://docs.mapbox.com/help/demos/custom-markers-gl-js/mapbox-icon.png');
background-size: cover;
width: 50px;
height: 50px;
border-radius: 50%;
cursor: pointer;
}
.mapboxgl-popup {
max-width: 200px;
}
.mapboxgl-popup-content {
text-align: center;
}
</style>
</head>
<body>
<div id="map"></div>
<div id="menu">
<span class="link" data-lat="-77.032" data-lng="38.913" data-id="#marker0">Washington</span>
<span class="link" data-lat="-122.414" data-lng="37.776" data-id="#marker1">San Francisco</span>
<span class="showall">Show all</span>
</div>
<script>
mapboxgl.accessToken = 'YOUR ACCESS TOKEN';
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-100, 37.8],
zoom: 0
});
var bounds = new mapboxgl.LngLatBounds();
var geojson = {
type: 'FeatureCollection',
features: [{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-77.032, 38.913]
},
properties: {
title: 'Mapbox',
description: 'Washington, D.C.'
}
},
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-122.414, 37.776]
},
properties: {
title: 'Mapbox',
description: 'San Francisco, California'
}
}]
};
geojson.features.forEach(function(marker, index) {
// create a HTML element for each feature
var el = document.createElement('div');
el.className = 'marker';
el.id = 'marker'+index;
// make a marker for each feature and add to the map
new mapboxgl.Marker(el)
.setLngLat(marker.geometry.coordinates)
.setPopup(new mapboxgl.Popup({ offset: 25 }) // add popups
.setHTML('<h3>' + marker.properties.title + '</h3><p>' + marker.properties.description + '</p>'))
.addTo(map);
bounds.extend(marker.geometry.coordinates);
});
function fitmarkers(){
map.fitBounds(bounds, {padding: 10, speed: 1.6});
}
fitmarkers();
function triggermarker(id){
map.on('moveend', function(){
$(id).trigger('click');
});
}
function fadeoutpopup() {
if ($('.mapboxgl-popup').length) {
$('.mapboxgl-popup').fadeOut(300, function() { $(this).remove(); });
};
}
$('.link').click(function() {
$('span').removeClass('active');
$(this).addClass("active");
fadeoutpopup();
var markerid = $(this).data('id');
map.flyTo({
center: [$(this).data('lat'),$(this).data('lng')],
zoom: 11,
speed: 3
});
triggermarker(markerid);
});
$('span.showall').click(function(f) {
fitmarkers();
fadeoutpopup();
});
</script>
</body>
</html>

Related

How to dynamically adjust symbology based on user generated table

I have created a simple leaflet web app that allows for the user to search for the countries that they have traveled.
The user can use a search box or click on the layer on the map. either action will highlight the country green and load the name and flag in an adjacent table.
This works fine. However, problems arise should the user decide to remove a country visited (for example they made a mistake when selecting)
I have included the ability to delete the table items by user click and enabled a function on double click of the layer itself to reset the colour.
What I need is for these two actions to relate to one another. so if the user removes the flag, the related country is reset and vis versa.
I think I need some sort of listener on the click remove or highlight function or perhaps defining the symbology based on the user-generated table of countries visited. Any suggestions?
<!DOCTYPE html>
<html>
{% load static %}
{% load leaflet_tags %}
<head>
{% leaflet_js %}
{% leaflet_css %}
<script type="text/javascript" src="{% static 'dist/leaflet.ajax.js' %}"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>hello world</title>
<link rel="stylesheet" href="{% static 'leaflet-groupedlayercontrol/leaflet.groupedlayercontrol.min.css' %}" />
<link rel="stylesheet" href="https://labs.easyblog.it/maps/leaflet-search/src/leaflet-search.css" />
<link rel="stylesheet" href="https://labs.easyblog.it/maps/leaflet-search/examples/style.css" />
<style type="text/css">
#findbox {
background: #eee;
border-radius: 0.125em;
border: 2px solid #1978cf;
box-shadow: 0 0 8px #999;
margin-bottom: 10px;
padding: 2px 0;
width: 600px;
height: 26px;
}
.search-tooltip {
width: 200px;
}
.leaflet-control-search .search-cancel {
position: static;
float: left;
margin-left: -22px;
}
#map {
width: 50%;
height: 650px;
}
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<p style="text-align: center; font-size: 24px; color: #175b81; font-weight: bold;"></p>
<h3>My World Map</h3>
<div id="findbox"></div>
<div id="map" style="height: 680px; width: 48%; display: ;"></div>
<div class="sidebar" style="display: right;">
<p style="text-align: centre; font-size: 24px; color: #175b81; font-weight: bold;">My Flags:</p>
<table style="width: 90%;">
<tr>
<td id="name" hidden></td>
<td id="code" hidden></td>
</tr>
<ul id="Countries_Visted"></ul>
</table>
</div>
<script>
var img1 = "<img src=";
var im2 = ">";
var quotes = "'";
var flagimage_pt1 = "https://www.countryflags.io/";
var flagimage_pt2 = "/flat/64.png";
// creating mapbox basemap
var mapboxAccessToken =
"pk.eyJ1IjoiY2hyaXNyeWFuLXRlY2giLCJhIjoiY2thY2c3bDZyMDZsNDJ4cHJlZmhwZmFjaCJ9.3GuHRvRz-8fxi4r103z05w";
var mapbox = L.map("map").setView([46.0, 8.0], 2.2);
mapbox.doubleClickZoom.disable();
L.tileLayer(
"https://api.mapbox.com/styles/v1/chrisryan-tech/ckaxvc0bt10041iqfz5fb7dgj/tiles/256/{z}/{x}/{y}#2x?access_token=" +
mapboxAccessToken,
{
tileSize: 512,
zoomOffset: -1,
attribution:
'© Mapbox © OpenStreetMap',
}
).addTo(mapbox);
//loading data with style, click function and listener
var data_layer = new L.GeoJSON.AJAX("{% url 'borders_data' %}", {
style: countriesStyle,
onEachFeature: countriesOnEachFeature,
});
//listener - adding to map on load
data_layer.on("data:loaded", function (e) {
layer.addTo(mapbox);
});
function countriesStyle(feature) {
return {
fillColor: "grey",
weight: 2,
opacity: 0.2,
color: "grey",
dashArray: 3,
fillOpacity: 0.2,
};
}
function countriesOnEachFeature(feature, layer) {
layer.on({
click: function (e) {
var layer = e.target;
layer.setStyle({
weight: 1,
color: "#fff",
dashArray: "",
fillOpacity: 0.9,
fillColor: "green",
});
if (!L.Browser.ie && !L.Browser.opera && !L.Browser.edge) {
layer.bringToFront();
}
},
});
layer.on({
click: load_name_flag,
});
layer.on({
dblclick: clear,
});
}
///// clearing styling
var layer = data_layer;
function clear(e) {
layer.resetStyle(e.target);
}
///// adding to clicked countries to countries visted list
function load_name_flag(e) {
var field1 = document.getElementById("name");
field1.innerHTML = e.target.feature.properties.name;
var field2 = document.getElementById("code");
field2.innerHTML = e.target.feature.properties.iso2;
var selected_name_search = field1.innerHTML;
var selected_flag_search = img1 + quotes + flagimage_pt1 + field2.innerHTML + flagimage_pt2 + quotes + im2;
var selected_features_combine = selected_name_search + selected_flag_search;
$("#Countries_Visted").append("<li>" + selected_features_combine + "</li>").disabled = true;
}
</script>
<!- search box functionality - searches attribute data -->
<!- contained within Geojson from loaded event listener -->
<script src="https://unpkg.com/leaflet#1.3.0/dist/leaflet.js"></script>
<script src="https://labs.easyblog.it/maps/leaflet-search/src/leaflet-search.js"></script>
<script>
//pointing search function to map layer
var searchControl = new L.Control.Search({
container: "findbox",
layer: data_layer,
initial: false,
collapsed: false,
propertyName: "name",
marker: false,
});
// search box finds layer and adds country name and flag, changes layer symbol to green
searchControl.on("search:locationfound", function (e) {
var field1 = document.getElementById("name");
field1.innerHTML = e.layer.feature.properties.name;
var field2 = document.getElementById("code");
field2.innerHTML = e.layer.feature.properties.iso2;
var selected_name_search = field1.innerHTML;
var selected_flag_search = img1 + quotes + flagimage_pt1 + field2.innerHTML + flagimage_pt2 + quotes + im2;
var selected_features_combine = selected_name_search + selected_flag_search;
// styles for selected country
e.layer.setStyle({ fillColor: "green", color: "black", fillOpacity: 0.8 });
/// adding name and flag to countriesvisted list from searchbox select
$("#Countries_Visted").append("<li>" + selected_features_combine + "</li>").disabled = true;
});
mapbox.addControl(searchControl); //inizialize search control
// function to remove added layers
Countries_Visted.onclick = function remove(e) {
var li = e.target;
var layer = data_layer;
var listItems = document.querySelectorAll("li");
var ul = document.getElementById("ul");
li.parentNode.removeChild(li);
layer.resetStyle(e.target);
};
</script>
</body>
</html>

Use marker icon with only awesome fonts, no surrounding balloon

I have this code that works fine, but I need to get only the icon to show and not the "balloon" with its shadow.
I have tried with removing "markerColor..." but that is only changing to the default blue marker / balloon.
How to only show the icon and its size and color?
pointToLayer: function(feature, latlng) {
var con = feature.properties.concept;
var hub;
// icons for XX, YY and ZZ
if (kon === 'XX') {
hub = new L.marker(latlng, {icon: L.AwesomeMarkers.icon({icon: 'truck', prefix: 'fa', markerColor: 'cadetblue'}) });
} else if (kon === 'YY') {
hub = new L.marker(latlng, {icon: L.AwesomeMarkers.icon({icon: 'envelope', prefix: 'fa', markerColor: 'blue'}) });
} else if (kon === 'ZZ') {
hub = new L.marker(latlng, {icon: L.AwesomeMarkers.icon({icon: 'bicycle', prefix: 'fa', markerColor: 'darkblue'}) });
} else {
hub = new L.marker(latlng, {icon: L.AwesomeMarkers.icon({icon: 'envelope-o', prefix: 'fa', markerColor: 'red'}) });
}
return hub;
}
Unfortunately, Leaflet.awesome-markers plugin does not offer you the option to display only the inner icon (from Font Awesome or whatever source) without the surrounding balloon.
Same for its cloned version and other variations like Leaflet.extra-markers plugin.
But you can very simply use a Leaflet DivIcon instead:
Represents a lightweight icon for markers that uses a simple <div> element instead of an image. Inherits from Icon but ignores the iconUrl and shadow options.
Then you simply fill that <div> container with your Font Awesome icon, the same way you would do it in a normal page, and what the Leaflet.awesome-markers plugin does under the hood for you:
L.marker(latlng, {
icon: L.divIcon({
html: '<i class="fa fa-truck" style="color: red"></i>',
iconSize: [20, 20],
className: 'myDivIcon'
})
});
Note that you also have to specify a bit of CSS to customize it as you wish:
.myDivIcon {
text-align: center; /* Horizontally center the text (icon) */
line-height: 20px; /* Vertically center the text (icon) */
}
Example:
var map = L.map('map').setView([48.86, 2.35], 11);
L.marker([48.86, 2.35], {
icon: L.divIcon({
html: '<i class="fa fa-truck" style="color: red"></i>',
iconSize: [20, 20],
className: 'myDivIcon'
})
}).addTo(map);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
.myDivIcon {
text-align: center; /* Horizontally center the text (icon) */
line-height: 20px; /* Vertically center the text (icon) */
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" />
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet.awesome-markers#2.0.4/dist/leaflet.awesome-markers.css" />
<script src="https://unpkg.com/leaflet.awesome-markers#2.0.4/dist/leaflet.awesome-markers.js"></script>
<link href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" rel="stylesheet">
<div id="map" style="height: 180px"></div>

Can't load Leaflet inside Vue component

I am trying to create a Leaflet map as a Vue component but I am having some difficult getting started. I installed Leaflet through npm
Where am I going wrong? console.log(Leaflet) is returning a Leaflet object but I am having trouble getting the map to expand and render.
Some direction would be appreciated
<template>
<div id="map"></div>
</template>
<script>
// import leaflet here?
import Leaflet from 'leaflet';
export default {
components: {
Leaflet
},
created() {
console.log(this);
console.log(Leaflet);
},
ready() {
this.map = L.map('map').setView([51.959, -8.623], 14);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(this.map);
}
}
</script>
<style>
#map {
height: 100%;
width: 100%;
margin-top: -24px;
}
/* default legend, layer styling from leaflet template */
.info {
padding: 6px 8px;
font: 14px/16px Arial, Helvetica, sans-serif;
background: white;
background: rgba(255,255,255,0.8);
box-shadow: 0 0 15px rgba(0,0,0,0.2);
border-radius: 5px;
}
.info h4 {
margin: 0 0 5px;
color: #777;
}
.legend {
text-align: left;
line-height: 18px;
color: #555;
}
.legend i {
width: 18px;
height: 18px;
float: left;
margin-right: 8px;
opacity: 0.7;
}
</style>
There are a couple problems in your code:
There is not a ready lifecycle hook in Vue. Use mounted().
You are trying to pass the Leaflet library as a component to Vue, which does nothing since Leaflet is not a Vue component and does not need any sort of registering with Vue.
A map data property was not declared on the Vue component.
There is no problem with importing the library as Leaflet from 'leaflet', but it might be more consistent for yourself or others to declare the Leaflet object as L from 'leaflet'. You can also use: import { Map } from 'leaflet', but then must initialize your Map appropriately: this.map = new Map("mapContainer")
Prevent potential memory leaks and/or cleanup appropriately by using the remove() method on a Leaflet Map Class. A good spot is within the Vue beforeDestroy lifecycle hook.
Also, don't forget to import the Leaflet CSS, for example:
import "leaflet/dist/leaflet.css";
<template>
<div id="mapContainer"></div>
</template>
<script>
import "leaflet/dist/leaflet.css";
import L from "leaflet";
export default {
name: "LeafletMap",
data() {
return {
map: null
};
},
mounted() {
this.map = L.map("mapContainer").setView([51.959, -8.623], 12);
L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution:
'© OpenStreetMap contributors'
}).addTo(this.map);
},
beforeDestroy() {
if (this.map) {
this.map.remove();
}
}
};
</script>
<style scoped>
#mapContainer {
width: 100vw;
height: 100vh;
}
</style>
The correct answer was already provided by jhickok but was insightful for the vue3 composition API as well. The leaflet map can't be instantiated in setup() for the same reasons explained.
<template>
<div id="mapContainer"></div>
</template>
<script>
import { map, tileLayer } from "leaflet";
import { onMounted, onBeforeUnmount } from "vue";
export default {
name: "Map",
setup() {
let container = null;
onMounted(() => {
container = map("mapContainer").setView([51.959, -8.623], 12);
tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", {
attribution:
'© OpenStreetMap contributors'
}).addTo(container);
});
onBeforeUnmount(() => {
container.remove();
});
}
};
</script>
<style scoped>
#mapContainer {
width: 40vw;
height: 40vh;
}
</style>
first install leafletjs and vue2-leaflet with npm
second copy the code to your component
<template>
<div id="app" v-if="isLoad">
<l-map style="height: 350px" :zoom="zoom" :center="center" #click="addMarker" :max-zoom="maxZoom" :min-zoom="minZoom">
<l-tile-layer :url="url" :attribution="attribution"></l-tilelayer>
<l-marker :lat-lng="markerLatLng" ></l-marker>
</l-map>
</div>
</template>
<script>
import {LMap, LTileLayer, LMarker} from "vue2-leaflet";
import "leaflet/dist/leaflet.css";
import {Icon} from "leaflet";
delete Icon.Default.prototype._getIconUrl;
Icon.Default.mergeOptions({
iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
iconUrl: require("leaflet/dist/images/marker-icon.png"),
shadowUrl: require("leaflet/dist/images/marker-shadow.png")
});
export default {
components: {
LMap,
LTileLayer,
LMarker,
},
mounted() {
this.mapIsReady()
},
data() {
return {
isLoad: false,
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
attribution: '© OpenStreetMap contributors',
zoom: 15,
maxZoom:18,
minZoom:5,
center: [35.6892, 51.3890],
markerLatLng: [35.6892, 51.3890],
};
},
methods: {
mapIsReady() {
let self = this
setTimeout(() => self.isLoad = true, 1500)
},
addMarker(event) {
console.log(event)
this.markerLatLng = [event.latlng.lat,event.latlng.lng];
},
},
};
</script>
this code has add marker , max zoom and min zoom for your map
this code used open street map because it's free. you can change it to api.mapbox.com if you want but you need api key or accessToken
I just did this, but I needed basemaps too (bing).
leafletWrapper.js
const L = require('leaflet')
require('leaflet-bing-layer')
export default L
LeafletMap.vue
<template>
<div id="map">
</div>
</template>
<script>
import L from 'leafletWrapper'
export default {
name: 'leaflet-map',
props: ['center', 'zoom', 'minZoom', 'maxZoom', 'markers'],
data () {
return {
mapObject: {},
markerLayer: {}
}
},
mounted () {
const bingKey = 'foo'
this.mapObject = L.map(
"map", {
center: this.center,
zoom: this.zoom,
minZoom: this.minZoom,
maxZoom: this.maxZoom
}
)
L.tileLayer.bing({bingMapsKey: bingKey, imagerySet: 'Road'}).addTo(this.mapObject)
},
beforeDestroy () {
this.mapObject.clearAllEventListeners()
}
}
</script>

How to fix marker in center of leaflet map after user will drag the map?

I am using a custom map on my node add form. My marker is set to my current location using lat and log. Now I want, whenever a user will drag or move map, marker should be in center (fixed). I tried lot of things like:
$cordovaGeolocation.getCurrentPosition(options).then(function(position) {
$scope.latlong = position.coords.latitude + "," + position.coords.longitude;
$rootScope.lati= position.coords.latitude ;
$rootScope.long = position.coords.longitude;
$scope.map.center = {
lat: position.coords.latitude,
lng: position.coords.longitude,
zoom: 20
};
$scope.map.markers.now = {
lat: position.coords.latitude,
lng: position.coords.longitude,
message: "Usted esta aqui!",
draggable: false,
focus: true
};
if ($rootScope.locationresults == undefined) {
Util.getAddressOf(position.coords.latitude, position.coords.longitude).then(function(location) {
$rootScope.locationresults = location[0].formatted_address;
console.log(location);
}, function(error) {
console.error(error);
});
}
$scope.$on("leafletDirectiveMap.move", function(event, args) {
$scope.map.markers.now.setLatLng([0,0]).update();
//$scope.map.markers.now.lat = $scope.map.center.lat;
//$scope.map.markers.now.lng = $scope.map.center.lng;
console.info(JSON.stringify($scope.map.markers.now));
});
$scope.$on("leafletDirectiveMap.drag", function(event, args){
console.log(JSON.stringify($scope.map.center));
//$scope.map.markers.now.setLatLng(0,0);
$scope.map.markers.now.lat = $scope.map.center.lat;
$scope.map.markers.now.lng = $scope.map.center.lng;
});
$scope.$on("leafletDirectiveMarker.dragend", function(event, args) {
console.log("moviendo");
$rootScope.lati= args.model.lat ;
$rootScope.long = args.model.lng;
Util.getAddressOf(args.model.lat, args.model.lng).then(function(location) {
$rootScope.locationresults = location[0].formatted_address;
$scope.latlong = args.model.lat + "," + args.model.lng;
console.log(location);
}, function(error) {
console.error(error);
});
});
}, function(error) {
console.log(error);
});
You could place a fake marker, placing a div with background image on top of the map and placing it with absolute position and pointing always to the center of the map.
Example:
.map-container{
position: relative;
width: 300px;
height: 400px;
}
.map-marker-centered{
background-image: url('https://img.icons8.com/color/48/000000/marker--v1.png') no-repeat;
width: 50px;
height: 60px;
position: absolute;
z-index: 20;
left: calc(50% - 25px);
top: calc(50% - 60px);
transition: all 0.4s ease;
}
<div class="map-container">
<div class="map-marker-centered"></div>
<div class="map"></div>
</div>
Result:
You can place a "fake" marker composed from a background image placed always at the center of the map. You can also detect when map moves and get the coordinates to where the marker points to. Run the snippet:
var mymap = L.map('mapid').setView([51.505, -0.09], 13)
// add the OpenStreetMap tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{ subdomains: ['a', 'b', 'c'] })
.addTo(mymap)
mymap.on("moveend", function () {
console.log(mymap.getCenter().toString());
});
.map {
height: 280px;
z-index: 1;
}
.map-container {
position: relative;
width: 300px;
height: 300px;
}
.map-marker-centered {
background-image: url("https://img.icons8.com/color/48/000000/marker--v1.png");
width: 50px;
height: 48px;
position: absolute;
z-index: 2;
left: calc(50% - 25px);
top: calc(50% - 50px);
transition: all 0.4s ease;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css"/>
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<div class="map-container">
<div class="map-marker-centered"></div>
<div id="mapid" class="map"></div>
</div>

Mapbox search bar doesent load location

I have 2 toolbars in my scrpit one to add markers and another one to search locations but when i had both in the scrpit the location bar stop fiding location can you tell me why ? i am new at leaflet and mapbox
<style>
#geocoder-container {
position: absolute;
top: 0;
width: 100%;
margin-top: 10px;
}
#geocoder-container > div {
min-width:50%;
margin-left:25%;
}
</style>
<div id='map'></div>
<div id='geocoder-container'></div>
<script>
<!-- MAP Feature-->
L.mapbox.accessToken = 'pk.eyJ1Ijoib2JlY2VuZSIsImEiOiJjaXNicjdja3kwMDE3MnBvMGppMWpubDBqIn0.L4r0u_Em0utvCuFmqbsWQw';
var map = L.mapbox.map('map', 'mapbox.streets')
.setView([38.89399, -77.03659], 17);
var featureGroup = L.featureGroup().addTo(map);
<!-- MAP Feature-->
<!-- Tolbar eddit -->
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup
}
}).addTo(map);
map.on('draw:created', function(e) {
featureGroup.addLayer(e.layer);
});
var geocoder = new mapboxgl.Geocoder({
container: 'geocoder-container'
});
map.addControl(geocoder);
</script>
</body>
</html>