LineLayer with arrows
by felixp
HTML
<!DOCTYPE html>
<html>
<head>
<title>deck.gl+Google</title>
<script src="https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.js"></script>
<link href="https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<script src="https://unpkg.com/[email protected]/dist.min.js"></script>
<script src="https://unpkg.com/@deck.gl/[email protected]/dist.min.js"></script>
<!-- jsFiddle will insert css and js -->
</head>
<body>
<div id="map"></div>
</body>
</html>
CSS
/* Always set the map height explicitly to define the size of the div element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
JavaScript
const data =
'https://d2ad6b4ur7yvpq.cloudfront.net/naturalearth-3.3.0/ne_10m_airports.geojson';
const dataTransform = d => d.features.filter(f => f.properties.scalerank < 3);
const origin = [14.42076, 50.08804]; // Prague
const deckgl = new deck.DeckGL({
container: 'map',
mapStyle: deck.carto.BASEMAP.DARK_MATTER,
initialViewState: {
latitude: 40,
longitude: 0,
zoom: 1
},
controller: true,
onViewStateChange: update
});
function update({
viewState
}) {
const flightsLayer = new deck.LineLayer({
id: 'flights',
data,
dataTransform,
getSourcePosition: origin,
getTargetPosition: f => f.geometry.coordinates,
getColor: [0, 128, 200],
getWidth: 2
});
// Project positions to get correct rotation in screen space
const viewport = new deck.WebMercatorViewport(viewState);
const p2 = viewport.project(origin);
const arrowLayer = new deck.IconLayer({
id: 'icon-layer',
data,
dataTransform,
// iconAtlas and iconMapping are required
// getIcon: return a string
iconAtlas: 'https://unpkg.com/@mapbox/[email protected]/icons/triangle.svg',
iconMapping: {
triangle: {
x: 0,
y: 0,
width: 15,
height: 15,
mask: true
}
},
getIcon: d => 'triangle',
getPosition: f => f.geometry.coordinates,
getAngle: f => {
const p1 = viewport.project(f.geometry.coordinates);
const deltaLng = p1[0] - p2[0];
const deltaLat = p1[1] - p2[1];
return 180 * Math.atan2(deltaLng, deltaLat) / Math.PI + 180;
},
getSize: d => 1,
getColor: [0, 128, 200],
sizeScale: 10,
updateTriggers: {
getAngle: [viewport]
}
});
deckgl.setProps({
layers: [flightsLayer, arrowLayer]
})
}