diff --git a/react/src/components/Map/Map.css b/react/src/components/Map/Map.css index 77ee8b8b..9a5c2edc 100644 --- a/react/src/components/Map/Map.css +++ b/react/src/components/Map/Map.css @@ -12,3 +12,6 @@ justify-content: center; font: 14px var(--global-font-family--sans); } + +.custom-marker { +} diff --git a/react/src/components/Map/Map.tsx b/react/src/components/Map/Map.tsx index afb6e66a..1afcae65 100644 --- a/react/src/components/Map/Map.tsx +++ b/react/src/components/Map/Map.tsx @@ -86,17 +86,112 @@ const LeafletMap: React.FC = ({ [selectedFeatureId] ); + /* + * move to module.css + * circle marker for points + * create custom icon marker + * create circle icon marker with style + */ const createCustomIcon = useCallback((feature: Feature) => { - const featureFAIcon = featureTypeToIcon(getFeatureType(feature)); + const defaultFillColor = 'var(--global-color-accent--normal)'; + const createCircleIcon = (customStyle = {}) => { + const defaultCustomStyle = { + radius: 8, + fillColor: defaultFillColor, + color: 'black', + weight: 1, + opacity: 1, + fillOpacity: 0.8, + }; + + const style = { ...defaultCustomStyle, ...customStyle }; + + // Add padding for the stroke + const padding = style.weight; + const totalSize = style.radius * 2 + padding * 2; + const center = totalSize / 2; + + return L.divIcon({ + html: ` + + + + `, + className: '', + iconSize: [totalSize, totalSize], + iconAnchor: [center, center], + }); + }; + + const createFontAwesomeIcon = ( + faIconString: string, + customStyle: { color?: string; backgroundColor?: string } = {} + ) => { + const color = customStyle?.color ?? defaultFillColor; + const backgroundColor = customStyle?.backgroundColor ?? '#ffffff'; + + const divHtml = ` +
+ +
+ `; + + return L.divIcon({ + html: divHtml, + className: 'custom-marker', + iconSize: [40, 40], + iconAnchor: [20, 20], + }); + }; + + const customStyle = feature.properties?.style; + if (customStyle) { + if (customStyle.faIcon) { + return createFontAwesomeIcon(customStyle.faIcon, customStyle); + } else { + return createCircleIcon(customStyle); + } + } + + const featureType = getFeatureType(feature); + + if (featureType === FeatureType.Point) { + return createCircleIcon(); + } + + const featureFAIcon = featureTypeToIcon(featureType); + // Get SVG path directly from the icon object const iconPath = featureFAIcon.icon[4]; return L.divIcon({ html: `
@@ -143,10 +238,10 @@ const LeafletMap: React.FC = ({ } = useMemo(() => { return featureCollection.features.reduce( (accumulator, feature: Feature) => { - if (feature.geometry.type === 'Point') { + if (feature.geometry.type === FeatureType.Point) { accumulator.markerFeatures.push(feature); } else { - if (getFeatureType(feature) === 'point_cloud') { + if (getFeatureType(feature) === FeatureType.PointCloud) { // Add a marker at the calculated position const markerPosition = calculatePointCloudMarkerPosition( feature.geometry diff --git a/react/src/index.css b/react/src/index.css index 27f096d5..82a2ff29 100644 --- a/react/src/index.css +++ b/react/src/index.css @@ -3,6 +3,10 @@ /* prettier-ignore */ @import url('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') layer(foundation); +/* needed for custom icons on map (to support taggit) */ +@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css') +layer(foundation); + @import url('@tacc/core-styles/dist/core-styles.base.css') layer(base); @import url('@tacc/core-styles/dist/core-styles.portal.css') layer(base);