You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@baremaps.apache.org by le...@apache.org on 2023/07/04 09:35:14 UTC

[incubator-baremaps-site] 02/03: Add map style select

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 <le...@gmail.com>
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}>