2022-12-10 11:16:46 +00:00
|
|
|
import { Fill, Text, Icon, Stroke, Style, Circle } from 'ol/style';
|
2022-11-28 07:38:21 +00:00
|
|
|
import startIcon from '../../icons/flag-start-b-svgrepo-com-green.svg';
|
|
|
|
import finishIcon from '../../icons/flag-finish-b-o-svgrepo-com-red.svg';
|
2022-11-29 20:07:46 +00:00
|
|
|
import wptIcon from '../../icons/location-pin-svgrepo-com-green.svg';
|
2022-12-07 12:30:46 +00:00
|
|
|
import houseIcon from '../../icons/house-svgrepo-com.svg';
|
|
|
|
import houseFlatIcon from '../../icons/houseFlat-svgrepo-com.svg';
|
|
|
|
import campingIcon from '../../icons/camping-14-svgrepo-com.svg';
|
|
|
|
import farmPigIcon from '../../icons/farm-pig-svgrepo-com.svg';
|
|
|
|
import cheeseIcon from '../../icons/cheese-svgrepo-com.svg';
|
|
|
|
import trainIcon from '../../icons/train-svgrepo-com.svg';
|
|
|
|
import picnicIcon from '../../icons/picnic-svgrepo-com.svg';
|
|
|
|
import caveIcon from '../../icons/cave-entrance-svgrepo-com.svg';
|
2022-12-10 15:23:10 +00:00
|
|
|
import leftArrowIcon from '../../icons/right-arrow-svgrepo-com.svg';
|
|
|
|
import blackArrowheadPointingUp from '../../icons/black-arrowhead-pointing-up-svgrepo-com.svg';
|
2022-11-29 20:07:46 +00:00
|
|
|
import wptIconSel from '../../icons/location-pin-svgrepo-com-red.svg';
|
2022-11-28 07:38:21 +00:00
|
|
|
import { Feature } from 'ol';
|
2022-11-29 18:49:05 +00:00
|
|
|
import memoize from 'memoizee';
|
2022-12-10 15:23:10 +00:00
|
|
|
import { getMap, getState } from '../map';
|
2022-12-10 11:16:46 +00:00
|
|
|
import { Point } from 'ol/geom';
|
2022-12-10 15:23:10 +00:00
|
|
|
import { Coordinate } from 'ol/coordinate';
|
2023-01-15 14:42:53 +00:00
|
|
|
import { createDefaultStyle } from 'ol/style/Style';
|
2022-11-28 07:38:21 +00:00
|
|
|
|
2023-01-16 15:28:34 +00:00
|
|
|
import osmIcons, { highlight } from './osm-icons';
|
2023-01-15 18:29:09 +00:00
|
|
|
import { indexOf } from 'lodash';
|
|
|
|
|
2022-11-29 18:49:05 +00:00
|
|
|
interface StyleParameters {
|
|
|
|
type: string;
|
|
|
|
isSelected: boolean;
|
|
|
|
}
|
2022-11-28 07:38:21 +00:00
|
|
|
|
2022-12-07 12:30:46 +00:00
|
|
|
const icons = {
|
|
|
|
house: {
|
|
|
|
src: houseIcon,
|
|
|
|
scale: 1 / 15,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
houseFlat: {
|
|
|
|
src: houseFlatIcon,
|
|
|
|
scale: 1 / 15,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
camping: {
|
|
|
|
src: campingIcon,
|
|
|
|
scale: 2,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
farmPig: {
|
|
|
|
src: farmPigIcon,
|
|
|
|
scale: 1 / 12,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
cheese: {
|
|
|
|
src: cheeseIcon,
|
|
|
|
scale: 3 / 4,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
train: {
|
|
|
|
src: trainIcon,
|
|
|
|
scale: 1 / 10,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
picnic: {
|
|
|
|
src: picnicIcon,
|
|
|
|
scale: 1 / 15,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
cave: {
|
|
|
|
src: caveIcon,
|
|
|
|
scale: 1 / 7,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
const wptIconObj = {
|
|
|
|
src: wptIcon,
|
|
|
|
scale: 0.1,
|
|
|
|
opacity: 0.9,
|
|
|
|
anchor: [0.5, 1],
|
|
|
|
};
|
|
|
|
|
2022-11-28 11:14:09 +00:00
|
|
|
const textStroke = new Stroke({
|
|
|
|
color: '#fff',
|
|
|
|
width: 3,
|
|
|
|
});
|
2022-12-09 20:43:54 +00:00
|
|
|
const textStrokeSel = new Stroke({
|
|
|
|
color: 'blue',
|
|
|
|
width: 2,
|
|
|
|
});
|
2022-11-28 11:14:09 +00:00
|
|
|
const textFill = new Fill({
|
|
|
|
color: '#000',
|
|
|
|
});
|
2022-11-29 20:07:46 +00:00
|
|
|
const textFillSel = new Fill({
|
|
|
|
color: 'red',
|
|
|
|
});
|
2022-11-28 11:14:09 +00:00
|
|
|
|
2022-12-09 20:43:54 +00:00
|
|
|
const trksegStroke = new Stroke({
|
2023-01-16 15:16:22 +00:00
|
|
|
color: [11, 16, 71, 0.8],
|
2022-12-09 20:43:54 +00:00
|
|
|
width: 3,
|
|
|
|
});
|
|
|
|
|
|
|
|
const trksegStrokeSel = new Stroke({
|
|
|
|
color: 'red',
|
|
|
|
width: 3,
|
|
|
|
});
|
|
|
|
|
|
|
|
const rteStroke = new Stroke({
|
2023-01-16 15:16:22 +00:00
|
|
|
color: [18, 71, 11, 0.8],
|
2022-12-09 20:43:54 +00:00
|
|
|
width: 3,
|
|
|
|
});
|
|
|
|
|
|
|
|
const rteStrokeSel = new Stroke({
|
|
|
|
color: 'red',
|
|
|
|
width: 3,
|
|
|
|
});
|
|
|
|
|
2022-12-10 11:16:46 +00:00
|
|
|
const circleFill = new Fill({
|
|
|
|
color: 'rgba(255,255,255,0.4)',
|
|
|
|
});
|
|
|
|
|
|
|
|
const circleStroke = new Stroke({
|
|
|
|
color: '#3399CC',
|
|
|
|
width: 1.25,
|
|
|
|
});
|
|
|
|
|
2023-01-16 08:11:42 +00:00
|
|
|
const poiTextFill = new Fill({
|
|
|
|
color: 'white',
|
|
|
|
});
|
|
|
|
|
2022-12-10 11:16:46 +00:00
|
|
|
const circle = new Circle({
|
|
|
|
fill: circleFill,
|
|
|
|
stroke: circleStroke,
|
|
|
|
radius: 5,
|
|
|
|
});
|
|
|
|
|
|
|
|
const replacer = (key: string, value: any) => {
|
|
|
|
if (key === 'feature' && typeof value === 'object') {
|
|
|
|
return { id: value.get('id'), rev: value.getRevision() };
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
};
|
|
|
|
|
2022-12-09 20:43:54 +00:00
|
|
|
const normalizer = (params: any) => {
|
2022-12-10 11:16:46 +00:00
|
|
|
const key = JSON.stringify(params, replacer);
|
2022-12-09 20:43:54 +00:00
|
|
|
// console.log({ caller: 'getStyle / normalizer', key });
|
|
|
|
return key;
|
|
|
|
};
|
|
|
|
|
|
|
|
const memoizeOptions = {
|
|
|
|
length: 1,
|
|
|
|
normalizer,
|
2023-01-15 14:42:53 +00:00
|
|
|
max: 1024000,
|
2022-12-09 20:43:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const zoom = () => Math.floor(getState().zoom);
|
|
|
|
|
2022-11-29 18:49:05 +00:00
|
|
|
const styles = {
|
2022-12-09 20:43:54 +00:00
|
|
|
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,
|
|
|
|
};
|
2022-11-29 18:49:05 +00:00
|
|
|
},
|
2022-12-09 20:43:54 +00:00
|
|
|
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({
|
2022-11-29 18:49:05 +00:00
|
|
|
font: '16px Calibri,sans-serif',
|
2022-12-09 20:43:54 +00:00
|
|
|
text: text,
|
|
|
|
fill: isSelected ? textFillSel : textFill,
|
|
|
|
stroke: isSelected ? textStrokeSel : textStroke,
|
2022-11-29 18:49:05 +00:00
|
|
|
offsetY: -40,
|
2022-12-09 20:43:54 +00:00
|
|
|
}),
|
|
|
|
});
|
|
|
|
}, memoizeOptions),
|
2022-11-29 18:49:05 +00:00
|
|
|
},
|
2022-12-09 20:43:54 +00:00
|
|
|
trkseg: {
|
|
|
|
getParameters: (feature: Feature) => {
|
|
|
|
return {
|
|
|
|
isSelected: feature.get('isSelected') ?? false,
|
2022-12-10 15:23:10 +00:00
|
|
|
feature: zoom() >= 7 ? feature : undefined,
|
|
|
|
zoom: zoom() >= 7 ? Math.floor(zoom()) : undefined,
|
2022-12-09 20:43:54 +00:00
|
|
|
};
|
2022-11-29 18:49:05 +00:00
|
|
|
},
|
2022-12-09 20:43:54 +00:00
|
|
|
getStyle: memoize((params: any) => {
|
|
|
|
console.log({ caller: 'getStyle', params });
|
2022-12-10 15:23:10 +00:00
|
|
|
const { isSelected, feature, zoom } = params;
|
2022-12-10 11:16:46 +00:00
|
|
|
const styles = [
|
|
|
|
new Style({ stroke: isSelected ? trksegStrokeSel : trksegStroke }),
|
|
|
|
];
|
|
|
|
if (feature) {
|
2022-12-10 15:23:10 +00:00
|
|
|
const map = getMap();
|
2022-12-10 11:16:46 +00:00
|
|
|
const geometry = feature.getGeometry();
|
2022-12-10 15:23:10 +00:00
|
|
|
const coordinates = geometry.getCoordinates();
|
|
|
|
let start = coordinates[0];
|
|
|
|
let startPixels = map?.getPixelFromCoordinate(start);
|
|
|
|
coordinates.slice(1).forEach((end: Coordinate) => {
|
|
|
|
const endPixels = map?.getPixelFromCoordinate(end);
|
|
|
|
if (
|
|
|
|
startPixels !== undefined &&
|
|
|
|
endPixels !== undefined &&
|
|
|
|
Math.sqrt(
|
|
|
|
(startPixels[0] - endPixels[0]) ** 2 +
|
|
|
|
(startPixels[1] - endPixels[1]) ** 2
|
|
|
|
) > 80
|
|
|
|
) {
|
|
|
|
const dx = end[0] - start[0];
|
|
|
|
const dy = end[1] - start[1];
|
|
|
|
const rotation = Math.atan2(dy, dx) - Math.PI / 2;
|
|
|
|
styles.push(
|
|
|
|
new Style({
|
|
|
|
geometry: new Point(end),
|
|
|
|
image: new Icon({
|
|
|
|
src: blackArrowheadPointingUp,
|
|
|
|
scale: 1 / 20,
|
|
|
|
anchor: [0.5, 0.5],
|
|
|
|
rotateWithView: true,
|
|
|
|
rotation: -rotation,
|
|
|
|
}),
|
|
|
|
})
|
|
|
|
);
|
|
|
|
startPixels = endPixels;
|
|
|
|
start = end;
|
|
|
|
}
|
2022-12-10 11:16:46 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
return styles;
|
2022-12-09 20:43:54 +00:00
|
|
|
}, memoizeOptions),
|
|
|
|
},
|
|
|
|
rte: {
|
|
|
|
getParameters: (feature: Feature) => {
|
|
|
|
return {
|
|
|
|
isSelected: feature.get('isSelected') ?? false,
|
|
|
|
};
|
2022-11-29 20:07:46 +00:00
|
|
|
},
|
2022-12-09 20:43:54 +00:00
|
|
|
getStyle: memoize((params: any) => {
|
|
|
|
console.log({ caller: 'getStyle', params });
|
|
|
|
const { isSelected } = params;
|
|
|
|
return new Style({ stroke: isSelected ? rteStrokeSel : rteStroke });
|
|
|
|
}, memoizeOptions),
|
2022-11-29 18:49:05 +00:00
|
|
|
},
|
2023-01-09 19:51:17 +00:00
|
|
|
route: {
|
|
|
|
getParameters: (feature: Feature) => {
|
|
|
|
return {
|
|
|
|
isSelected: feature.get('isSelected') ?? false,
|
2023-01-13 13:02:58 +00:00
|
|
|
name: feature.get('name'),
|
2023-01-09 19:51:17 +00:00
|
|
|
};
|
|
|
|
},
|
|
|
|
getStyle: memoize((params: any) => {
|
|
|
|
console.log({ caller: 'getStyle', params });
|
2023-01-13 13:02:58 +00:00
|
|
|
const { isSelected, name } = params;
|
|
|
|
return new Style({
|
|
|
|
stroke: isSelected ? routeStrokeSel : routeStroke,
|
|
|
|
text: new Text({
|
|
|
|
text: name,
|
|
|
|
font: 'bold 14px "Open Sans", "Arial Unicode MS", "sans-serif"',
|
|
|
|
placement: 'line',
|
|
|
|
padding: [2, 2, 2, 2],
|
|
|
|
fill: new Fill({
|
|
|
|
color: 'black',
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
});
|
2023-01-09 19:51:17 +00:00
|
|
|
}, memoizeOptions),
|
|
|
|
},
|
2023-01-17 11:40:38 +00:00
|
|
|
way: {
|
2023-01-16 08:28:57 +00:00
|
|
|
strokes: {
|
|
|
|
iwn: new Stroke({
|
|
|
|
color: [174, 33, 219, 0.8],
|
|
|
|
width: 6,
|
|
|
|
}),
|
|
|
|
nwn: new Stroke({
|
|
|
|
color: [174, 33, 219, 0.8],
|
2023-01-16 15:16:22 +00:00
|
|
|
width: 5,
|
2023-01-16 08:28:57 +00:00
|
|
|
}),
|
|
|
|
rwn: new Stroke({
|
|
|
|
color: [174, 33, 219, 0.8],
|
2023-01-16 15:16:22 +00:00
|
|
|
width: 5,
|
2023-01-16 08:28:57 +00:00
|
|
|
lineDash: [10, 10],
|
|
|
|
}),
|
|
|
|
lwn: new Stroke({
|
|
|
|
color: [174, 33, 219, 0.8],
|
2023-01-16 15:16:22 +00:00
|
|
|
width: 3,
|
2023-01-16 08:28:57 +00:00
|
|
|
lineDash: [10, 10],
|
|
|
|
}),
|
|
|
|
},
|
2023-01-15 14:42:53 +00:00
|
|
|
getParameters: (feature: Feature) => {
|
|
|
|
return {
|
|
|
|
isSelected: feature.get('isSelected') ?? false,
|
|
|
|
name: feature.get('name'),
|
2023-01-16 08:28:57 +00:00
|
|
|
network: feature.get('network'),
|
2023-01-15 14:42:53 +00:00
|
|
|
};
|
|
|
|
},
|
|
|
|
getStyle: memoize((params: any) => {
|
|
|
|
console.log({ caller: 'getStyle', params });
|
2023-01-16 08:28:57 +00:00
|
|
|
const { isSelected, name, network } = params;
|
2023-01-15 14:42:53 +00:00
|
|
|
return new Style({
|
2023-01-17 11:40:38 +00:00
|
|
|
stroke: styles.way.strokes[network],
|
2023-01-15 14:42:53 +00:00
|
|
|
text: new Text({
|
|
|
|
text: name,
|
|
|
|
font: 'bold 14px "Open Sans", "Arial Unicode MS", "sans-serif"',
|
|
|
|
placement: 'line',
|
|
|
|
padding: [2, 2, 2, 2],
|
|
|
|
fill: new Fill({
|
|
|
|
color: 'black',
|
|
|
|
}),
|
|
|
|
}),
|
|
|
|
});
|
|
|
|
}, memoizeOptions),
|
|
|
|
},
|
2023-01-17 11:40:38 +00:00
|
|
|
poi: {
|
2023-01-15 18:29:09 +00:00
|
|
|
getParameters: (feature: Feature) => {
|
2023-01-16 15:28:34 +00:00
|
|
|
const klass: string = feature.get('class');
|
|
|
|
const isHighlighted = highlight.hasOwnProperty(klass);
|
2023-01-15 18:29:09 +00:00
|
|
|
return {
|
|
|
|
isSelected: feature.get('isSelected') ?? false,
|
|
|
|
name: feature.get('name'),
|
2023-01-16 15:28:34 +00:00
|
|
|
klass,
|
|
|
|
isHighlighted,
|
2023-01-16 15:16:22 +00:00
|
|
|
isTextHidden: zoom() < 19,
|
2023-01-16 15:28:34 +00:00
|
|
|
isHidden: !isHighlighted && zoom() < 16,
|
2023-01-15 18:29:09 +00:00
|
|
|
};
|
|
|
|
},
|
|
|
|
getStyle: memoize((params: any) => {
|
|
|
|
console.log({ caller: 'getStyle', params });
|
2023-01-16 15:28:34 +00:00
|
|
|
const { isSelected, name, klass, isHidden, isTextHidden, isHighlighted } =
|
|
|
|
params;
|
2023-01-16 08:11:42 +00:00
|
|
|
if (isHidden) {
|
|
|
|
return null;
|
|
|
|
}
|
2023-01-15 18:29:09 +00:00
|
|
|
const icon = osmIcons[klass];
|
|
|
|
if (icon === undefined) {
|
2023-01-16 08:11:42 +00:00
|
|
|
return undefined;
|
2023-01-15 18:29:09 +00:00
|
|
|
}
|
|
|
|
return new Style({
|
|
|
|
image: new Icon({
|
|
|
|
src: icon,
|
2023-01-16 15:28:34 +00:00
|
|
|
scale: isHighlighted ? 3 : 1.5,
|
2023-01-16 08:11:42 +00:00
|
|
|
opacity: 1,
|
2023-01-15 20:35:08 +00:00
|
|
|
// anchor: [0, 0],
|
2023-01-15 18:29:09 +00:00
|
|
|
}),
|
2023-01-16 15:16:22 +00:00
|
|
|
text:
|
|
|
|
name && !isTextHidden
|
|
|
|
? new Text({
|
|
|
|
text: name,
|
|
|
|
font: 'bold 14px "Open Sans", "Arial Unicode MS", "sans-serif"',
|
|
|
|
offsetY: +40,
|
|
|
|
padding: [0, 0, 0, 0],
|
|
|
|
fill: new Fill({
|
|
|
|
color: 'black',
|
|
|
|
}),
|
|
|
|
backgroundFill: poiTextFill,
|
|
|
|
})
|
|
|
|
: undefined,
|
2023-01-15 18:29:09 +00:00
|
|
|
});
|
|
|
|
}, memoizeOptions),
|
|
|
|
},
|
2022-11-29 18:49:05 +00:00
|
|
|
};
|
2022-11-28 11:14:09 +00:00
|
|
|
|
2023-01-15 14:42:53 +00:00
|
|
|
export const style = (feature: Feature, resolution: number) => {
|
|
|
|
const type = (
|
|
|
|
feature.get('type') !== undefined ? feature.get('type') : feature.type_
|
|
|
|
) as keyof typeof styles;
|
2022-12-09 20:43:54 +00:00
|
|
|
const styleForType = styles[type];
|
|
|
|
if (!styleForType) {
|
2023-01-15 18:29:09 +00:00
|
|
|
// console.log({ caller: 'style / default', type, feature, resolution });
|
2023-01-15 14:42:53 +00:00
|
|
|
return createDefaultStyle(feature, resolution)[0];
|
2022-11-28 10:52:50 +00:00
|
|
|
}
|
2022-12-09 20:43:54 +00:00
|
|
|
const params = styles[type].getParameters(feature);
|
|
|
|
const getStyle = styles[type].getStyle;
|
2023-01-13 13:02:58 +00:00
|
|
|
const style = getStyle(params);
|
2023-01-15 20:35:08 +00:00
|
|
|
console.log({ caller: 'style', feature, type, params, style });
|
2023-01-16 08:11:42 +00:00
|
|
|
if (style === undefined) {
|
2023-01-15 18:29:09 +00:00
|
|
|
return createDefaultStyle(feature, resolution)[0];
|
|
|
|
}
|
2023-01-13 13:02:58 +00:00
|
|
|
return style;
|
2022-11-28 07:38:21 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export default style;
|