152 lines
4.1 KiB
JavaScript
152 lines
4.1 KiB
JavaScript
// class HexgridHeatmap {
|
|
// constructor(map, options = {}) {
|
|
// this.map = map;
|
|
// this.options = {
|
|
// id: 'hexgrid-heatmap',
|
|
// radius: 1000, // meters
|
|
// colorRange: [
|
|
// [0, '#f7fbff'],
|
|
// [0.2, '#6baed6'],
|
|
// [0.4, '#4292c6'],
|
|
// [0.6, '#2171b5'],
|
|
// [0.8, '#084594'],
|
|
// [1, '#08306b']
|
|
// ],
|
|
// opacity: 0.7,
|
|
// ...options
|
|
// };
|
|
|
|
// // this.hexLayerId = `${this.options.id}-hex`;
|
|
// this.hexLayerId = `${this.options.id}`;
|
|
// this.hexData = null;
|
|
|
|
// if (this.map.loaded()) {
|
|
// this._initialize();
|
|
// } else {
|
|
// this.map.on('load', () => this._initialize());
|
|
// }
|
|
// }
|
|
|
|
// async _initialize() {
|
|
// await this._createHexgrid();
|
|
// this._addSourcesAndLayers();
|
|
// this._setupEventListeners();
|
|
// }
|
|
|
|
// async _createHexgrid() {
|
|
// if (!this.options.data) return;
|
|
|
|
// // 1. Get bounding box of point data
|
|
// const bbox = turf.bbox(this.options.data);
|
|
|
|
// // 2. Create hexgrid covering the bounding box
|
|
// const cellSide = this.options.radius;
|
|
// const hexgrid = turf.hexGrid(bbox, cellSide, { units: 'meters' });
|
|
|
|
// // 3. Count points in each hexagon
|
|
// this.hexData = this._countPointsInHexagons(this.options.data, hexgrid);
|
|
// }
|
|
|
|
// _countPointsInHexagons(points, hexgrid) {
|
|
// // Collect counts for each hexagon
|
|
// const counts = {};
|
|
// points.features.forEach(point => {
|
|
// hexgrid.features.forEach((hex, i) => {
|
|
// if (turf.booleanPointInPolygon(point, hex)) {
|
|
// counts[i] = (counts[i] || 0) + 1;
|
|
// }
|
|
// });
|
|
// });
|
|
|
|
// // Add counts to hexgrid properties
|
|
// hexgrid.features.forEach((hex, i) => {
|
|
// hex.properties = {
|
|
// ...hex.properties,
|
|
// count: counts[i] || 0
|
|
// };
|
|
// });
|
|
|
|
// // Normalize values (0-1) for coloring
|
|
// const maxCount = Math.max(...Object.values(counts), 1);
|
|
// hexgrid.features.forEach(hex => {
|
|
// hex.properties.normalizedValue = hex.properties.count / maxCount;
|
|
// });
|
|
|
|
// return hexgrid;
|
|
// }
|
|
|
|
// _addSourcesAndLayers() {
|
|
// // Add hexgrid source
|
|
// this.map.addSource(this.hexLayerId, {
|
|
// type: 'geojson',
|
|
// data: this.hexData
|
|
// });
|
|
|
|
// // Add hexagon layer
|
|
// this.map.addLayer({
|
|
// id: this.hexLayerId,
|
|
// type: 'fill',
|
|
// source: this.hexLayerId,
|
|
// paint: {
|
|
// 'fill-color':
|
|
// 'red',
|
|
// // [
|
|
// // 'interpolate',
|
|
// // ['linear'],
|
|
// // ['get', 'normalizedValue'],
|
|
// // ...this.options.colorRange.flat()
|
|
// // ],
|
|
// 'fill-opacity': this.options.opacity,
|
|
// 'fill-outline-color': '#fff'
|
|
// }
|
|
// });
|
|
// }
|
|
|
|
// _setupEventListeners() {
|
|
// this.map.on('click', this.hexLayerId, (e) => {
|
|
// const features = this.map.queryRenderedFeatures(e.point, {
|
|
// layers: [this.hexLayerId]
|
|
// });
|
|
// if (features.length > 0) {
|
|
// this._showPopup(features[0], e.lngLat);
|
|
// }
|
|
// });
|
|
|
|
// this.map.on('mousemove', this.hexLayerId, (e) => {
|
|
// this.map.getCanvas().style.cursor = 'pointer';
|
|
// });
|
|
|
|
// this.map.on('mouseleave', this.hexLayerId, () => {
|
|
// this.map.getCanvas().style.cursor = '';
|
|
// });
|
|
// }
|
|
|
|
// _showPopup(feature, lngLat) {
|
|
// console.log('Hexagon clicked:', feature);
|
|
// new mapboxgl.Popup()
|
|
// .setLngLat(lngLat)
|
|
// .setHTML(`
|
|
// <strong>Hexagon Data</strong>
|
|
// <div>Points: ${feature.properties.count}</div>
|
|
// <div>Value: ${feature.properties.normalizedValue.toFixed(2)}</div>
|
|
// `)
|
|
// .addTo(this.map);
|
|
// }
|
|
|
|
// // Public API
|
|
// updateData(newData) {
|
|
// this.options.data = newData;
|
|
// return this._createHexgrid().then(() => {
|
|
// this.map.getSource(this.hexLayerId).setData(this.hexData);
|
|
// });
|
|
// }
|
|
|
|
// remove() {
|
|
// if (this.map.getLayer(this.hexLayerId)) {
|
|
// this.map.removeLayer(this.hexLayerId);
|
|
// }
|
|
// if (this.map.getSource(this.hexLayerId)) {
|
|
// this.map.removeSource(this.hexLayerId);
|
|
// }
|
|
// }
|
|
// }
|