From 6ee99d033f0a6c022863a338c33faf950fd75728 Mon Sep 17 00:00:00 2001 From: Khaled Sakr Date: Wed, 12 Feb 2025 15:29:24 +0100 Subject: [PATCH 1/2] feat(heremap): allow choosing map engine via prop --- src/HEREMap.tsx | 37 ++++++++- src/Polyline.tsx | 12 ++- src/useLegacyRasterLayers.ts | 141 +++++++++++++++++++++++++++++++++++ src/useRasterLayers.ts | 35 +++++---- src/useVectorLayers.ts | 33 ++++---- 5 files changed, 222 insertions(+), 36 deletions(-) create mode 100644 src/useLegacyRasterLayers.ts diff --git a/src/HEREMap.tsx b/src/HEREMap.tsx index e77a4ae..d46c188 100644 --- a/src/HEREMap.tsx +++ b/src/HEREMap.tsx @@ -5,6 +5,7 @@ import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } f import { HEREMapContext } from './context' import type { DefaultLayers } from './types' +import { useLegacyRasterLayers } from './useLegacyRasterLayers' import { useRasterLayers } from './useRasterLayers' import { useVectorLayers } from './useVectorLayers' import { getPlatform } from './utils/get-platform' @@ -19,6 +20,14 @@ export interface HEREMapProps extends H.Map.Options { interactive?: boolean, routes?: object[], truckRestrictions?: boolean, + /** + * Specify the engine type. Choose between the newer HARP engine, or the legacy P2D engine. + * The WEBGL engine is not supported by this library. + * + * Note that the P2D engine is no longer supported by HERE and may be shut down at any moment. + * It's only provided for legacy reasons for a transitional period. + */ + engineType?: H.Map.EngineType, showActiveAndInactiveTruckRestrictions?: boolean, trafficLayer?: boolean, useSatellite?: boolean, @@ -83,7 +92,16 @@ export const HEREMap = forwardRef(({ animateZoom, animateCenter, useVectorTiles, + engineType = H.Map.EngineType.HARP, }, ref) => { + if (engineType === H.Map.EngineType.WEBGL) { + throw new Error('WEBGL Engine is not supported.') + } + + if (engineType !== H.Map.EngineType.HARP && useVectorTiles) { + throw new Error('Vector tiles can only be used with the HARP engine.') + } + const uniqueIdRef = useRef(uniqueId()) const [map, setMap] = useState(null) @@ -100,7 +118,7 @@ export const HEREMap = forwardRef(({ trafficLayer, truckRestrictions, useSatellite, - useVectorTiles, + enable: useVectorTiles, }) useRasterLayers({ @@ -113,7 +131,20 @@ export const HEREMap = forwardRef(({ truckRestrictions, showActiveAndInactiveTruckRestrictions, useSatellite, - useVectorTiles, + enable: !useVectorTiles && engineType === H.Map.EngineType.HARP, + hidpi, + }) + + useLegacyRasterLayers({ + apiKey, + congestion, + defaultLayers: defaultLayersRef.current, + language, + map, + trafficLayer, + truckRestrictions, + useSatellite, + enable: !useVectorTiles && engineType === H.Map.EngineType.P2D, hidpi, }) @@ -199,8 +230,6 @@ export const HEREMap = forwardRef(({ apikey: apiKey, }) - const engineType = H.Map.EngineType.HARP - defaultLayersRef.current = platform.createDefaultLayers({ lg: getTileLanguage(language), engineType, diff --git a/src/Polyline.tsx b/src/Polyline.tsx index 0510659..a28b133 100644 --- a/src/Polyline.tsx +++ b/src/Polyline.tsx @@ -14,11 +14,17 @@ export interface PolylineProps extends EventHandlers { data?: object, zIndex?: number, style?: H.map.SpatialStyle.Options, + /** + * Sets the arrows style when the P2D engine is in use. + * @deprecated This is no longer supported in the newer map engines. + */ + arrows?: H.map.ArrowStyle.Options, draggable?: boolean, } export const Polyline: FC = ({ style = defaultMapStyles, + arrows, data, zIndex, points, @@ -75,12 +81,16 @@ export const Polyline: FC = ({ polyline?.setStyle(style) }, [style]) + useEffect(() => { + polyline?.setArrows(arrows) + }, [arrows]) + useEffect(() => { if (!routesGroup) { return } - const routeLine = new H.map.Polyline(line, { style, zIndex, data }) + const routeLine = new H.map.Polyline(line, { style, zIndex, data, arrows }) routesGroup.addObject(routeLine) setPolyline(routeLine) return () => { diff --git a/src/useLegacyRasterLayers.ts b/src/useLegacyRasterLayers.ts new file mode 100644 index 0000000..273793a --- /dev/null +++ b/src/useLegacyRasterLayers.ts @@ -0,0 +1,141 @@ +import { useEffect, useMemo } from 'react' + +import type { DefaultLayers } from './types' +import { getTileLanguage } from './utils/languages' + +export interface UseRasterLayersProps { + map?: H.Map, + truckRestrictions?: boolean, + trafficLayer?: boolean, + useSatellite?: boolean, + congestion?: boolean, + defaultLayers?: DefaultLayers, + apiKey: string, + hidpi?: boolean, + enable: boolean, + language: string, + engineType?: H.Map.EngineType, +} + +export const getLayers = ( + apiKey: string, + language: string, + hidpi?: boolean, +) => { + const lang = getTileLanguage(language) + const ppi = hidpi ? 400 : 100 + const format = 'png8' + + const getTrafficOverlayProvider = (): H.map.provider.ImageTileProvider.Options => { + return { + getURL (col, row, level) { + return `https://traffic.maps.hereapi.com/v3/flow/mc/${level}/${col}/${row}/${format}?apiKey=${apiKey}&ppi=${ppi}` + }, + } + } + const getTrafficBaseProvider = (): H.map.provider.ImageTileProvider.Options => { + return { + getURL (col, row, level) { + const style = 'lite.day' + return `https://maps.hereapi.com/v3/base/mc/${level}/${col}/${row}/${format}?apiKey=${apiKey}&lang=${lang}&ppi=${ppi}&style=${style}` + }, + } + } + + const getTruckLayerProviderLegacy = (enableCongestion: boolean): H.map.provider.ImageTileProvider.Options => { + return { + max: 20, + min: 8, + getURL (col, row, level) { + return ['https://', + '1.base.maps.ls.hereapi.com/maptile/2.1/truckonlytile/newest/normal.day/', + level, + '/', + col, + '/', + row, + '/256/png8', + '?style=fleet', + '&apiKey=', + apiKey, + enableCongestion ? '&congestion' : '', + '&lg=', + lang, + '&ppi=', + hidpi ? '320' : '72', + ].join('') + }, + } + } + const truckOverlayProvider = new H.map.provider.ImageTileProvider(getTruckLayerProviderLegacy(false)) + const truckOverlayCongestionProvider = new H.map.provider.ImageTileProvider(getTruckLayerProviderLegacy(true)) + const trafficOverlayProvider = new H.map.provider.ImageTileProvider(getTrafficOverlayProvider()) + const trafficBaseProvider = new H.map.provider.ImageTileProvider(getTrafficBaseProvider()) + + return { + trafficBaseLayer: new H.map.layer.TileLayer(trafficBaseProvider), + trafficOverlayLayer: new H.map.layer.TileLayer(trafficOverlayProvider), + truckCongestionLayer: new H.map.layer.TileLayer(truckOverlayCongestionProvider), + truckOverlayLayer: new H.map.layer.TileLayer(truckOverlayProvider), + } +} + +export const useLegacyRasterLayers = ({ + map, + useSatellite, + trafficLayer, + congestion, + truckRestrictions, + defaultLayers, + apiKey, + language, + hidpi, + enable, +}: UseRasterLayersProps) => { + const layers = useMemo(() => map && getLayers( + apiKey, + language, + hidpi, + ), [apiKey, language, hidpi, map]) + + useEffect(() => { + if (map && layers && enable && defaultLayers) { + const satelliteBaseLayer = defaultLayers?.raster.satellite.map + const emptyBaseLayer = defaultLayers?.raster.normal.map + const baseLayer = useSatellite + ? satelliteBaseLayer + : trafficLayer + ? layers.trafficBaseLayer + : emptyBaseLayer + + map.setBaseLayer(baseLayer) + } + }, [map, useSatellite, defaultLayers, trafficLayer, enable, layers]) + + useEffect(() => { + if (map && layers && enable) { + if (truckRestrictions) { + if (congestion) { + map.removeLayer(layers.truckOverlayLayer) + map.addLayer(layers.truckCongestionLayer) + } else { + map.removeLayer(layers.truckCongestionLayer) + map.addLayer(layers.truckOverlayLayer) + } + } else { + map.removeLayer(layers.truckCongestionLayer) + map.removeLayer(layers.truckOverlayLayer) + } + } + }, [truckRestrictions, congestion, map, enable, layers]) + + useEffect(() => { + if (map && layers && enable) { + if (trafficLayer) { + map.addLayer(layers.trafficOverlayLayer) + } else { + map.removeLayer(layers.trafficOverlayLayer) + } + } + }, [trafficLayer, map, enable, layers]) +} diff --git a/src/useRasterLayers.ts b/src/useRasterLayers.ts index ccb9a4b..696192c 100644 --- a/src/useRasterLayers.ts +++ b/src/useRasterLayers.ts @@ -13,7 +13,7 @@ export interface UseRasterLayersProps { congestion?: boolean, defaultLayers?: DefaultLayers, apiKey: string, - useVectorTiles: boolean, + enable: boolean, language: string, hidpi?: boolean, } @@ -87,52 +87,59 @@ export const useRasterLayers = ({ defaultLayers, apiKey, language, - useVectorTiles, + enable, showActiveAndInactiveTruckRestrictions, + hidpi, }: UseRasterLayersProps) => { const truckOverlayLayer = useMemo(() => map && getTruckOverlayLayer({ apiKey, language, showActiveAndInactiveTruckRestrictions, - }), [apiKey, showActiveAndInactiveTruckRestrictions, language, map]) + hidpi, + }), [apiKey, showActiveAndInactiveTruckRestrictions, language, hidpi, map]) const baseLayer = useMemo(() => map && getBaseLayer({ apiKey, language, congestion, trafficLayer, - }), [apiKey, language, congestion, trafficLayer, map]) + hidpi, + }), [apiKey, language, congestion, trafficLayer, hidpi, map]) useEffect(() => { - if (!map || !defaultLayers || !baseLayer || useVectorTiles) { + if (!map || !defaultLayers || !baseLayer || !enable) { return } const satelliteBaseLayer = defaultLayers?.raster.satellite.map map.setBaseLayer(useSatellite ? satelliteBaseLayer : baseLayer) - }, [map, useSatellite, defaultLayers, baseLayer, useVectorTiles]) + }, [map, useSatellite, defaultLayers, baseLayer, enable]) useEffect(() => { - if (!map || !truckOverlayLayer) { + if (!map || !enable || !truckOverlayLayer) { return } - if (truckRestrictions && !useVectorTiles) { + if (truckRestrictions) { map.addLayer(truckOverlayLayer) - } else { + } + + return () => { map.removeLayer(truckOverlayLayer) } - }, [truckRestrictions, map, useVectorTiles, truckOverlayLayer]) + }, [truckRestrictions, map, enable, truckOverlayLayer]) useEffect(() => { - if (!map || !defaultLayers) { + if (!map || !defaultLayers || !enable) { return } - if (trafficLayer && !useVectorTiles) { + if (trafficLayer) { map.addLayer(defaultLayers.vector.traffic.logistics) - } else { + } + + return () => { map.removeLayer(defaultLayers.vector.traffic.logistics) } - }, [trafficLayer, map, defaultLayers, useVectorTiles]) + }, [trafficLayer, map, defaultLayers, enable]) } diff --git a/src/useVectorLayers.ts b/src/useVectorLayers.ts index bbefde8..8828cc4 100644 --- a/src/useVectorLayers.ts +++ b/src/useVectorLayers.ts @@ -9,7 +9,7 @@ export interface UseVectorLayersProps { useSatellite?: boolean, congestion?: boolean, defaultLayers?: DefaultLayers, - useVectorTiles: boolean, + enable: boolean, } const defaultLogisticsLayerFeatures = [ @@ -44,10 +44,10 @@ export const useVectorLayers = ({ congestion, truckRestrictions, defaultLayers, - useVectorTiles, + enable, }: UseVectorLayersProps) => { useEffect(() => { - if (!map || !defaultLayers || !useVectorTiles) { + if (!map || !defaultLayers || !enable) { return } @@ -70,36 +70,35 @@ export const useVectorLayers = ({ } style.addEventListener('change', changeListener) }) - }, [defaultLayers, map, useVectorTiles, useSatellite, truckRestrictions, congestion]) + }, [defaultLayers, map, enable, useSatellite, truckRestrictions, congestion]) useEffect(() => { - if (!map || !defaultLayers) { - return - } - - if (!useVectorTiles) { - map.removeLayer(defaultLayers.hybrid.logistics.vector) + if (!map || !defaultLayers || !enable) { return } if (useSatellite) { map.setBaseLayer(defaultLayers.hybrid.logistics.raster) map.addLayer(defaultLayers.hybrid.logistics.vector) - } else { - map.setBaseLayer(defaultLayers.vector.normal.logistics) + } + + return () => { map.removeLayer(defaultLayers.hybrid.logistics.vector) + map.setBaseLayer(defaultLayers.vector.normal.logistics) } - }, [defaultLayers, map, useVectorTiles, useSatellite]) + }, [defaultLayers, map, enable, useSatellite]) useEffect(() => { - if (!map || !defaultLayers) { + if (!map || !defaultLayers || !enable) { return } - if (trafficLayer && useVectorTiles) { + if (trafficLayer) { map.addLayer(defaultLayers.vector.traffic.logistics) - } else { + } + + return () => { map.removeLayer(defaultLayers.vector.traffic.logistics) } - }, [trafficLayer, map, defaultLayers, useVectorTiles]) + }, [trafficLayer, map, defaultLayers, enable]) } From 1c524b855e06829024370a06c4b277731856679e Mon Sep 17 00:00:00 2001 From: Khaled Sakr Date: Thu, 13 Feb 2025 15:55:17 +0100 Subject: [PATCH 2/2] refactor: naming improvement --- src/HEREMap.tsx | 6 +++--- src/useLegacyRasterLayers.ts | 16 ++++++++-------- src/useRasterLayers.ts | 16 ++++++++-------- src/useVectorLayers.ts | 16 ++++++++-------- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/HEREMap.tsx b/src/HEREMap.tsx index d46c188..a66d1ef 100644 --- a/src/HEREMap.tsx +++ b/src/HEREMap.tsx @@ -118,7 +118,7 @@ export const HEREMap = forwardRef(({ trafficLayer, truckRestrictions, useSatellite, - enable: useVectorTiles, + enableVectorLayers: useVectorTiles, }) useRasterLayers({ @@ -131,7 +131,7 @@ export const HEREMap = forwardRef(({ truckRestrictions, showActiveAndInactiveTruckRestrictions, useSatellite, - enable: !useVectorTiles && engineType === H.Map.EngineType.HARP, + enableRasterLayers: !useVectorTiles && engineType === H.Map.EngineType.HARP, hidpi, }) @@ -144,7 +144,7 @@ export const HEREMap = forwardRef(({ trafficLayer, truckRestrictions, useSatellite, - enable: !useVectorTiles && engineType === H.Map.EngineType.P2D, + enableRasterLayers: !useVectorTiles && engineType === H.Map.EngineType.P2D, hidpi, }) diff --git a/src/useLegacyRasterLayers.ts b/src/useLegacyRasterLayers.ts index 273793a..17c0733 100644 --- a/src/useLegacyRasterLayers.ts +++ b/src/useLegacyRasterLayers.ts @@ -12,7 +12,7 @@ export interface UseRasterLayersProps { defaultLayers?: DefaultLayers, apiKey: string, hidpi?: boolean, - enable: boolean, + enableRasterLayers: boolean, language: string, engineType?: H.Map.EngineType, } @@ -90,7 +90,7 @@ export const useLegacyRasterLayers = ({ apiKey, language, hidpi, - enable, + enableRasterLayers, }: UseRasterLayersProps) => { const layers = useMemo(() => map && getLayers( apiKey, @@ -99,7 +99,7 @@ export const useLegacyRasterLayers = ({ ), [apiKey, language, hidpi, map]) useEffect(() => { - if (map && layers && enable && defaultLayers) { + if (map && layers && enableRasterLayers && defaultLayers) { const satelliteBaseLayer = defaultLayers?.raster.satellite.map const emptyBaseLayer = defaultLayers?.raster.normal.map const baseLayer = useSatellite @@ -110,10 +110,10 @@ export const useLegacyRasterLayers = ({ map.setBaseLayer(baseLayer) } - }, [map, useSatellite, defaultLayers, trafficLayer, enable, layers]) + }, [map, useSatellite, defaultLayers, trafficLayer, enableRasterLayers, layers]) useEffect(() => { - if (map && layers && enable) { + if (map && layers && enableRasterLayers) { if (truckRestrictions) { if (congestion) { map.removeLayer(layers.truckOverlayLayer) @@ -127,15 +127,15 @@ export const useLegacyRasterLayers = ({ map.removeLayer(layers.truckOverlayLayer) } } - }, [truckRestrictions, congestion, map, enable, layers]) + }, [truckRestrictions, congestion, map, enableRasterLayers, layers]) useEffect(() => { - if (map && layers && enable) { + if (map && layers && enableRasterLayers) { if (trafficLayer) { map.addLayer(layers.trafficOverlayLayer) } else { map.removeLayer(layers.trafficOverlayLayer) } } - }, [trafficLayer, map, enable, layers]) + }, [trafficLayer, map, enableRasterLayers, layers]) } diff --git a/src/useRasterLayers.ts b/src/useRasterLayers.ts index 696192c..b8b269e 100644 --- a/src/useRasterLayers.ts +++ b/src/useRasterLayers.ts @@ -13,7 +13,7 @@ export interface UseRasterLayersProps { congestion?: boolean, defaultLayers?: DefaultLayers, apiKey: string, - enable: boolean, + enableRasterLayers: boolean, language: string, hidpi?: boolean, } @@ -87,7 +87,7 @@ export const useRasterLayers = ({ defaultLayers, apiKey, language, - enable, + enableRasterLayers, showActiveAndInactiveTruckRestrictions, hidpi, }: UseRasterLayersProps) => { @@ -107,16 +107,16 @@ export const useRasterLayers = ({ }), [apiKey, language, congestion, trafficLayer, hidpi, map]) useEffect(() => { - if (!map || !defaultLayers || !baseLayer || !enable) { + if (!map || !defaultLayers || !baseLayer || !enableRasterLayers) { return } const satelliteBaseLayer = defaultLayers?.raster.satellite.map map.setBaseLayer(useSatellite ? satelliteBaseLayer : baseLayer) - }, [map, useSatellite, defaultLayers, baseLayer, enable]) + }, [map, useSatellite, defaultLayers, baseLayer, enableRasterLayers]) useEffect(() => { - if (!map || !enable || !truckOverlayLayer) { + if (!map || !enableRasterLayers || !truckOverlayLayer) { return } @@ -127,10 +127,10 @@ export const useRasterLayers = ({ return () => { map.removeLayer(truckOverlayLayer) } - }, [truckRestrictions, map, enable, truckOverlayLayer]) + }, [truckRestrictions, map, enableRasterLayers, truckOverlayLayer]) useEffect(() => { - if (!map || !defaultLayers || !enable) { + if (!map || !defaultLayers || !enableRasterLayers) { return } @@ -141,5 +141,5 @@ export const useRasterLayers = ({ return () => { map.removeLayer(defaultLayers.vector.traffic.logistics) } - }, [trafficLayer, map, defaultLayers, enable]) + }, [trafficLayer, map, defaultLayers, enableRasterLayers]) } diff --git a/src/useVectorLayers.ts b/src/useVectorLayers.ts index 8828cc4..2a4f6a1 100644 --- a/src/useVectorLayers.ts +++ b/src/useVectorLayers.ts @@ -9,7 +9,7 @@ export interface UseVectorLayersProps { useSatellite?: boolean, congestion?: boolean, defaultLayers?: DefaultLayers, - enable: boolean, + enableVectorLayers: boolean, } const defaultLogisticsLayerFeatures = [ @@ -44,10 +44,10 @@ export const useVectorLayers = ({ congestion, truckRestrictions, defaultLayers, - enable, + enableVectorLayers, }: UseVectorLayersProps) => { useEffect(() => { - if (!map || !defaultLayers || !enable) { + if (!map || !defaultLayers || !enableVectorLayers) { return } @@ -70,10 +70,10 @@ export const useVectorLayers = ({ } style.addEventListener('change', changeListener) }) - }, [defaultLayers, map, enable, useSatellite, truckRestrictions, congestion]) + }, [defaultLayers, map, enableVectorLayers, useSatellite, truckRestrictions, congestion]) useEffect(() => { - if (!map || !defaultLayers || !enable) { + if (!map || !defaultLayers || !enableVectorLayers) { return } @@ -86,10 +86,10 @@ export const useVectorLayers = ({ map.removeLayer(defaultLayers.hybrid.logistics.vector) map.setBaseLayer(defaultLayers.vector.normal.logistics) } - }, [defaultLayers, map, enable, useSatellite]) + }, [defaultLayers, map, enableVectorLayers, useSatellite]) useEffect(() => { - if (!map || !defaultLayers || !enable) { + if (!map || !defaultLayers || !enableVectorLayers) { return } @@ -100,5 +100,5 @@ export const useVectorLayers = ({ return () => { map.removeLayer(defaultLayers.vector.traffic.logistics) } - }, [trafficLayer, map, defaultLayers, enable]) + }, [trafficLayer, map, defaultLayers, enableVectorLayers]) }