diff --git a/app/listings/map.tsx b/app/listings/map.tsx index 2a86805f..a7e0896a 100644 --- a/app/listings/map.tsx +++ b/app/listings/map.tsx @@ -2,7 +2,7 @@ import { NumberUtils } from "@/lib/commons/number_utils" import { CURRENCY_FORMATTER } from "@/lib/formatter/currency" -import { Feature, View } from "ol" +import { Feature, Overlay, View } from "ol" import Point from "ol/geom/Point" import TileLayer from "ol/layer/Tile" import VectorLayer from "ol/layer/Vector" @@ -127,6 +127,13 @@ export function ListingsMap(props: ListingsMapInterface) { features: mapFeatures.iconFeatures, }), }); + const overlay = new Overlay({ + autoPan: { + animation: { + duration: 250, + }, + }, + }); const map = new Map({ target: 'map', @@ -136,12 +143,14 @@ export function ListingsMap(props: ListingsMapInterface) { }), vectorLayerIconFeatures ], + overlays: [overlay], view: new View({ center: [0, 0], zoom: 2, }), }) + // Change features display style based on the map's zoom level let featureDisplayState: 'icon' | 'text' = 'icon'; const MAP_ZOOM_TEXT = 15; map.on('moveend', (e) => { @@ -157,13 +166,14 @@ export function ListingsMap(props: ListingsMapInterface) { } }) + // Change feature display style to active when hovered upon let activeIndex: number = -1; let previousStyle: StyleLike | undefined; map.on('pointermove', (e) => { // Hover (revert style) if (activeIndex >= 0) { - // Use icons features if zoom level is big - // Use text features if zoom level is small + // Uses icon features if zoom level is big + // Uses text features if zoom level is small let activeFeature = mapFeatures.iconFeatures.at(activeIndex); if (featureDisplayState === 'text') { activeFeature = mapFeatures.textFeatures.at(activeIndex); @@ -184,10 +194,6 @@ export function ListingsMap(props: ListingsMapInterface) { const hoveredFeature = hoveredFeatures.at(hoveredFeatures.length - 1) as Feature; const hoveredIndex = NumberUtils.toNumber(hoveredFeature.getId(), -1) - // TODO: Display popup/banner of listing card - // 1. https://openlayers.org/en/latest/examples/overlay.html (HTML only) - // 2. https://openlayers.org/en/latest/examples/popup.html (Bootstrap) - // 3. https://openlayers.org/en/latest/examples/select-features.html if (hoveredIndex !== activeIndex) { activeIndex = hoveredIndex const activeFeature = mapFeatures.activeFeatures.at(activeIndex); @@ -200,10 +206,42 @@ export function ListingsMap(props: ListingsMapInterface) { }) }) + // TODO: Display popup/banner of listing card + // 2. https://openlayers.org/en/latest/examples/popup.html (HTML only) + // 3. https://openlayers.org/en/latest/examples/select-features.html + map.on('click', (e) => { + if (activeIndex >= 0) { + // Change content + const content = document.getElementById('popup-content')!; + content.innerHTML = '

You clicked here:

' + props.listings.at(activeIndex)?.id + ''; + + // Set overlay's element and position + const container = document.getElementById('popup')!; + overlay.setElement(container); + overlay.setPosition(e.coordinate); + + const closer = document.getElementById('popup-closer')!; + closer.onclick = function () { + overlay.setPosition(undefined); + return false; + }; + } + }) + return () => map.dispose() }, []) return ( -
+
+
+ ) } \ No newline at end of file