I'm having some troubles trying to display 2 different markers placed at exactly the same coordinates.
The case is: we are displaying stores, and some of them are placed at the same building (ie. a mall), so, they are different stores but shares the same ubication/coordinates.
Our json source content looks like this:
{
"properties" : {
"id" : "1",
"name" : "Store 1"
},
"geometry" : {
"coordinates" : [-70.66667, -33.45],
"type" : "Point"
}
},
{
"properties" : {
"id" : "2",
"name" : "Store 2"
},
"geometry" : {
"coordinates" : [-70.66667, -33.45],
"type" : "Point"
}
}
The thing is, just one of them gets displayed.
My question is, is there an out of the box solution for this use-case? Or should we implement our own solution ?
Thanks in advance!
If you are using the Marker class from mapbox-gl, you can just apply standard CSS transform to offset the marker.
Another solution would be something refered to as "spider marker":
https://bewithjonam.github.io/mapboxgl-spiderifier/docs/index.html
https://github.com/bewithjonam/mapboxgl-spiderifier
One solution is setting an offset to the markers with same coordinates. This will put markers with same coordinates at the same height next to each other:
for (const marker of markers) {
// get all markers with the same coordinates
const sameMarkers = markers.filter(m => m.lat === marker.lat && m.lon === marker.lon);
// if there is more than one marker with the same coordinates
if (sameMarkers.length > 1) {
// get the index of the current marker
const index = sameMarkers.indexOf(marker);
// calculate the offset for the current marker
const offset = 32 * (index - (sameMarkers.length - 1) / 2);
// set the offset
marker.setOffset([offset, 0]);
}
}
Related
I use mapbox GL to referenced video games company based in Africa. All these company are placed on a map : https://africangamingnetworks.com/
When I have multiple markers with same coordinate for example two companies in Yaounde in Cameroon, mapbox shows just the first one, because they have the same latitude and longitude.
How could I do to show all markers with same coordinates ?
Thanks in advance.
<%# include file="/init.jsp"%>
<div class="shadow row">
<div class=" col-12 rounded-sm " id='map'
style='height: 800px;'></div>
</div>
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoia29zdGVkIiMWQzbXA3M2ZxYmd5MnkifQ.faOl-gGzibR9yMpZ-i7FTQ';
var map = new mapboxgl.Map({
container : 'map',
style : 'mapbox://styles/mapbox/streets-v11',
zoom : 2
// starting zoom
});
// Add zoom and rotation controls to the map.
map.addControl(new mapboxgl.NavigationControl());
var studioListComplete = [];
<c:forEach var="studio" items="${studioList}">
studioListComplete
.push({
"type" : "Feature",
"properties" : {
"description" : "<strong>${studio.studioName} (${studio.country})</strong> <br/><br/>" +
"${studio.studioDescription}<br/><br/>"+
"<strong>City : </strong>${studio.city}<br/>"+
"<strong>Number of employees : </strong>${studio.numberOfEmployees}<br/>"+
"<strong>Phone : </strong>${studio.phoneNumber}<br/><br/>"+
"Please visit our website",
"icon": "rocket"
},
"geometry" : {
"type" : "Point",
"coordinates" : [ "${studio.longitude}",
"${studio.latitude}" ]
}
});
//var marker = new mapboxgl.Marker()
//.setLngLat(["${studio.longitude}", "${studio.latitude}"])
//.addTo(map);
</c:forEach>
console.log(studioListComplete);
map.on('load', function() {
// Add a layer showing the places.
map.addLayer({
"id" : "places",
"type" : "symbol",
"source" : {
"type" : "geojson",
"data" : {
"type" : "FeatureCollection",
"features" : studioListComplete
}
},
"layout" : {
"icon-image" : "{icon}-15",
'icon-size': 1,
"icon-allow-overlap" : true
}
});
// When a click event occurs on a feature in the places layer, open a popup at the
// location of the feature, with description HTML from its properties.
map.on('click', 'places', function(e) {
var coordinates = e.features[0].geometry.coordinates.slice();
var description = e.features[0].properties.description;
// Ensure that if the map is zoomed out such that multiple
// copies of the feature are visible, the popup appears
// over the copy being pointed to.
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
new mapboxgl.Popup().setLngLat(coordinates).setHTML(description)
.addTo(map);
});
// Change the cursor to a pointer when the mouse is over the places layer.
map.on('mouseenter', 'places', function() {
map.getCanvas().style.cursor = 'pointer';
});
// Change it back to a pointer when it leaves.
map.on('mouseleave', 'places', function() {
map.getCanvas().style.cursor = '';
});
});
</script>
<style>
//Style is here
</style>
If you'd like two discrete markers to display for points with the same coordinates, the best thing to do is to slightly modify the latitude and longitude of one of the points so that it is not directly on top of the other one.
Alternatively, if it is not an option to modify the coordinate data, you could explore clustering your data so that it is visually clear that multiple companies are located within the same cluster. This example shows how to create and style clusters using a default circle layer, and this example shows how the visual clusters can be highly customized.
I've 1 annotation inside the map to select a place , after drag and drop the annotation i should take the new annotation lang,lat , however after drag and drop the annotation the lang , lat still show the old credentials .
i am not able to get new annotation credentials , any idea ?
var MapModule = require('ti.map');
var mapView = MapModule.createView({
mapType : MapModule.TERRAIN_TYPE,
height : '50%',
width : Ti.UI.FILL,
top : 1,
zoom : 12,
region : {
latitude : 33.373296399867975,
longitude : 44.35598730468746,
latitudeDelta : 0.6,
longitudeDelta : 0.6
},
userLocation : true,
animate : true,
annotations : []
});
win.add(mapView);
annotation = MapModule.createAnnotation({
latitude : dalel.latitude,
longitude : dalel.longitude,
title : L('long_press_then_move'),
subtitle : L('drag_drop_anotion'),
draggable : true,
});
mapView.annotations = [annotation];
and here how i get lang lat of the annotation :
data.longitude = mapView.annotations[0].longitude;
data.latitude = mapView.annotations[0].latitude;
I never got exactly that to work :-(
Instead I implemented a "long click" event to set the annotation in a new place and remove the old one. And it actually turns out that this is better also from the user's perspective as it can sometimes be difficult to drag the annotation - especially if you need to drag it near the edges of the visible map or even beyond.
So I suggest you consider that option. Whether it will work for you is obviously dependent on the functionality of your app.
/John
To receive the new location of the dragged pin listen to the pinchangedragstate event of the Map View.
I have used viz chart library. I have given some drill down functionality on the column graph. For that I have to select any column of the graph to see the detail for the selected part (in the same page).
Now I want to select my first column/bar of the column graph automatically. It means when I go to the graph page, the first bar should be selected as default and the detail of the selected bar should be there.
Please help me guys.
Code:
View:
<viz:ui5.Column id="chart" selectData="goToDaily" width="auto">
<viz:plotArea>
<viz:ui5.types.VerticalBar colorPalette="#FFCC00"/>
</viz:plotArea>
<viz:title>
<viz:ui5.types.Title text="Monthly">
</viz:ui5.types.Title>
</viz:title>
<viz:dataset>
<viz:ui5.data.FlattenedDataset id="fds1" >
<viz:dimensions>
<viz:ui5.data.DimensionDefinition id="dim" axis="1" name="Month" value="{name}">
</viz:ui5.data.DimensionDefinition>
</viz:dimensions>
<viz:measures>
<viz:ui5.data.MeasureDefinition id="mea" name="Values" value="{value}">
</viz:ui5.data.MeasureDefinition >
</viz:measures>
</viz:ui5.data.FlattenedDataset>
</viz:dataset>
</viz:ui5.Column>
Controller:
Oninit:
JSONmodel = new sap.ui.model.json.JSONModel();
data1 = [ {
name : "Jan",
value : 100,
},
{
name : "Feb",
value : 150,
},
{
name : "March",
value :120,
},
{
name : "April",
value : 200,
}
];
JSONmodel.setData(data1);
sap.ui.getCore().byId("idPage3--chart").setModel(JSONmodel);
Select Data for Chart:
goToDaily:function(evt){
sap.ui.getCore().byId("idPage3--chart").selection({ctx:[{dii_a1:1}]});
}
I have tried to select month Feb as default selection, but not able to select it.
Regards,
Niket Talati
There are quite a few things incorrect in your code
You have specified an event handler for selectData but this is obviously only triggered when you first "select data". You never fire an event for data selection in your code, so the event handler will only be triggered if you click on a column manually
It seems you tried to fire the event from the event handler (which is the other way around, see previous point), but you have never implemented the fireSelectData method.
In addition, the signature of the map you tried to select is incorrect. According to the API (which is ill-formatted, I know) you need to send a whole lot more, something like this:
// ...snip...
var oSelection = {
data : [
{
target : oRect,
data : [
{
ctx : {
path : {
dii_a1 : 0,
dii_a2 : 0,
mg : 0,
mi : 0
},
type : "Measure"
},
val : 100
}
]
}
],
name : "selectData"
};
oYourChart.fireSelectData(oSelection);
// ...snip...
If you need to get an element by it's Id when using XMLViews, you should use this.getView().byId("chart") instead
Hope the above helps!
I'm trying to create an interactive and real-time graph using flot library. It's very similar to the real-time example in Flot site but with some additional options.
This is a part of my code:
var bars = false;
var lines = true;
var steps = false;
var xAxisInterval = 5;
var xAxisUnit = "minute";
var plot = 0;
var dataChart = [
{
label : "Consumo",
data : input1_data, //history
threshold : {below : threshold},
color : input1_color, //'#00B800',
lines : {show : input1_show, fill : input1_fill}
},
{
label : "Consumo Previsto",
data : input2_data, //forecast data
threshold : {below : threshold},
//stack : null,
color : input2_color,//'#66E066',
lines : {show : input2_show, fill : input2_fill}
}
];
var plotOptions = {
lines:{
show: lines,
steps: steps
},
bars: {
show: bars,
barWidth: 0.6
},
yaxis:{ min:0, max: 65000 },
xaxis: { mode : "time", tickSize : [ xAxisInterval, xAxisUnit ] },
zoom: { interactive : gridZoom },
pan: { interactive : gridPan },
points: { show: showPoints },
grid: { hoverable: gridHoverable, color: gridColor },
legend: { backgroundColor:legendBackgroundColor, backgroundOpacity:legendBackgroundOpacity, position: legendPosition }
};
if (plot == 0) {
plot = $.plot("#" + divId, dataChart, plotOptions);
}
else {
jQuery.each(dataChart , function(index, value) {
plot.setData([value.data]);
});
plot.setupGrid();
plot.draw();
}
If i only use the code line $.plot("#"+divId, dataChart, plotOptions), it works well.
But to improve performance, instead of construt an entire new plot in every time increment, i tryed to use the code in if/else statement. But the ploted chart loss some options, like series colors and legend, and is painted with color defined in grid options (gridColor) ..., as shown in figure below.
Is this a bug or am I doing something wrong?
You are replacing the all the series options with just the data piece. Also, setData replaces all the data in the chart, so I don't think calling it multiple times in a loop is correct (you'll only end up with the last series).
I usually follow this pattern to replace just the data:
var series = plot.getData();
for (var i = 0 i < dataChart.length; i++){
series[i].data = dataChart[i].data;
}
plot.setData(series);
plot.setupGrid();
plot.draw();
Is there any way we can enable highcharts to display marker value at all the times ?
I got it working. Posting for reference of others
plotOptions : {
line : {
dataLabels : {
enabled : true,
formatter : function() {
return this.y + '%';
}
}
},
series : {
name : 'Team Briefing',
shadow : false,
marker : {
lineWidth : 2,
radius : 6,
symbol : 'circle'
}
}
},
Check the Point Marker reference guide. What I remember about Highcharts is that still it does not provide anything such as.
when you initiate the chart with an object (as your first argument) : ' ...new Highcharts.Chart( { ... } )'
one of this object properties you can use is the plotOptions.series.marker
this marker is an object itself:
marker:{
enabled:true,
lineWith:0.0,
radius:0.0,
// more attributes...
}
those are the default setting. meaning: It is enabled by default, but the radius is also zero by default, and that is the reson you don't see the points .
make a long story short: you need to set the raduis (to be bigger than zero)
read more at http://api.highcharts.com/highcharts#plotOptions.series.marker.radius