Skip to content

Commit 30f6230

Browse files
committed
Make markers clickable
1 parent c811472 commit 30f6230

File tree

3 files changed

+38
-41
lines changed

3 files changed

+38
-41
lines changed

src/app/(main)/community/events/map/engine.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ class MapEngine implements MapHandle {
361361
private notifyHoverChange(index: number) {
362362
if (index === this.hoveredMarkerIndex) return
363363
this.hoveredMarkerIndex = index
364+
this.updateCursor()
364365
if (!this.onActiveMarkerChange) return
365366
if (this.destroyed) return
366367
const id =
@@ -370,6 +371,12 @@ class MapEngine implements MapHandle {
370371
this.onActiveMarkerChange(id)
371372
}
372373

374+
private updateCursor() {
375+
if (this.pointer.active) return
376+
this.canvas.style.cursor =
377+
this.hoveredMarkerIndex >= 0 ? "pointer" : "default"
378+
}
379+
373380
private updatePointerTrail(px: number, py: number) {
374381
const now = performance.now() * 0.001
375382
const maxGap = this.cellSize * this.pixelRatio * 1.5
@@ -473,14 +480,16 @@ class MapEngine implements MapHandle {
473480
this.canvas.setPointerCapture(event.pointerId)
474481
this.canvas.style.cursor = "move"
475482
this.notifyHoverChange(-1)
483+
this.pointerTrail.fill(-1)
484+
this.trailCount = 0
476485
}
477486

478487
private handlePointerMove = (event: PointerEvent) => {
479488
this.hoverPointer.x = event.clientX
480489
this.hoverPointer.y = event.clientY
481490
this.hoverPointer.hasValue = true
482491
const devicePos = this.pointerToDevice(event.clientX, event.clientY)
483-
if (devicePos) {
492+
if (devicePos && !this.pointer.active) {
484493
this.updatePointerTrail(devicePos[0], devicePos[1])
485494
}
486495
if (!this.pointer.active) {
@@ -527,7 +536,6 @@ class MapEngine implements MapHandle {
527536
if (!this.pointer.active || event.pointerId !== this.pointer.id) return
528537
this.pointer.active = false
529538
this.canvas.releasePointerCapture(event.pointerId)
530-
this.canvas.style.cursor = "default"
531539
this.pointer.lastMoveTime = 0
532540
if (event.type === "pointerup") {
533541
this.updateHoveredMarkerFromClient(event.clientX, event.clientY)

src/app/(main)/community/events/map/map-tooltip.tsx

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,23 @@
22

33
import { meetups } from "@/components/meetups"
44

5-
export type MeetupMapPointer = {
6-
x: number
7-
y: number
8-
visible: boolean
9-
}
10-
115
const meetupNameById = new Map(meetups.map(({ node }) => [node.id, node.name]))
126

137
type MapTooltipProps = {
148
id: string
159
activeMeetupId: string | null
16-
pointer: MeetupMapPointer
1710
}
1811

19-
export function MapTooltip({ id, activeMeetupId, pointer }: MapTooltipProps) {
20-
if (!activeMeetupId || !pointer.visible) return null
21-
const name = meetupNameById.get(activeMeetupId)
22-
if (!name) return null
12+
export function MapTooltip({ id, activeMeetupId }: MapTooltipProps) {
13+
const name = activeMeetupId && meetupNameById.get(activeMeetupId)
2314
return (
2415
<span
2516
id={id}
2617
role="tooltip"
27-
className="pointer-events-none absolute left-0 top-0 z-10 hidden min-w-0 whitespace-nowrap border border-neu-200/40 bg-neu-0/40 px-2 py-1 text-xs font-medium text-neu-900 shadow-sm backdrop-blur-sm group-hover/map:flex"
18+
className="pointer-events-none absolute left-0 top-0 z-10 hidden min-w-0 whitespace-nowrap border border-neu-200/40 bg-neu-0/40 px-2 py-[3px] text-xs text-neu-900 shadow-sm backdrop-blur-sm group-hover/map:flex"
2819
style={{
29-
transform: `translate3d(calc(${pointer.x}px - 50%), calc(${pointer.y}px - 50% - 24px), 0)`,
20+
transform: `translate3d(calc(var(--x) - 50%), calc(var(--y) - 50% - 22px), 0)`,
21+
visibility: activeMeetupId ? "visible" : "hidden",
3022
}}
3123
>
3224
{name}

src/app/(main)/community/events/meetups-map.tsx

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { useTheme } from "next-themes"
1212
import { meetups } from "@/components/meetups"
1313

1414
import { bootMeetupsMap, type MapHandle, type MarkerPoint } from "./map/engine"
15-
import { MapTooltip, type MeetupMapPointer } from "./map/map-tooltip"
15+
import { MapTooltip } from "./map/map-tooltip"
1616
import { MapSkeleton } from "./map-skeleton"
1717
import { MeetupsList } from "./meetups-list"
1818
import { asRgbString, MAP_COLORS, MapColors } from "./map/map-colors"
@@ -45,34 +45,33 @@ export function MeetupsMap() {
4545

4646
const [status, setStatus] = useState<MapStatus>("loading")
4747
const [errorMessage, setErrorMessage] = useState<string | null>(null)
48-
const [pointer, setPointer] = useState<MeetupMapPointer>({
49-
x: 0,
50-
y: 0,
51-
visible: false,
52-
})
5348

5449
const handlePointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {
50+
const tooltip = document.getElementById("map-tooltip")
51+
if (!tooltip) return
5552
const rect = event.currentTarget.getBoundingClientRect()
5653
const x = event.clientX - rect.left
5754
const y = event.clientY - rect.top
58-
setPointer(previous => {
59-
if (
60-
previous.visible &&
61-
Math.abs(previous.x - x) < 0.5 &&
62-
Math.abs(previous.y - y) < 0.5
63-
) {
64-
return previous
65-
}
66-
return { x, y, visible: true }
67-
})
55+
tooltip.style.setProperty("--x", `${x}px`)
56+
tooltip.style.setProperty("--y", `${y}px`)
6857
}
6958

7059
const handlePointerLeave = () => {
71-
setPointer(previous =>
72-
previous.visible
73-
? { x: previous.x, y: previous.y, visible: false }
74-
: previous,
75-
)
60+
const tooltip = document.getElementById("map-tooltip")
61+
if (!tooltip) return
62+
tooltip.style.removeProperty("--x")
63+
tooltip.style.removeProperty("--y")
64+
}
65+
66+
const activeMeetup = useMemo(
67+
() => meetups.find(m => m.node.id === activeMeetupId),
68+
[activeMeetupId],
69+
)
70+
71+
const handleMapClick = () => {
72+
if (activeMeetup?.node.link) {
73+
window.open(activeMeetup.node.link, "_blank", "noopener,noreferrer")
74+
}
7675
}
7776

7877
useEffect(() => {
@@ -158,6 +157,8 @@ export function MeetupsMap() {
158157
className="group/map relative grow border-neu-200 bg-[--sea] dark:border-neu-50 dark:bg-[--sea] md:border-l"
159158
onPointerMove={handlePointerMove}
160159
onPointerLeave={handlePointerLeave}
160+
onClick={handleMapClick}
161+
style={{ cursor: activeMeetup ? "pointer" : "default" }}
161162
>
162163
<canvas
163164
ref={canvasRef}
@@ -171,11 +172,7 @@ export function MeetupsMap() {
171172
}}
172173
/>
173174

174-
<MapTooltip
175-
id="map-tooltip"
176-
activeMeetupId={activeMeetupId}
177-
pointer={pointer}
178-
/>
175+
<MapTooltip id="map-tooltip" activeMeetupId={activeMeetupId} />
179176

180177
<InfoTip />
181178

0 commit comments

Comments
 (0)