Added a new example for webgl icons rendering
This commit is contained in:
80333
examples/data/csv/ufo_sighting_data.csv
Normal file
80333
examples/data/csv/ufo_sighting_data.csv
Normal file
File diff suppressed because it is too large
Load Diff
BIN
examples/data/ufo_shapes.png
Normal file
BIN
examples/data/ufo_shapes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
17
examples/icon-sprite-webgl.html
Normal file
17
examples/icon-sprite-webgl.html
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Icon Sprites with WebGL
|
||||
shortdesc: Rendering many icons with WebGL
|
||||
docs: >
|
||||
This example shows how to use `ol/renderer/webgl/PointsLayer` to render
|
||||
a very large amount of sprites. The above map is based on a dataset from the National UFO Reporting Center: each
|
||||
icon marks a UFO sighting according to its reported shape (disk, light, fireball...). The older the sighting, the redder
|
||||
the icon.
|
||||
|
||||
A very simple sprite atlas is used in the form of a PNG file containing all icons on a grid. Then, the `texCoordCallback`
|
||||
option of the `ol/renderer/webgl/PointsLayer` constructor is used to specify which sprite to use according to the sighting shape.
|
||||
|
||||
The dataset contains around 80k points and can be found here: https://www.kaggle.com/NUFORC/ufo-sightings
|
||||
tags: "webgl, icon, sprite, point, ufo"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
124
examples/icon-sprite-webgl.js
Normal file
124
examples/icon-sprite-webgl.js
Normal file
@@ -0,0 +1,124 @@
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import TileLayer from '../src/ol/layer/Tile.js';
|
||||
import TileJSON from '../src/ol/source/TileJSON';
|
||||
import Feature from '../src/ol/Feature';
|
||||
import Point from '../src/ol/geom/Point';
|
||||
import VectorLayer from '../src/ol/layer/Vector';
|
||||
import {Vector} from '../src/ol/source';
|
||||
import {fromLonLat} from '../src/ol/proj';
|
||||
import WebGLPointsLayerRenderer from '../src/ol/renderer/webgl/PointsLayer';
|
||||
import {lerp} from '../src/ol/math';
|
||||
|
||||
const features = [];
|
||||
const vectorSource = new Vector({
|
||||
features: [],
|
||||
attributions: 'National UFO Reporting Center'
|
||||
});
|
||||
|
||||
const texture = document.createElement('img');
|
||||
texture.src = 'data/ufo_shapes.png';
|
||||
|
||||
// This describes the content of the associated sprite sheet
|
||||
// coords are u0, v0, u1, v1 for a given shape
|
||||
const shapeTextureCoords = {
|
||||
'light': [0, 0.5, 0.25, 0],
|
||||
'sphere': [0.25, 0.5, 0.5, 0],
|
||||
'circle': [0.25, 0.5, 0.5, 0],
|
||||
'disc': [0.5, 0.5, 0.75, 0],
|
||||
'oval': [0.5, 0.5, 0.75, 0],
|
||||
'triangle': [0.75, 0.5, 1, 0],
|
||||
'fireball': [0, 1, 0.25, 0.5],
|
||||
'default': [0.75, 1, 1, 0.5]
|
||||
};
|
||||
|
||||
const oldColor = [255, 160, 110];
|
||||
const newColor = [180, 255, 200];
|
||||
|
||||
class WebglPointsLayer extends VectorLayer {
|
||||
createRenderer() {
|
||||
return new WebGLPointsLayerRenderer(this, {
|
||||
texture: texture,
|
||||
colorCallback: function(feature, vertex, component) {
|
||||
// component at index 3 is alpha
|
||||
if (component === 3) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// color is interpolated based on year (min is 1910, max is 2013)
|
||||
// please note: most values are between 2000-2013
|
||||
const ratio = (feature.get('year') - 1950) / (2013 - 1950);
|
||||
return lerp(oldColor[component], newColor[component], ratio * ratio) / 255;
|
||||
},
|
||||
texCoordCallback: function(feature, component) {
|
||||
let coords = shapeTextureCoords[feature.get('shape')];
|
||||
if (!coords) {
|
||||
coords = shapeTextureCoords['default'];
|
||||
}
|
||||
return coords[component];
|
||||
},
|
||||
sizeCallback: function() {
|
||||
return 16;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function loadData() {
|
||||
const client = new XMLHttpRequest();
|
||||
client.open('GET', 'data/csv/ufo_sighting_data.csv');
|
||||
client.onload = function() {
|
||||
const csv = client.responseText;
|
||||
let curIndex;
|
||||
let prevIndex = 0;
|
||||
let line;
|
||||
while ((curIndex = csv.indexOf('\n', prevIndex)) > 0) {
|
||||
line = csv.substr(prevIndex, curIndex - prevIndex).split(',');
|
||||
prevIndex = curIndex + 1;
|
||||
|
||||
// skip header
|
||||
if (prevIndex === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const coords = fromLonLat([parseFloat(line[5]), parseFloat(line[4])]);
|
||||
|
||||
// only keep valid points
|
||||
if (isNaN(coords[0]) || isNaN(coords[1])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
features.push(new Feature({
|
||||
datetime: line[0],
|
||||
year: parseInt(/[0-9]{4}/.exec(line[0])[0]), // extract the year as int
|
||||
shape: line[2],
|
||||
duration: line[3],
|
||||
geometry: new Point(coords)
|
||||
}));
|
||||
}
|
||||
vectorSource.addFeatures(features);
|
||||
};
|
||||
client.send();
|
||||
}
|
||||
|
||||
loadData();
|
||||
|
||||
new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new TileJSON({
|
||||
url: 'https://api.tiles.mapbox.com/v3/mapbox.world-dark.json?secure',
|
||||
crossOrigin: 'anonymous'
|
||||
})
|
||||
}),
|
||||
new WebglPointsLayer({
|
||||
source: vectorSource
|
||||
})
|
||||
],
|
||||
target: document.getElementById('map'),
|
||||
view: new View({
|
||||
center: [0, 4000000],
|
||||
zoom: 2
|
||||
})
|
||||
});
|
||||
Reference in New Issue
Block a user