2025-12-01 09:43:14 +01:00

125 lines
5.0 KiB
HTML

<html>
<head>
<link rel="stylesheet" href="/examples/site.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@v10.7.0/ol.css" type="text/css">
<script src="https://cdn.jsdelivr.net/npm/ol@v10.7.0/dist/ol.js"></script>
<script src="https://unpkg.com/underscore@1.13.1/underscore-min.js"></script>
<script src="https://unpkg.com/flatgeobuf@4.3.3/dist/flatgeobuf-ol.min.js"></script>
</head>
<body>
<ul class="primary-navigation">
<li>
<a href="/examples/leaflet/large.html">Leaflet Examples</a>
</li>
<li class="active">
OpenLayers Examples
</li>
<li>
<a href="/examples/maplibre/">MapLibre Example</a>
</li>
</ul>
<ul class="secondary-navigation">
<li><a href="/examples/openlayers/">Basic Example</a></li>
<li><a href="/examples/openlayers/filtered.html">Filter By Rect</a></li>
<li class="active">Filtering a Large Dataset</li>
</ul>
<style>
#map {
width: 100%;
height:400px;
}
</style>
<div id="map"></div>
<div id="popup" class="ol-popup">
<a href="#" id="popup-closer" class="ol-popup-closer"></a>
<div id="popup-content"></div>
</div>
<script>
document.addEventListener("DOMContentLoaded", () => {
// Elements that make up the popup.
var popupContainer = document.getElementById('popup');
var popupContent = document.getElementById('popup-content');
var popupCloser = document.getElementById('popup-closer');
// Create an overlay to anchor the popup to the map.
var overlay = new ol.Overlay({
element: popupContainer,
});
/**
* Add a click handler to hide the popup.
* @return {boolean} Don't follow the href.
*/
popupCloser.onclick = () => {
overlay.setPosition(undefined);
popupCloser.blur();
return false;
};
function createBufferedExtent(coord) {
const extent = ol.extent.boundingExtent([coord]);
const bufferedExtent = ol.extent.buffer(extent, 1000);
return bufferedExtent;
}
const strategy = (extent) => [createBufferedExtent(ol.extent.getCenter(extent))];
const source = new ol.source.Vector({ strategy });
const loader = flatgeobuf.createLoader(source, 'https://flatgeobuf.septima.dk/population_areas.fgb', "EPSG:4326", strategy, true);
source.setLoader(loader)
const map = new ol.Map({
layers: [
new ol.layer.Tile({ source: new ol.source.OSM() }),
new ol.layer.Vector({ source })
],
overlays: [overlay],
target: 'map',
view: new ol.View({
center: ol.proj.fromLonLat([-73.98, 40.766]),
zoom: 14
})
});
// show the popup when clicking a feature
map.on("click", (e) => {
map.forEachFeatureAtPixel(e.pixel, (feature) => {
popupContent.innerHTML = `<h1>${feature.get("population")} people live in this census block.</h1>`;
overlay.setPosition(e.coordinate);
})
});
});
</script>
<p>
This is a map of every census block in the USA, including it's
population. The entire file is over 12GB, but FlatGeobuf fetches only
the tiny subset of data that intersects with the bounding box. Pan the
map to move the query's bounding box.
</p>
<p>
When you have feature data that cover a large area in fine-grained
detail like this, the typical options are to either manually slice up
your file into manageable regions or to rely on running an application
server which does this slicing dynamically.
</p>
<p>
Hosting an application has initial complexity and ongoing maintenance
costs. Slicing files can be tedious and inevitiably you might be
interested in an area on the boundary of slices.
</p>
<p>
For these cases, consider instead using a single indexed FlatGeobuf.
Because FlatGeobuf's spatial index allows you to fetch only the data
you're interested in, you can keep your page size down while avoiding
the tedium of slicing up files manually, or building and maintaining an
application server.
</p>
<p>
Though getting a small subset of features from a large dataset transfers
relatively little data, it does so using multiple requests. There are some
<a href="https://github.com/flatgeobuf/flatgeobuf?tab=readme-ov-file#optimizing-remotely-hosted-flatgeobufs">tips for optimizing remote hosted flatgeobufs</a>, mostly oriented around minimizing round trip latency.
</p>
</body>
</html>