diff --git a/src/components/gpx/styles.ts b/src/components/gpx/styles.ts index a50dafe..f4c3e48 100644 --- a/src/components/gpx/styles.ts +++ b/src/components/gpx/styles.ts @@ -82,6 +82,10 @@ const textStroke = new Stroke({ color: '#fff', width: 3, }); +const textStrokeSel = new Stroke({ + color: 'blue', + width: 2, +}); const textFill = new Fill({ color: '#000', }); @@ -89,176 +93,106 @@ const textFillSel = new Fill({ color: 'red', }); +const trksegStroke = new Stroke({ + color: 'blue', + width: 3, +}); + +const trksegStrokeSel = new Stroke({ + color: 'red', + width: 3, +}); + +const rteStroke = new Stroke({ + color: 'green', + width: 3, +}); + +const rteStrokeSel = new Stroke({ + color: 'red', + width: 3, +}); + +const normalizer = (params: any) => { + const key = JSON.stringify(params); + // console.log({ caller: 'getStyle / normalizer', key }); + return key; +}; + +const memoizeOptions = { + length: 1, + normalizer, + max: 1024, +}; + +const zoom = () => Math.floor(getState().zoom); + const styles = { - default: { - trkseg: { - stroke: new Stroke({ - color: 'blue', - width: 3, - }), + wpt: { + getParameters: (feature: Feature) => { + const minZoom = feature.get('extensions')?.['dyo:minZoom']; + return { + isSelected: feature.get('isSelected') ?? false, + text: feature.get('name'), + customIcon: icons[feature.get('sym') as keyof typeof icons], + hidden: minZoom && zoom() < minZoom, + }; }, - 'trkseg-start': { - image: new Icon({ - src: startIcon, - scale: 0.2, - opacity: 0.6, - anchor: [0.5, 1], - }), - }, - 'trkseg-finish': { - image: new Icon({ - src: finishIcon, - scale: 0.2, - opacity: 0.6, - anchor: [0.5, 1], - }), - }, - rte: { - stroke: new Stroke({ - color: 'green', - width: 5, - }), - }, - 'rte-start': { - image: new Icon({ - src: startIcon, - scale: 0.3, - opacity: 0.6, - anchor: [0.5, 1], - }), - }, - 'rte-finish': { - image: new Icon({ - src: finishIcon, - scale: 0.3, - opacity: 0.6, - anchor: [0.5, 1], - }), - }, - wpt: { - image: (feature: Feature, zoom: number) => { - const minZoom = feature.get('extensions')?.['dyo:minZoom']; - if (minZoom && zoom < minZoom) { - return null; - } - const customIcon = icons[feature.get('sym') as keyof typeof icons]; - const icon = customIcon ?? wptIconObj; - return new Icon(icon); - }, - text: (feature: Feature, zoom: number) => { - const minZoom = feature.get('extensions')?.['dyo:minZoom']; - if (minZoom && zoom < minZoom) { - return null; - } - return new Text({ + getStyle: memoize((params: any) => { + console.log({ caller: 'getStyle', params }); + const { isSelected, text, customIcon, hidden } = params; + if (hidden) { + return null; + } + const icon = customIcon ?? wptIconObj; + return new Style({ + image: new Icon(icon), + text: new Text({ font: '16px Calibri,sans-serif', - text: feature.get('name'), - fill: textFill, - stroke: textStroke, - offsetY: -40, - }); - }, - }, - }, - selected: { - trkseg: { - stroke: new Stroke({ - color: 'red', - width: 3, - }), - }, - rte: { - stroke: new Stroke({ - color: 'red', - width: 5, - }), - }, - wpt: { - image: new Icon({ - src: wptIconSel, - scale: 0.1, - opacity: 0.9, - anchor: [0.5, 1], - }), - text: (feature: Feature) => - new Text({ - font: '16px Calibri,sans-serif', - text: feature.get('name'), - fill: textFillSel, - stroke: textStroke, + text: text, + fill: isSelected ? textFillSel : textFill, + stroke: isSelected ? textStrokeSel : textStroke, offsetY: -40, }), + }); + }, memoizeOptions), + }, + trkseg: { + getParameters: (feature: Feature) => { + return { + isSelected: feature.get('isSelected') ?? false, + }; }, + getStyle: memoize((params: any) => { + console.log({ caller: 'getStyle', params }); + const { isSelected } = params; + return new Style({ stroke: isSelected ? trksegStrokeSel : trksegStroke }); + }, memoizeOptions), + }, + rte: { + getParameters: (feature: Feature) => { + return { + isSelected: feature.get('isSelected') ?? false, + }; + }, + getStyle: memoize((params: any) => { + console.log({ caller: 'getStyle', params }); + const { isSelected } = params; + return new Style({ stroke: isSelected ? rteStrokeSel : rteStroke }); + }, memoizeOptions), }, }; -const styleRequiresFeatureAndZoom = memoize( - (type: keyof typeof styles.default) => { - const defaults = styles.default[type]; - const selected = styles.selected[type]; - const all = { ...selected, ...defaults }; - for (const key of Object.keys(all)) { - if (all[key] instanceof Function && all[key].length > 1) { - return true; - } - } - return false; - } -); - -const styleRequiresFeature = memoize((type: keyof typeof styles.default) => { - const defaults = styles.default[type]; - const selected = styles.selected[type]; - const all = { ...selected, ...defaults }; - for (const key of Object.keys(all)) { - if (all[key] instanceof Function) { - return true; - } - } - return false; -}); - -const getStyle = memoize( - ( - type: keyof typeof styles.default, - isSelected: boolean = false, - feature: any, - zoom: any - ) => { - const defaults = styles.default[type]; - const selected = styles.selected[type]; - const all = isSelected ? { ...defaults, ...selected } : { ...defaults }; - // console.log({ - // caller: 'style / getStyle', - // type, - // isSelected, - // params, - // defaults, - // selected, - // all, - // }); - for (const key of Object.keys(all)) { - if (all[key] instanceof Function) { - all[key] = all[key](feature, zoom); - } - } - return new Style(all); - }, - { length: 4, max: 1024 } -); - export const style = (feature: Feature) => { - const type = feature.get('type'); - const isSelected = feature.get('isSelected') === true; - // console.log({ caller: 'style', type, isSelected }); - if (styleRequiresFeatureAndZoom(type)) { - const zoom = Math.floor(getState().zoom); - return getStyle(type, isSelected, feature, zoom); + const type = feature.get('type') as keyof typeof styles; + console.log({ caller: 'style', type }); + const styleForType = styles[type]; + if (!styleForType) { + return null; } - if (styleRequiresFeature(type)) { - return getStyle(type, isSelected, feature, null); - } - return getStyle(type, isSelected, null, null); + const params = styles[type].getParameters(feature); + const getStyle = styles[type].getStyle; + return getStyle(params); }; export default style;