D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
self
/
root
/
usr
/
share
/
grafana
/
public
/
app
/
plugins
/
panel
/
geomap
/
layers
/
data
/
Filename :
dayNightLayer.tsx
back
Copy
import Feature from 'ol/Feature'; import Map from 'ol/Map'; import { Coordinate } from 'ol/coordinate'; import { MultiLineString } from 'ol/geom'; import Point from 'ol/geom/Point'; import { Group as LayerGroup } from 'ol/layer'; import VectorLayer from 'ol/layer/Vector'; import { fromLonLat } from 'ol/proj'; import VectorSource from 'ol/source/Vector'; import { Fill, Stroke, Style, Circle } from 'ol/style'; import DayNight from 'ol-ext/source/DayNight'; import { Subscription } from 'rxjs'; import { MapLayerRegistryItem, MapLayerOptions, PanelData, GrafanaTheme2, EventBus, DataHoverEvent, DataHoverClearEvent, } from '@grafana/data'; export enum ShowTime { From = 'from', To = 'to', } // Configuration options for Circle overlays export interface DayNightConfig { show: ShowTime; sun: boolean; nightColor: string; } const defaultConfig: DayNightConfig = { show: ShowTime.To, sun: false, nightColor: '#a7a6ba4D', }; export const DAY_NIGHT_LAYER_ID = 'dayNight'; // Used by default when nothing is configured export const defaultDayNightConfig: MapLayerOptions<DayNightConfig> = { type: DAY_NIGHT_LAYER_ID, name: '', // will get replaced config: defaultConfig, tooltip: true, }; /** * Map layer configuration for circle overlay */ export const dayNightLayer: MapLayerRegistryItem<DayNightConfig> = { id: DAY_NIGHT_LAYER_ID, name: 'Night / Day', description: 'Show day and night regions', isBaseMap: false, /** * Function that configures transformation and returns a transformer * @param map * @param options * @param theme */ create: async (map: Map, options: MapLayerOptions<DayNightConfig>, eventBus: EventBus, theme: GrafanaTheme2) => { // Assert default values const config = { ...defaultConfig, ...options?.config, }; // DayNight source const source = new DayNight({}); const sourceMethods = Object.getPrototypeOf(source); const sourceLine = new DayNight({}); const sourceLineMethods = Object.getPrototypeOf(sourceLine); // Night polygon const vectorLayer = new VectorLayer({ source, style: new Style({ fill: new Fill({ color: theme.visualization.getColorByName(config.nightColor), }), }), }); // Night line (for crosshair sharing) const nightLineLayer = new VectorLayer({ source: new VectorSource({ features: [], }), style: new Style({ stroke: new Stroke({ color: '#607D8B', width: 1.5, lineDash: [2, 3], }), }), }); // Sun circle const sunFeature = new Feature({ geometry: new Point([]), }); const sunLayer = new VectorLayer({ source: new VectorSource({ features: [sunFeature], }), style: new Style({ image: new Circle({ radius: 13, fill: new Fill({ color: 'rgb(253,184,19)' }), }), }), }); // Sun line (for crosshair sharing) const sunLineFeature = new Feature({ geometry: new Point([]), }); const sunLineStyle = new Style({ image: new Circle({ radius: 13, stroke: new Stroke({ color: 'rgb(253,184,19)', width: 1.5, }), }), }); const sunLineStyleDash = new Style({ image: new Circle({ radius: 15, stroke: new Stroke({ color: '#607D8B', width: 1.5, lineDash: [2, 3], }), }), }); const sunLineLayer = new VectorLayer({ source: new VectorSource({ features: [sunLineFeature], }), style: [sunLineStyleDash, sunLineStyle], }); // Build group of layers // TODO: add blended night region to "connect" current night region to lines const layer = new LayerGroup({ layers: config.sun ? [vectorLayer, sunLayer, sunLineLayer, nightLineLayer] : [vectorLayer, nightLineLayer], }); // Crosshair sharing subscriptions const subscriptions = new Subscription(); if (false) { subscriptions.add( eventBus.subscribe(DataHoverEvent, (event) => { const time = event.payload?.point?.time as number; if (time) { const lineTime = new Date(time); const nightLinePoints = sourceLine.getCoordinates(lineTime.toString(), 'line'); nightLineLayer.getSource()?.clear(); const lineStringArray: Coordinate[][] = []; for (let l = 0; l < nightLinePoints.length - 1; l++) { const x1: number = Object.values(nightLinePoints[l])[0]; const y1: number = Object.values(nightLinePoints[l])[1]; const x2: number = Object.values(nightLinePoints[l + 1])[0]; const y2: number = Object.values(nightLinePoints[l + 1])[1]; const lineString = [fromLonLat([x1, y1]), fromLonLat([x2, y2])]; lineStringArray.push(lineString); } nightLineLayer.getSource()?.addFeature( new Feature({ geometry: new MultiLineString(lineStringArray), }) ); let sunLinePos: number[] = []; sunLinePos = sourceLineMethods.getSunPosition(lineTime); sunLineFeature.getGeometry()?.setCoordinates(fromLonLat(sunLinePos)); sunLineFeature.setStyle([sunLineStyle, sunLineStyleDash]); } }) ); subscriptions.add( eventBus.subscribe(DataHoverClearEvent, (event) => { nightLineLayer.getSource()?.clear(); sunLineFeature.setStyle(new Style({})); }) ); } return { init: () => layer, dispose: () => subscriptions.unsubscribe(), update: (data: PanelData) => { const from = new Date(data.timeRange.from.valueOf()); const to = new Date(data.timeRange.to.valueOf()); let selectedTime: Date = new Date(); let sunPos: number[] = []; // TODO: add option for "Both" if (config.show === ShowTime.From) { selectedTime = from; } else { selectedTime = to; } source.setTime(selectedTime); if (config.sun) { sunPos = sourceMethods.getSunPosition(selectedTime); sunFeature.getGeometry()?.setCoordinates(fromLonLat(sunPos)); } }, // Marker overlay options registerOptionsUI: (builder) => { if (!options.config?.nightColor) { options.config = { ...defaultConfig, ...options.config }; } builder.addRadio({ path: 'config.show', name: 'Show', settings: { options: [ { label: 'From', value: ShowTime.From }, { label: 'To', value: ShowTime.To }, ], }, defaultValue: defaultConfig.show, }); builder.addColorPicker({ path: 'config.nightColor', name: 'Night region color', description: 'Pick color of night region', defaultValue: defaultConfig.nightColor, settings: [{ enableNamedColors: false }], }); builder.addBooleanSwitch({ path: 'config.sun', name: 'Display sun', description: 'Show the sun', defaultValue: defaultConfig.sun, }); }, }; }, // fill in the default values defaultOptions: defaultConfig, };