import Style from 'ol/style/Style' import Icon from 'ol/style/Icon' import { MarkerStyle } from '@polar/lib-custom-types' import { getPolygonFillHatch } from './hatches' type GetMarkerFunction = (style: MarkerStyle, multi: boolean) => Style // these have been measured to fit once and influence marker size const imgSize: [number, number] = [26, 36] const imgSizeMulti: [number, number] = [40, 36] const defaultStroke = '#FFFFFF' const defaultStrokeWidth = '2' const defaultFill = '#005CA9' const defaultHoverFill = '#7B1045' const defaultSelectionFill = '#679100' const defaultUnselectableFill = '#333333' const prefix = 'data:image/svg+xml,' const getImagePattern = (fill: Exclude) => typeof fill === 'string' ? '' : ` ` /* Path of marker svg used in this file copied and adapted from * @masterportal/masterportalapi/public/marker.svg. */ const makeMarker = ({ fill = defaultFill, size = imgSize, stroke = defaultStroke, strokeWidth = defaultStrokeWidth, }: MarkerStyle) => `${prefix}${encodeURIComponent(` DB6C494E-88E8-49F1-89CE-97CBEC3A5240 ${getImagePattern(fill)} `)}` const makeMultiMarker = ({ clusterSize = imgSizeMulti, fill = defaultFill, stroke = defaultStroke, strokeWidth = defaultStrokeWidth, }: MarkerStyle) => `${prefix}${encodeURIComponent(` 0A6F4952-4A5A-4E86-88E4-4B3D2EA1E3DF ${getImagePattern(fill)} `)}` // center bottom of marker 📍 is intended to show the spot const anchor = [0.5, 1] /** * The map became a little laggy due to constant re-generation of styles. * This memoization function optimises this issue by reusing styles. * */ const memoizeStyle = (getMarker: GetMarkerFunction): GetMarkerFunction => { const singleCache = new Map() const multiCache = new Map() return (style, multi) => { const cache = multi ? multiCache : singleCache if (cache.has(style)) { return cache.get(style) } const markerStyle = getMarker(style, multi) cache.set(style, markerStyle) if (cache.size > 1000) { console.warn( `@polar/core: 1000+ styles have been created. This is possibly a memory leak. Please mind that the methods exported by this module are memoized. You *may* be calling the methods with constantly newly generated objects, or maybe there's just a lot of styles.` ) } return markerStyle } } const getStyleFunction = (fallbackFill: string): GetMarkerFunction => (style, multi = false) => new Style({ image: new Icon({ src: (multi ? makeMultiMarker : makeMarker)({ fill: fallbackFill, ...style, }), anchor, }), }) export const getDefaultStyle = memoizeStyle(getStyleFunction(defaultFill)) export const getHoveredStyle = memoizeStyle(getStyleFunction(defaultHoverFill)) export const getSelectedStyle = memoizeStyle( getStyleFunction(defaultSelectionFill) ) export const getUnselectableStyle = memoizeStyle( getStyleFunction(defaultUnselectableFill) )