From 4281c5afc13e106a3c4682a1d290bf87651e0ce9 Mon Sep 17 00:00:00 2001 From: nikki-kiga <42276368+nikki-kiga@users.noreply.github.com> Date: Thu, 11 Nov 2021 12:27:57 -0800 Subject: [PATCH] Geomap: Add opacity and prepare svg (#41170) --- .../geomap/editor/GazetteerPathEditor.tsx | 4 +-- .../panel/geomap/layers/data/markersLayer.tsx | 30 +++++++++++----- public/app/plugins/panel/geomap/types.ts | 4 ++- .../panel/geomap/utils/getGeoMapStyle.ts | 1 - .../plugins/panel/geomap/utils/prepareSVG.ts | 34 +++++++++++++++++++ public/img/icons/marker/plane.svg | 2 +- 6 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 public/app/plugins/panel/geomap/utils/prepareSVG.ts diff --git a/public/app/plugins/panel/geomap/editor/GazetteerPathEditor.tsx b/public/app/plugins/panel/geomap/editor/GazetteerPathEditor.tsx index 5c749da7ab4..e9e8d006e78 100644 --- a/public/app/plugins/panel/geomap/editor/GazetteerPathEditor.tsx +++ b/public/app/plugins/panel/geomap/editor/GazetteerPathEditor.tsx @@ -43,7 +43,7 @@ export const GazetteerPathEditor: FC { let options = settings?.options ? [...settings.options] : [...defaultPaths]; - let current = options.find((f) => f.value === gaz?.path); + let current = options?.find((f) => f.value === gaz?.path); if (!current && gaz) { current = { label: gaz.path, @@ -52,7 +52,7 @@ export const GazetteerPathEditor: FC diff --git a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx index 7d59a3306c1..b2701d75ec4 100644 --- a/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx +++ b/public/app/plugins/panel/geomap/layers/data/markersLayer.tsx @@ -30,6 +30,7 @@ import { getMarkerFromPath } from '../../utils/regularShapes'; import { ReplaySubject } from 'rxjs'; import { FeaturesStylesBuilderConfig, getFeatures } from '../../utils/getFeatures'; import { StyleMaker, StyleMakerConfig } from '../../types'; +import { getSVGUri } from '../../utils/prepareSVG'; // Configuration options for Circle overlays export interface MarkersConfig { @@ -99,6 +100,11 @@ export const markersLayer: MapLayerRegistryItem = { legend = ; } + const markerPath = + getPublicOrAbsoluteUrl(config.markerSymbol?.fixed) ?? getPublicOrAbsoluteUrl('img/icons/marker/circle.svg'); + // double to match regularshapes using size as radius + const uri = await getSVGUri(markerPath, config.size.fixed * 2); + return { init: () => vectorLayer, legend: legend, @@ -107,22 +113,30 @@ export const markersLayer: MapLayerRegistryItem = { return; // ignore empty } - const markerPath = - getPublicOrAbsoluteUrl(config.markerSymbol?.fixed) ?? getPublicOrAbsoluteUrl('img/icons/marker/circle.svg'); - - const marker = getMarkerFromPath(config.markerSymbol?.fixed); - const makeIconStyle = (cfg: StyleMakerConfig) => { - return new style.Style({ + const icon = new style.Style({ image: new style.Icon({ - src: markerPath, + src: uri, color: cfg.color, - // opacity, + opacity: cfg.opacity, + // scale based on field value scale: (DEFAULT_SIZE + cfg.size) / 100, }), }); + // transparent bounding box for featureAtPixel detection + const boundingBox = new style.Style({ + image: new style.RegularShape({ + fill: new style.Fill({ color: 'rgba(0,0,0,0)' }), + points: 4, + radius: cfg.size, + angle: Math.PI / 4, + }), + }); + return [icon, boundingBox] }; + const marker = getMarkerFromPath(config.markerSymbol?.fixed); + const shape: StyleMaker = marker?.make ?? makeIconStyle; const features: Feature[] = []; diff --git a/public/app/plugins/panel/geomap/types.ts b/public/app/plugins/panel/geomap/types.ts index 0e02b9dd74c..6352fe05873 100644 --- a/public/app/plugins/panel/geomap/types.ts +++ b/public/app/plugins/panel/geomap/types.ts @@ -47,6 +47,7 @@ export interface GeomapPanelOptions { } export interface FeatureStyleConfig { fillColor: string; //eventually be ColorDimensionConfig + opacity?: number; strokeWidth?: number; rule?: FeatureRuleConfig; } @@ -84,6 +85,7 @@ export interface StyleMakerConfig { size: number; markerPath?: string; text?: string; + opacity?: number; } -export type StyleMaker = (config: StyleMakerConfig) => Style; +export type StyleMaker = (config: StyleMakerConfig) => Style | Style[]; diff --git a/public/app/plugins/panel/geomap/utils/getGeoMapStyle.ts b/public/app/plugins/panel/geomap/utils/getGeoMapStyle.ts index 4ec8311cdd4..38b4f410745 100644 --- a/public/app/plugins/panel/geomap/utils/getGeoMapStyle.ts +++ b/public/app/plugins/panel/geomap/utils/getGeoMapStyle.ts @@ -16,6 +16,5 @@ export const getGeoMapStyle = (config: FeatureStyleConfig, property: any) => { width: config.strokeWidth, }) : undefined, - //handle a shape/marker too? }); }; diff --git a/public/app/plugins/panel/geomap/utils/prepareSVG.ts b/public/app/plugins/panel/geomap/utils/prepareSVG.ts new file mode 100644 index 00000000000..2b6fb831cff --- /dev/null +++ b/public/app/plugins/panel/geomap/utils/prepareSVG.ts @@ -0,0 +1,34 @@ +import { getPublicOrAbsoluteUrl } from 'app/features/dimensions'; + +const getUri = (url: string, size: number): Promise => { + return fetch(url, { method: 'GET' }) + .then((res) => { + return res.text(); + }) + .then((text) => { + const parser = new DOMParser(); + const doc = parser.parseFromString(text, 'image/svg+xml'); + const svg = doc.getElementsByTagName('svg')[0]; + if (!svg) { + return ''; + } + //set to white so ol color tint works + svg.setAttribute('fill', '#fff'); + const svgString = new XMLSerializer().serializeToString(svg); + const svgURI = encodeURIComponent(svgString); + return `data:image/svg+xml,${svgURI}`; + }) + .catch((error) => { + console.error(error); + return ''; + }); +}; + +export const getSVGUri = async (url: string, size: number) => { + const svgURI = await getUri(url, size); + + if (!svgURI) { + return getPublicOrAbsoluteUrl('img/icons/marker/circle.svg'); + } + return svgURI; +}; diff --git a/public/img/icons/marker/plane.svg b/public/img/icons/marker/plane.svg index a49c2c502fb..39fd8c8b4b8 100644 --- a/public/img/icons/marker/plane.svg +++ b/public/img/icons/marker/plane.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file