Hooked up auroras
This commit is contained in:
104
client/src/services/aurora.ts
Normal file
104
client/src/services/aurora.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import 'ol/ol.css';
|
||||
import {BASE} from '@/services/api.ts';
|
||||
import {Feature} from 'ol';
|
||||
import Point from 'ol/geom/Point';
|
||||
import VectorLayer from 'ol/layer/Vector';
|
||||
import VectorSource from 'ol/source/Vector';
|
||||
import {Style} from 'ol/style';
|
||||
|
||||
export function normalize(coordinates: number | {lon: number} | {long: number} | {longitude: number}) {
|
||||
const convert = (n) => {
|
||||
if (n > 180) return n - 360;
|
||||
if (n < -180) return n + 360;
|
||||
return n;
|
||||
}
|
||||
|
||||
if(typeof coordinates == 'number') return convert(coordinates);
|
||||
if(typeof coordinates['lon'] == 'number') return convert(coordinates['lon']);
|
||||
if(typeof coordinates['long'] == 'number') return convert(coordinates['long']);
|
||||
if(typeof coordinates['longitude'] == 'number') return convert(coordinates['longitude']);
|
||||
}
|
||||
|
||||
export class Aurora {
|
||||
data: any = null;
|
||||
layer;
|
||||
map;
|
||||
name = 'aurora';
|
||||
refresh;
|
||||
refreshRate = 60_000 * 60;
|
||||
timestamp;
|
||||
visible = false;
|
||||
|
||||
constructor(map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
private style(intensity: number) {
|
||||
return new Style({renderer: (coordinates, state) => {
|
||||
const ctx = state.context as CanvasRenderingContext2D;
|
||||
const [x, y] = <[number, number]>coordinates;
|
||||
const previousComposite = ctx.globalCompositeOperation;
|
||||
ctx.globalCompositeOperation = 'screen';
|
||||
const zoom = this.map.getView().getZoom() || 1;
|
||||
const baseRadius = 50;
|
||||
const radius = baseRadius * Math.pow(2, zoom - 3);
|
||||
const gradient = ctx.createRadialGradient(x, y, 0, x, y, radius);
|
||||
const alpha = intensity / 50;
|
||||
gradient.addColorStop(0, `rgba(0, 255, 0, ${alpha})`);
|
||||
gradient.addColorStop(1, 'rgba(0, 255, 0, 0)');
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
ctx.globalCompositeOperation = previousComposite;
|
||||
}});
|
||||
};
|
||||
|
||||
async update() {
|
||||
const d = await fetch(BASE + '/api/aurora').then(resp => resp.json());
|
||||
this.timestamp = new Date(d.timestamp).getTime();
|
||||
this.data = d.data;
|
||||
}
|
||||
|
||||
async redraw() {
|
||||
const threshold = 5;
|
||||
const features = (this.data?.coordinates || [])
|
||||
.filter(([lon, lat, intensity]: [number, number, number], i) => i % 4 == 0 && lat != 0 && intensity >= threshold)
|
||||
.map(([lon, lat, intensity]: [number, number, number]) => {
|
||||
const feature = new Feature({geometry: new Point([normalize(lon), lat])});
|
||||
const geom = feature.getGeometry() as Point;
|
||||
geom.transform('EPSG:4326', this.map.getView().getProjection());
|
||||
feature.setStyle(this.style(intensity));
|
||||
return feature;
|
||||
});
|
||||
if(this.layer) this.map.removeLayer(this.layer);
|
||||
if(!features.length) return;
|
||||
this.layer = new VectorLayer({source: new VectorSource({features, wrapX: true}), zIndex: 5030, opacity: 0.4});
|
||||
this.layer.set('name', this.name);
|
||||
this.map.addLayer(this.layer);
|
||||
}
|
||||
|
||||
async show() {
|
||||
if(this.visible) return;
|
||||
this.visible = true;
|
||||
if(!this.data || Date.now() - this.timestamp > this.refreshRate) await this.update();
|
||||
if(!this.visible) return;
|
||||
await this.redraw();
|
||||
if(!this.refresh) {
|
||||
this.refresh = setInterval(async () => {
|
||||
await this.update();
|
||||
if(!this.visible) return;
|
||||
await this.redraw();
|
||||
}, this.refreshRate);
|
||||
}
|
||||
}
|
||||
|
||||
hide() {
|
||||
if(!this.visible) return;
|
||||
this.visible = false;
|
||||
if(this.refresh) this.refresh = clearInterval(this.refresh);
|
||||
this.map.getLayers().forEach(layer => {
|
||||
if(layer?.get('name') == this.name) this.map.removeLayer(layer);
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user