This is an automated email from the ASF dual-hosted git repository. leonardcs pushed a commit to branch feature/styles in repository https://gitbox.apache.org/repos/asf/incubator-baremaps-site.git
commit 56bdb3653309b9b41f2ca592f6965652337fb2f6 Author: Leonard <[email protected]> AuthorDate: Tue Jul 4 10:47:10 2023 +0200 Add map style select --- src/components/GeocoderSearch/style.module.css | 2 +- src/components/MapStyleSelect/index.tsx | 43 ++++++++++++++++++++++ src/components/MapStyleSelect/style.module.css | 45 +++++++++++++++++++++++ src/components/map/index.tsx | 22 +++++++++-- src/components/map/mapStyles.ts | 51 ++++++++++++++++++++++++++ src/components/map/style.module.css | 7 +++- src/pages/index.mdx | 2 +- 7 files changed, 165 insertions(+), 7 deletions(-) diff --git a/src/components/GeocoderSearch/style.module.css b/src/components/GeocoderSearch/style.module.css index a519823..9a757e9 100644 --- a/src/components/GeocoderSearch/style.module.css +++ b/src/components/GeocoderSearch/style.module.css @@ -6,7 +6,7 @@ /* Responsive width for small screens */ @media screen and (max-width: 768px) { .ctrl-container { - width: 85%; + width: 70%; } } diff --git a/src/components/MapStyleSelect/index.tsx b/src/components/MapStyleSelect/index.tsx new file mode 100644 index 0000000..1c59044 --- /dev/null +++ b/src/components/MapStyleSelect/index.tsx @@ -0,0 +1,43 @@ +import cn from 'clsx'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faFillDrip } from '@fortawesome/free-solid-svg-icons'; +import { MapStyle } from '../map/mapStyles'; +import styles from './style.module.css'; + +interface MapStyleSelectProps { + map: maplibregl.Map; + mapStyles: MapStyle[]; +} + +export const MapStyleSelect: React.FC<MapStyleSelectProps> = ({ + map, + mapStyles +}) => { + return ( + <div className={cn(styles['ctrl-container'], 'maplibregl-ctrl-top-left')}> + <div + className={cn( + styles['select-container'], + 'maplibregl-ctrl maplibregl-ctrl-group' + )} + > + <FontAwesomeIcon icon={faFillDrip} className={styles.icon} /> + <select + className={styles['style-select']} + onChange={e => { + const style = mapStyles.find(style => style.name === e.target.value); + if (style) { + map.setStyle(style.styleUrl); + } + }} + > + {mapStyles.map(style => ( + <option key={style.name} value={style.name}> + {style.name} + </option> + ))} + </select> + </div> + </div> + ); +}; diff --git a/src/components/MapStyleSelect/style.module.css b/src/components/MapStyleSelect/style.module.css new file mode 100644 index 0000000..63aece0 --- /dev/null +++ b/src/components/MapStyleSelect/style.module.css @@ -0,0 +1,45 @@ +.ctrl-container { + left: 465px; + color: black; +} + +/* Responsive width for small screens */ +@media screen and (max-width: 768px) { + .ctrl-container { + left: 72%; + } +} + +.icon { + padding: 0 10px; +} + +.select-container { + width: 100%; + height: 29px; + display: flex; + align-items: center; +} + +.style-select { + appearance: none; + border: none; + background-color: white; + outline: none; + box-shadow: none; + padding-right: 20px; + + background-image: linear-gradient(45deg, transparent 50%, gray 50%), + linear-gradient(135deg, gray 50%, transparent 50%); + background-position: calc(100% - 5px) calc(50% + 2px), 100% calc(50% + 2px); + background-size: 5px 5px, 5px 5px; + background-repeat: no-repeat; +} + +.theme-select:focus { + background-image: linear-gradient(135deg, transparent 50%, gray 50%), + linear-gradient(45deg, gray 50%, transparent 50%); + background-position: calc(100% - 5px) 50%, 100% 50%; + background-size: 5px 5px, 5px 5px; + background-repeat: no-repeat; +} diff --git a/src/components/map/index.tsx b/src/components/map/index.tsx index 054731f..3b9ca55 100644 --- a/src/components/map/index.tsx +++ b/src/components/map/index.tsx @@ -1,10 +1,13 @@ import React, { useRef, useEffect, useState } from 'react'; +import cn from 'clsx'; import maplibregl from 'maplibre-gl'; import MaplibreInspect from '@/lib/maplibre/dist/maplibre-gl-inspect/maplibre-gl-inspect'; import MaplibreTileBoundaries from '@/lib/maplibre/dist/maplibre-gl-tile-boundaries/maplibre-gl-tile-boundaries'; import styles from './style.module.css'; import { GeocoderSearch } from '../GeocoderSearch'; +import { STYLES } from './mapStyles'; +import { MapStyleSelect } from '../MapStyleSelect'; interface MapProps { longitude?: number; @@ -25,6 +28,10 @@ interface MapProps { getControls?: () => maplibregl.IControl[]; geocoder?: boolean; ipToLoc?: boolean; + styleSelect?: boolean; + /** Map CSS styles */ + rounded?: boolean; + style?: React.CSSProperties; } export const getDefaultControls = (): maplibregl.IControl[] => [ @@ -55,7 +62,10 @@ export default function Map({ mapOptions = {} as maplibregl.MapOptions, getControls = getDefaultControls, geocoder = true, - ipToLoc = true + ipToLoc = true, + styleSelect = false, + rounded = true, + style = {} }: MapProps) { const mapContainer = useRef(null); const [map, setMap] = useState(null); @@ -97,17 +107,23 @@ export default function Map({ setMap(newMap); }; - initMap(); + if (!map) { + initMap(); + } }, []); return ( - <div className={styles.wrap}> + <div + className={cn(styles.wrap, rounded ? styles.rounded : '')} + style={style} + > {geocoder && ( <GeocoderSearch url="https://demo.baremaps.com/api/geocoder" map={map} /> )} + {styleSelect && <MapStyleSelect map={map} mapStyles={STYLES} />} <div ref={mapContainer} className={styles.map} /> </div> ); diff --git a/src/components/map/mapStyles.ts b/src/components/map/mapStyles.ts new file mode 100644 index 0000000..81a42be --- /dev/null +++ b/src/components/map/mapStyles.ts @@ -0,0 +1,51 @@ +export interface MapStyle { + name: string; + styleUrl: string; +} + +export const STYLES: MapStyle[] = [ + { + name: 'Default', + styleUrl: '/mapStyles/default.json' + }, + { + name: 'Light', + styleUrl: '/mapStyles/light.json' + }, + { + name: 'Dark', + styleUrl: '/mapStyles/dark.json' + }, + { + name: 'Achromatomaly', + styleUrl: '/mapStyles/achromatomaly.json' + }, + { + name: 'Achromatopsia', + styleUrl: '/mapStyles/achromatopsia.json' + }, + { + name: 'Deuteranomaly', + styleUrl: '/mapStyles/deuteranomaly.json' + }, + { + name: 'Deuteranopia', + styleUrl: '/mapStyles/deuteranopia.json' + }, + { + name: 'Protanomaly', + styleUrl: '/mapStyles/protanomaly.json' + }, + { + name: 'Protanopia', + styleUrl: '/mapStyles/protanopia.json' + }, + { + name: 'Tritanomaly', + styleUrl: '/mapStyles/tritanomaly.json' + }, + { + name: 'Tritanopia', + styleUrl: '/mapStyles/tritanopia.json' + } +]; diff --git a/src/components/map/style.module.css b/src/components/map/style.module.css index 509f84c..2267eb7 100644 --- a/src/components/map/style.module.css +++ b/src/components/map/style.module.css @@ -8,11 +8,14 @@ .map { position: absolute; color: black; - border: solid 1px lightgray; - border-radius: 0.75rem; width: 100%; height: 100%; overflow: hidden; +} + +.rounded { + border: solid 1px lightgray; + border-radius: 0.75rem; /* this fixes the overflow:hidden for canvas - corresponds to 1 black pixel */ -webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); } diff --git a/src/pages/index.mdx b/src/pages/index.mdx index 542b2aa..f0a322a 100644 --- a/src/pages/index.mdx +++ b/src/pages/index.mdx @@ -34,7 +34,7 @@ import { IconTitle } from '@/components/titles/IconTitle'; <div className="content-container"> <Features> <Feature index={0} plain large style={{ height: 600 }}> - <Map /> + <Map styleSelect /> </Feature> <Feature index={0}> <IconTitle icon={faListCheck}>
