I'm developping a map using mapbox gl js, my issue is the following:
I have 1 source and I apply 1 setData on this source with a geojson collection of points -> fine
I want to update one position for one feature (point) of this featurecollection
I do querySourceFeatures and I get an array of features -> fine
I detect the feature I want to modify and I modify the lat-long accordingly -> fine
I would like to apply the whole setData with the modify feature to redraw but ...
Here is the problem, how do I go from the array of features (one is modified) to a feature collection compatible with setData ... ?
I'm confused why (or what) there is not a straight path to do that ... What do I miss here?
can you help me please?
thanks,
Olivier
finally, I rebuild the featureCollection "manually" in a separate function ... I though it would not be an optimized solution but at the end, reveals quite straight ...
function build_featureCollection_from_array(parray) {
lv_fc = {};
lv_fc.type = "FeatureCollection";
lv_fc.features = parray;
return lv_fc;
}
Related
Background:
I'm currently integrating HERE maps into our web-based application. I'm trying both - HERE provided Javascript API and Leaflet at the same time to find the best approach for our use-case.
While JavaScript API provided by HERE maps is OK, rendering wise Leaflet performs much better when using raster tiles.
Issue:
It would be fine by me to use raster tiles + leaflet, but our application also needs to display traffic incidents data.
Traffic incident data is provided by HERE in JSON and XML formats (Documentation link, Example JSON). They provide [Z]/[X]/[Y], quadkey, prox, bbox, or corridor filters which can be used to retrieve filtered data set.
I've tried using [Z]/[X]/[Y] addressing with custom L.TileLayer implementation which loads appropriate JSON, converts it to GeoJSON and displays GeoJSON on map. However that approach is very inefficient and significant performance drop is visible.
Question:
Maybe anyone has already solved this issue and could share any insights on how the HERE traffic incidents could be shown on Leaflet map without encountering performance issues?
I created the following script, which works without any performance issues:
var fg = L.featureGroup().addTo(map);
function loadTraffic(data) {
fg.clearLayers();
var d = data.TRAFFICITEMS.TRAFFICITEM.map((r) => {
var latlngs = [];
if (r.LOCATION.GEOLOC) {
if (r.LOCATION.GEOLOC.ORIGIN) {
latlngs.push(L.latLng(r.LOCATION.GEOLOC.ORIGIN.LATITUDE, r.LOCATION.GEOLOC.ORIGIN.LONGITUDE));
}
if (r.LOCATION.GEOLOC.TO) {
if (L.Util.isArray(r.LOCATION.GEOLOC.TO)) {
r.LOCATION.GEOLOC.TO.forEach((latlng) => {
latlngs.push(L.latLng(latlng.LATITUDE, latlng.LONGITUDE));
})
} else {
latlngs.push(L.latLng(r.LOCATION.GEOLOC.TO.LATITUDE, r.LOCATION.GEOLOC.TO.LONGITUDE));
}
}
}
var desc = r.TRAFFICITEMDESCRIPTION.find(x => x.TYPE === "short_desc").content;
return {
latlngs,
desc
}
})
console.log(d);
d.forEach((road)=>{
L.polyline(road.latlngs,{color: 'red'}).addTo(fg).bindPopup(road.desc);
});
map.fitBounds(fg.getBounds())
}
If this script is not working for you, please share your json file.
Ok, so I've found a solution for this task. Apparently I was on a good path, I only needed to optimize my implementation.
What I had to do to achieve appropriate performance is:
Create custom CircleMarker extension which would draw custom icon on canvas
Create JS worker which would fetch the data from a given URL, transform it to GeoJSON and return GeoJSON to it's listener
Create custom GridLayer implementation, which, in fetchTile function, creates worker instance, passes it a link with appropriate [Z]/[X]/[Y] coordinates already set, adds listener, which listens for worker's done event and returns empty tile
On worker's done event, custom GridLayer implementation creates GeoJSON layer, adds it to the dictionary with coordinates as a key and, if zoom level is still the same - adds that layer to the map
Add zoomend observer on a map, which removes any layers that does not match current zoom level from the map
Now the map is definitely usable and works way faster than original HERE JS API.
P.S. Sorry, but I can't share the implementation itself due to our company policies.
Is there any function that allows us to rotate an Here map using the JavaScript API ?
I have found it for android (https://developer.here.com/mobile-sdks/documentation/android-hybrid-plus/topics/maps.html) but I am not able to find it for JavaScript.
If this function does not exist what is the best alternative (still using Here JavaScript API) ?
The documentation for rotation isn't very well described but I found an example in the organisation's repo:
https://github.com/heremaps/developer-blog/blob/bef386d743d062275ac976546e3c745932ed8e47/javascript-api-3.1/js/MapRotation.js
You can affect the rotation of a map by setting the heading property in the ViewModel:
let mapView = map.getViewModel();
mapView.setLookAtData({
heading: 90
});
H.map.ViewModel.control
https://developer.here.com/javascript-apis/documentation/v3/maps/topics_api_nlp/h-map-viewmodel.html#h-map-viewmodel__control
It looks like you can control the angleX or angleY from the ViewModel if you are able to set this somewhere.
I have a hashtable I am trying to use in an vector layer so this is what I made:
var make = [], remove = [];
for (var key in data) {
var val = data[key];
if (featureCache[key]) {
if (val._ts > featureCache[key]._ts) {
var geom = featureCache[key].getGeometry();
The problem starts here. From what I have found out so far I have two options:
geom.setCoordinates(latlng([val.Latitude, val.Longitude]));
geom.flatCoordinates = latlng([val.Latitude, val.Longitude]);
However the first one bubbles up and makes the map render, this is a problem because I have over 1500 features and I plan on using more.
The second line gives me assertion failed, and I dont know how to debug it.
featureCache[key]._ts = val._ts;
}
} else {
make.push(featureCache[key] =
new ol.Feature({
geometry: new ol.geom.Point(latlng([val.Latitude,val.Longitude]))
})
);
featureCache[key]._ts = val._ts;
}
}
source.addFeatures(make);
This needs to be run every other second or so because I want the data to be as realtime as possible.
And if this is a really stupid way do do it, I would like to know that too.
I am not sure how you could do it with the new API, but you could try this:
clone an old geometry and update it, do this for each
add the clone to a collection that OL is not aware of (avoids the map render / updates)
once that collection is ready, remove the old collection from OL and set the new (batch)
Doing this for several thousand items should work pretty fast on 'modern' browsers as you set it only once. The key point is to avoid triggering updates while you update each entry.
Maybe there are ways to avoid the bubbling/events to allow for batch updates (no triggering of map render for each change) ?
I have a working application here: http://dola.colorado.gov/gis-cms/sites/default/files/html/census2000v2.html
I'm using the Javascript API with ArcGIS Online. I have a bunch of layers loaded and pre-symbolized in an AGOL 'Web Map'.
I'd like to be able to customize the symbology of each layer dynamically using javascript. I'd ideally like to use a renderer and be able to create a different symbology for each demographic variable.
I've run into a major brick wall. To be able to change the symbology, I need to be able to iterate through graphics in a feature set - yet I have no idea where to get a feature set object from. All the examples I see use 'Feature Layers' loaded through URLs.
I think first you need to get the layer from the webmap:
var featureLayer = mapObject.getLayer(layerName)
Then you can query the featurelayer, which will return a featureSet.
Here is an example:
var query = new esri.tasks.Query();
query.outFields = ["*"];
featureLayer.queryFeatures(query, function(featureSet) {
//do something with the featureSet here!
});
I am using the heatmap.js library from pa7 in github successfully to make some heatmap
http://www.patrick-wied.at/static/heatmapjs/example-heatmap-leaflet.html
But when I updated the heatmap with additional data or new data points, the leaflet library does not really update with the additional data points. There seems to be no method that can used for redraw. I dont know if someone has already solved this problem, thats why I am asking to see. Here is the simple portion of my additional script:
ndata=[{lat: 13.59, lon:-17.05, value: 11},{lat: 33.08, lon:-103.24, value: 19}]
testData.data.push.apply(ndata)
layer.addData(testData.data);
There is no errors in the console of Google chrome or no exceptions.
Thanks
There is a redraw method in the layer:
var heatmapLayer = L.TileLayer.heatMap();
// add layer to map
heatmapLayer.redraw()
Having said this, in the latest version, the heatmap layer automatically redraws when you set the data (see https://github.com/pa7/heatmap.js/blob/d09c4e99852b4849e2b4d4f12976a9fce0327ca5/src/heatmap-leaflet.js#L112).