mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Geomap: Support geojson styling properties (#80272)
* Geomap: Support geojson styling properties * Add enum for geojson styles * Move styleStrings outside of style function * Add styling note to geoJSON docs * Clean up geomap docs * Add support for points * Add simple example * Add support for all geojson types and update example * Update colors * Update docs * Remove old TODO * Update geojson name --------- Co-authored-by: nmarrs <nathanielmarrs@gmail.com>
This commit is contained in:
parent
9b9d91e7ae
commit
378c863616
@ -282,6 +282,26 @@ The GeoJSON layer allows you to select and load a static GeoJSON file from the f
|
|||||||
- **Add style rule** creates additional style rules.
|
- **Add style rule** creates additional style rules.
|
||||||
- **Display tooltip** allows you to toggle tooltips for the layer.
|
- **Display tooltip** allows you to toggle tooltips for the layer.
|
||||||
|
|
||||||
|
{{% admonition type="note" %}}
|
||||||
|
Styles can be set within the "properties" object of the GeoJSON with support for the following geometries:
|
||||||
|
|
||||||
|
- Polygon, MultiPolygon
|
||||||
|
|
||||||
|
- **"fill"** - The color of the interior of the polygon(s)
|
||||||
|
- **"fill-opacity"** - The opacity of the interior of the polygon(s)
|
||||||
|
- **"stroke-width"** - The width of the line component of the polygon(s)
|
||||||
|
|
||||||
|
- Point, MultiPoint
|
||||||
|
|
||||||
|
- **"marker-color"** - The color of the point(s)
|
||||||
|
- **"marker-size"** - The size of the point(s)
|
||||||
|
|
||||||
|
- LineString, MultiLineString
|
||||||
|
- **"stroke"** - The color of the line(s)
|
||||||
|
- **"stroke-width"** - The width of the line(s)
|
||||||
|
|
||||||
|
{{% /admonition %}}
|
||||||
|
|
||||||
## Night / Day layer
|
## Night / Day layer
|
||||||
|
|
||||||
The Night / Day layer displays night and day regions based on the current time range.
|
The Night / Day layer displays night and day regions based on the current time range.
|
||||||
@ -457,7 +477,7 @@ A map from a collaborative free geographic world database.
|
|||||||
|
|
||||||
### More Information
|
### More Information
|
||||||
|
|
||||||
- [**About Open Street Map**](https://www.openstreetmap.org/about)\
|
- [**About Open Street Map**](https://www.openstreetmap.org/about)
|
||||||
|
|
||||||
## ArcGIS layer
|
## ArcGIS layer
|
||||||
|
|
||||||
@ -536,7 +556,7 @@ Displays measure tools in the upper right corner. Measurements appear only when
|
|||||||
- **Double-click** to end measurement
|
- **Double-click** to end measurement
|
||||||
|
|
||||||
{{% admonition type="note" %}}
|
{{% admonition type="note" %}}
|
||||||
<br /- When you change measurement type or units, the previous measurement is removed from the map. <br /- If the control is closed and then re-opened, the most recent measurement is displayed. <br /- A measurement can be modified by clicking and dragging on it.
|
When you change measurement type or units, the previous measurement is removed from the map. If the control is closed and then re-opened, the most recent measurement is displayed. A measurement can be modified by clicking and dragging on it.
|
||||||
{{% /admonition %}}
|
{{% /admonition %}}
|
||||||
|
|
||||||
#### Length
|
#### Length
|
||||||
|
@ -8,25 +8,27 @@ import { Style } from 'ol/style';
|
|||||||
import { ReplaySubject } from 'rxjs';
|
import { ReplaySubject } from 'rxjs';
|
||||||
import { map as rxjsmap, first } from 'rxjs/operators';
|
import { map as rxjsmap, first } from 'rxjs/operators';
|
||||||
|
|
||||||
import {
|
import { MapLayerRegistryItem, MapLayerOptions, GrafanaTheme2, EventBus } from '@grafana/data';
|
||||||
MapLayerRegistryItem,
|
|
||||||
MapLayerOptions,
|
|
||||||
GrafanaTheme2,
|
|
||||||
EventBus,
|
|
||||||
} from '@grafana/data';
|
|
||||||
import { ComparisonOperation } from '@grafana/schema';
|
import { ComparisonOperation } from '@grafana/schema';
|
||||||
|
|
||||||
import { GeomapStyleRulesEditor } from '../../editor/GeomapStyleRulesEditor';
|
import { GeomapStyleRulesEditor } from '../../editor/GeomapStyleRulesEditor';
|
||||||
import { StyleEditor } from '../../editor/StyleEditor';
|
import { StyleEditor } from '../../editor/StyleEditor';
|
||||||
import { polyStyle } from '../../style/markers';
|
import { polyStyle } from '../../style/markers';
|
||||||
import { defaultStyleConfig, StyleConfig, StyleConfigState } from '../../style/types';
|
import {
|
||||||
|
defaultStyleConfig,
|
||||||
|
GeoJSONLineStyles,
|
||||||
|
GeoJSONPointStyles,
|
||||||
|
GeoJSONPolyStyles,
|
||||||
|
StyleConfig,
|
||||||
|
StyleConfigState,
|
||||||
|
StyleConfigValues,
|
||||||
|
} from '../../style/types';
|
||||||
import { getStyleConfigState } from '../../style/utils';
|
import { getStyleConfigState } from '../../style/utils';
|
||||||
import { FeatureRuleConfig, FeatureStyleConfig } from '../../types';
|
import { FeatureRuleConfig, FeatureStyleConfig } from '../../types';
|
||||||
import { checkFeatureMatchesStyleRule } from '../../utils/checkFeatureMatchesStyleRule';
|
import { checkFeatureMatchesStyleRule } from '../../utils/checkFeatureMatchesStyleRule';
|
||||||
import { getLayerPropertyInfo } from '../../utils/getFeatures';
|
import { getLayerPropertyInfo } from '../../utils/getFeatures';
|
||||||
import { getPublicGeoJSONFiles } from '../../utils/utils';
|
import { getPublicGeoJSONFiles } from '../../utils/utils';
|
||||||
|
|
||||||
|
|
||||||
export interface GeoJSONMapperConfig {
|
export interface GeoJSONMapperConfig {
|
||||||
// URL for a geojson file
|
// URL for a geojson file
|
||||||
src?: string;
|
src?: string;
|
||||||
@ -107,10 +109,16 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const polyStyleStrings: string[] = Object.values(GeoJSONPolyStyles);
|
||||||
|
const pointStyleStrings: string[] = Object.values(GeoJSONPointStyles);
|
||||||
|
const lineStyleStrings: string[] = Object.values(GeoJSONLineStyles);
|
||||||
const vectorLayer = new VectorLayer({
|
const vectorLayer = new VectorLayer({
|
||||||
source,
|
source,
|
||||||
style: (feature: FeatureLike) => {
|
style: (feature: FeatureLike) => {
|
||||||
const isPoint = feature.getGeometry()?.getType() === 'Point';
|
const featureType = feature.getGeometry()?.getType();
|
||||||
|
const isPoint = featureType === 'Point' || featureType === 'MultiPoint';
|
||||||
|
const isPolygon = featureType === 'Polygon' || featureType === 'MultiPolygon';
|
||||||
|
const isLine = featureType === 'LineString' || featureType === 'MultiLineString';
|
||||||
|
|
||||||
for (const check of styles) {
|
for (const check of styles) {
|
||||||
if (check.rule && !checkFeatureMatchesStyleRule(check.rule, feature)) {
|
if (check.rule && !checkFeatureMatchesStyleRule(check.rule, feature)) {
|
||||||
@ -131,6 +139,29 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
|
|||||||
return polyStyle(values);
|
return polyStyle(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support styling polygons from Feature properties
|
||||||
|
const featureProps = feature.getProperties();
|
||||||
|
if (isPolygon && Object.keys(featureProps).some((property) => polyStyleStrings.includes(property))) {
|
||||||
|
const values: StyleConfigValues = {
|
||||||
|
color: featureProps[GeoJSONPolyStyles.color] ?? check.state.base.color,
|
||||||
|
opacity: featureProps[GeoJSONPolyStyles.opacity] ?? check.state.base.opacity,
|
||||||
|
lineWidth: featureProps[GeoJSONPolyStyles.lineWidth] ?? check.state.base.lineWidth,
|
||||||
|
};
|
||||||
|
return polyStyle(values);
|
||||||
|
} else if (isLine && Object.keys(featureProps).some((property) => lineStyleStrings.includes(property))) {
|
||||||
|
const values: StyleConfigValues = {
|
||||||
|
color: featureProps[GeoJSONLineStyles.color] ?? check.state.base.color,
|
||||||
|
lineWidth: featureProps[GeoJSONLineStyles.lineWidth] ?? check.state.base.lineWidth,
|
||||||
|
};
|
||||||
|
return check.state.maker(values);
|
||||||
|
} else if (isPoint && Object.keys(featureProps).some((property) => pointStyleStrings.includes(property))) {
|
||||||
|
const values: StyleConfigValues = {
|
||||||
|
color: featureProps[GeoJSONPointStyles.color] ?? check.state.base.color,
|
||||||
|
size: featureProps[GeoJSONPointStyles.size] ?? check.state.base.size,
|
||||||
|
};
|
||||||
|
return check.state.maker(values);
|
||||||
|
}
|
||||||
|
|
||||||
// Lazy create the style object
|
// Lazy create the style object
|
||||||
if (isPoint) {
|
if (isPoint) {
|
||||||
if (!check.point) {
|
if (!check.point) {
|
||||||
@ -196,4 +227,3 @@ export const geojsonLayer: MapLayerRegistryItem<GeoJSONMapperConfig> = {
|
|||||||
},
|
},
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -127,6 +127,22 @@ export interface StyleConfigValues {
|
|||||||
textConfig?: TextStyleConfig;
|
textConfig?: TextStyleConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum GeoJSONPolyStyles {
|
||||||
|
color = 'fill',
|
||||||
|
opacity = 'fill-opacity',
|
||||||
|
lineWidth = 'stroke-width',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum GeoJSONPointStyles {
|
||||||
|
color = 'marker-color',
|
||||||
|
size = 'marker-size',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum GeoJSONLineStyles {
|
||||||
|
color = 'stroke',
|
||||||
|
lineWidth = 'stroke-width',
|
||||||
|
}
|
||||||
|
|
||||||
/** When the style depends on a field */
|
/** When the style depends on a field */
|
||||||
export interface StyleConfigFields {
|
export interface StyleConfigFields {
|
||||||
color?: string;
|
color?: string;
|
||||||
|
150
public/maps/example-with-style.geojson
Normal file
150
public/maps/example-with-style.geojson
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
{
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"name": "Example with Style",
|
||||||
|
"features": [
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "Bermuda Triangle",
|
||||||
|
"fill": "red",
|
||||||
|
"fill-opacity": 0.5,
|
||||||
|
"stroke-width": 10
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "Polygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[-80.226529, 25.789106],
|
||||||
|
[-66.1057427, 18.4663188],
|
||||||
|
[-64.78138, 32.294887]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "Bermuda Triangles",
|
||||||
|
"fill": "red",
|
||||||
|
"fill-opacity": 0.1,
|
||||||
|
"stroke-width": 1
|
||||||
|
},
|
||||||
|
"geometry": {
|
||||||
|
"type": "MultiPolygon",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[-72.5039545, 29.0419965],
|
||||||
|
[-73.16613585, 22.1277124],
|
||||||
|
[-80.226529, 25.789106]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[-65.44356135, 25.3806029],
|
||||||
|
[-73.16613585, 22.12771244],
|
||||||
|
[-66.1057427, 18.4663188]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[-65.44356135, 25.3806029],
|
||||||
|
[-72.5039545, 29.0419965],
|
||||||
|
[-64.78138, 32.294887]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": { "type": "Point", "coordinates": [-80.226529, 25.789106] },
|
||||||
|
"properties": {
|
||||||
|
"name": "Miami",
|
||||||
|
"marker-color": "rgb(255,255,0)",
|
||||||
|
"marker-size": 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "MultiPoint",
|
||||||
|
"coordinates": [
|
||||||
|
[-66.1057427, 18.4663188],
|
||||||
|
[-64.78138, 32.294887]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "San Juan and Hamilton",
|
||||||
|
"marker-color": "#F99E26",
|
||||||
|
"marker-size": 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "LineString",
|
||||||
|
"coordinates": [
|
||||||
|
[-77.76975242, 13.2503978],
|
||||||
|
[-73.16613585, 22.1277124]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "Line 1",
|
||||||
|
"stroke": "red",
|
||||||
|
"stroke-width": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "LineString",
|
||||||
|
"coordinates": [
|
||||||
|
[-55.48910779, 24.42726436],
|
||||||
|
[-65.44356135, 25.3806029]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "Line 2",
|
||||||
|
"stroke": "white",
|
||||||
|
"stroke-width": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "LineString",
|
||||||
|
"coordinates": [
|
||||||
|
[-76.38582213, 38.25780378],
|
||||||
|
[-72.5039545, 29.0419965]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "Line 3",
|
||||||
|
"stroke": "blue",
|
||||||
|
"stroke-width": 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "MultiLineString",
|
||||||
|
"coordinates": [
|
||||||
|
[
|
||||||
|
[-80.226529, 25.789106],
|
||||||
|
[-66.1057427, 18.4663188]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[-66.1057427, 18.4663188],
|
||||||
|
[-64.78138, 32.294887]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[-64.78138, 32.294887],
|
||||||
|
[-80.226529, 25.789106]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"name": "Bermuda Triangle Thin Line",
|
||||||
|
"stroke": "yellow",
|
||||||
|
"stroke-width": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user