I am working on trying to create a basic, grid-based, but performant weather-arrow visualization system.
EDIT 2:
Up-to-date version here: ( Mapbox Tracker ) of the system using the workflow which is described below
Usage Instructions:
- Click on Wind icon (on the left)
- Wait for triangles to occupy screen
- Pan time-slider (at the bottom)
As you will observe (especially on larger resolutions or when panning time slider quickly) there is quite a performance hit when drawing the triangles.
I would greatly appreciate any advice on where to start with either using something in the current API which would help, or any ideas on how to tap into the current graphics pipeline with some type of custom buffer where I would only need to rotate, scale, change color of triangles already populated in screen space.
I feel as though my specific use-case would greatly benefit from something like this, I really just don't know how to approach it.
I have a naive implementation running using this workflow:
Create a geojson FeatureCollection source
Create a fill layer
Using Data Driven property: fill-color
Data function:
Get map bounds
Project sw & ne into screen points (map.project(LatLng))
Divide height and width into portions
Loop through width and height portions
Lookup data
Access data rotation property
Create vertices based on center point + size
Rotate vertices
Create Point objects for vertices
Unproject Point Object and wrap map.unproject(Point).wrap()
Create Feature Object, assign Data driven Color
Assign unprojected LatLng as Coordinates to Polygon geometry
Add to Feature Array for Collection
Call setData on layer
So while this works, I'm looking for advice for a more performance friendly approach.
What I'm thinking here is whether I can somehow create a custom layer, one where I only need to draw to screen co-ordinates to represent the data relative to its LatLng point. So that I can draw colored, scaled, rotated triangles in screen space, and then have them update to relevant data from the new relative LatLng position.
E.g. Update some type of Mesh on screen instead of having to: unproject, then update feature collection source using map.getSource('arrows').setData(d), requestAnimationFrame(function) etc.
I've done similar in three.js in other projects but I would much rather use something that is more mapbox native. Does this sound feasible? Am I going to see a decent performance boost if so?
I've not dealt with raw gl calls before etc so I might need a pointer or two in the right direction if its going to need to get as low level as that.
EDIT:
Previous Implementation using gmaps / three.js : volvooceanrace
(wait for button on left to go from grey to black) click on top button which shows a 'wind' label when hovered over, slide red time bar underneath to change data.
Added screenshot of current working implementation
Mapbox GL Arrows
Not sure what was available in 2016, but a reasonable approach these days might be to use symbol layers, and the icon-rotate data-driven property to rotate each icon based on the property of its data point.
Related
I have some geoJSON polygons that I render via layers on top of my map. Depending on the shape itself and the zoom level, sometimes the rendered shapes are too small and it doesn't make sense to even show them.
Is there a way to hide shapes that have rendered area less than some number?
So, as Babis.amas suggested, first I calculate the area of the feature with help of turf.area. It gives the value in square meters. Then I convert this value to pixels using the function mentioned here. And then it really depends on the shape type I'm dealing with. If the shape considered to be too small to be rendered, I just don't add it to the layer data feature collection.
I am working with ~150,000 polylines that span North America. Across all the lines I'd like to draw/animate from the start to the end of each line. I started down the road of adding vertices to an array and updating a Mapbox source like this example. This was not feasible given the size of the entire dataset. In geojson form it's about 800mb and manipulating this in the browser seemed unreasonable.
As an alternate approach, I've broken each polyline into equally sized segments of 10km in length. I added an attribute on each segment which represents its percent distance from the start. I created an interval below that triggers a setFilter event, filtering segments based in the percent from start.
currentLinPos=0;
lineInterval=setInterval(function(){
currentLinPos+=.01;
if(currentLinPos>0.9999){
currentLinPos=0
}
map.setFilter('lines',['<','linePrc',currentLinPos])
}, 250);
Even when working with a small subset of the data, performance choppy and lags. I expected a better result from Mapbox GL but perhaps I need to rethink my data structure or approach entirely. Or would using something like DECK.GL be far superior here?
Using geojson.io page I want to draw some districts/countries.
I'm drawing each district separately as there is no multipolygons in Leaflet Draw. However when I'm drawing the borders even with maximum zoom - the borders will never be exactly the same. Coordinates will differ to some extend which is natural. Hence when I am downloading the data in topojson , the data are not valid to display meshes between different districts
How to achieve the goal to have the borders always with the same coordinates?
For example it could be achieved by having the markers visible during drawing and just picking up the one I'm interested in(on a same border) by mouse click - the same way the shape is finished.
I have downloaded the source code, read it (it is nice), searched through docs and thinking how to adjust it for my goal but I'm lost :/
Leaflet.Snap did the trick.
I was afraid that snapping will be not exact for the borders but it is :)
I need a Time Line For My Web Project.
Something like this - I read the code of this Time Line but did not understand it because it is not documented enough.
My problem is the math behind all of this (not the interaction with the canvas).
I have read several articles about the math of the scroll bars, but none of them talk about zoom.
Some
articles suggest to hold canvas element with very large width value - and to display just the
View Port.
I don't think that's the right way to do it - I want to draw just the correct viewport.
In my project, I have array of n points.
Each point holds time value represented in seconds, but not all of the points are within the Viewp Port.
Considering the current zoom level, how do I calculate:
What points should be drawn and where to draw them?
What is the size and position of the thumb?
Any articles / tutorials about such a thing?
You might be able to use something like Flot which handles the placement of points, as well as zooming and panning. Here's an example of that.
There are a bunch of other drawing libraries, here a good list.
You always have Raphealjs.com , one of the most used library to play with SVG, with this you can write your own js to generate the timeline.
Seatgeek has a zoomable draggable tiled interface.
An example is here:
http://seatgeek.com/sf-bulls-yankees-tickets/3-2-2012-tampa-george-steinbrenner-field/mlb/785875/#
I want to implement a scrollable draggable interface like this but I cannot use Google's code for google maps.
Also I need the tile system like google maps where it pulls tiles from the server for rendering the map.
Need to implement in javascript. What library can I use? How can I do it?
How does seatgeek do it?
I de-compiled their javascript http://pastebin.com/PVjahhnH
Map Client
OpenLayers
OpenLayers Examples
Map Data
OpenStreetMap
This kind of interface seems complex to implement, but it is just some math tricks. If you decide to implement your own algorithm, try this out:
Take the full image and create tiles in different scales and consequently with different depth.
The user start looking at the scene in real scale, composed by 16 tiles created from the original scene.
If the user drags, all tiles moves equaly. If the user zoom in, all tiles are scaled up.
If the user zoom more than X, you change the 16 tiles by their 16 child tiles! Got it? Higher the zoom, higher the detail. To avoid having 36000 tiles at the same time, generate with different depth and switch them on the fly.
You just need to load and move the tiles. Multiply tile x, y, width, height by the zoom. Keep the focus of the scene in the mouse position. Take a look at this example. It does exactly the steps above, but with a lot of microscope images. It is the same idea of google maps.
CloudMade map tile is one of the server based map tile service. Please read this page server http://cloudmade.com/documentation/map-tiles or contact with alex#cloudmade.com for more information.