Skip to content

Commit

Permalink
refactor: use precomputed polygons on area maps
Browse files Browse the repository at this point in the history
wip: show crags on hover
  • Loading branch information
viet nguyen committed Jan 18, 2024
1 parent 9572162 commit bbc2a76
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 161 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
"@radix-ui/react-tabs": "^1.0.1",
"@radix-ui/react-toggle": "^1.0.1",
"@turf/bbox": "^6.5.0",
"@turf/bbox-polygon": "^6.5.0",
"@turf/convex": "^6.5.0",
"@turf/line-to-polygon": "^6.5.0",
"@udecode/zustood": "^1.1.3",
"auth0": "^2.42.0",
"awesome-debounce-promise": "^2.1.0",
Expand Down Expand Up @@ -72,6 +71,7 @@
"tailwindcss-radix": "^2.5.0",
"typesense": "^1.2.1",
"underscore": "^1.13.3",
"use-debounce": "^10.0.0",
"uuid": "9.0.0",
"yup": "^1.2.0",
"zod": "^3.21.4",
Expand Down
2 changes: 1 addition & 1 deletion src/app/area/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { StickyHeaderContainer } from '@/app/components/ui/StickyHeaderContainer
import { AreaCrumbs } from '@/components/breadcrumbs/AreaCrumbs'
import { ArticleLastUpdate } from '@/components/edit/ArticleLastUpdate'
import { getMapHref, getFriendlySlug, getAreaPageFriendlyUrl, sanitizeName } from '@/js/utils'
import { LazyAreaMap } from '@/components/area/areaMap'
import { LazyAreaMap } from '@/components/maps/AreaMap'
import { AreaPageContainer } from '@/app/components/ui/AreaPageContainer'
import { AreaPageActions } from '../../components/AreaPageActions'
import { SubAreasSection } from './sections/SubAreasSection'
Expand Down
118 changes: 0 additions & 118 deletions src/components/area/areaMap.tsx

This file was deleted.

98 changes: 98 additions & 0 deletions src/components/maps/AreaMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
'use client'
import { useRef, useState } from 'react'
import { Map, ScaleControl, FullscreenControl, NavigationControl, Source, Layer, FillLayer, MapLayerMouseEvent } from 'react-map-gl'
import dynamic from 'next/dynamic'
import { Padding } from '@math.gl/web-mercator/dist/fit-bounds'
import { lineString } from '@turf/helpers'
import lineToPolygon from '@turf/line-to-polygon'
import { useDebouncedCallback } from 'use-debounce'

import { AreaMetadataType, AreaType } from '../../js/types'
import { MAP_STYLES } from './BaseMap'
import { MouseoverPanel } from './MouseoverPanel'

type ChildArea = Pick<AreaType, 'uuid' | 'areaName'> & { metadata: Pick<AreaMetadataType, 'lat' | 'lng' | 'leaf' | 'bbox' | 'polygon'> }
interface AreaMapProps {
subAreas: ChildArea[]
area: AreaType
focused: string | null
selected: string | null
}

export interface MapAreaFeatureProperties {
id: string
name: string
parent: {
id: string
name: string
}
}

/**
* Area map
*/
const AreaMap: React.FC<AreaMapProps> = ({ area, subAreas }) => {
const [hovered, setHovered] = useState<MapAreaFeatureProperties | null>(null)
const mapRef = useRef(null)
let padding: Padding = { top: 45, left: 45, bottom: 45, right: 45 }
if (subAreas.length === 0) {
padding = { top: 100, left: 100, bottom: 100, right: 100 }
}

const { metadata } = area

const boundary = metadata?.polygon == null ? null : lineToPolygon(lineString(metadata.polygon), { properties: { name: area.areaName } })

const onMouseEnter = (event: MapLayerMouseEvent): void => {
console.log('onMouseEnter', event)
const feature = event?.features?.[0]
if (feature != null) {
setHovered(feature.properties as MapAreaFeatureProperties)
}
}

return (
<div className='relative w-full h-full'>
<Map
ref={mapRef}
id='map'
initialViewState={{
bounds: metadata.bbox,
fitBoundsOptions: { padding }
}}
onMouseMove={useDebouncedCallback(onMouseEnter, 200, { leading: true, maxWait: 200 })}
reuseMaps
mapboxAccessToken={process.env.NEXT_PUBLIC_MAPBOX_API_KEY}
mapStyle={MAP_STYLES.light}
cooperativeGestures
interactiveLayerIds={['crags']}
>
<ScaleControl />
<FullscreenControl />
<NavigationControl showCompass={false} />
{hovered != null && <MouseoverPanel {...hovered} />}
{boundary != null &&
<Source id='child-areas-polygon' type='geojson' data={boundary}>
<Layer {...areaPolygonStyle} />
</Source>}
</Map>
</div>
)
}

export default AreaMap

export const LazyAreaMap = dynamic<AreaMapProps>(async () => await import('./AreaMap').then(
module => module.default), {
ssr: false
})

const areaPolygonStyle: FillLayer = {
id: 'polygon',
type: 'fill',
paint: {
'fill-antialias': true,
'fill-color': 'rgb(236,72,153)',
'fill-opacity': ['step', ['zoom'], 0.2, 15, 0]
}
}
15 changes: 15 additions & 0 deletions src/components/maps/MouseoverPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { MapAreaFeatureProperties } from './AreaMap'
import { getAreaPageFriendlyUrl } from '@/js/utils'

/**
* Show the name of the area on hover
*/
export const MouseoverPanel: React.FC<MapAreaFeatureProperties> = ({ id, name }) => {
return (
<div className='absolute top-3 right-12'>
<div className='px-2 py-1 bg-neutral text-neutral-content shadow-ls rounded text-xs'>
<a href={getAreaPageFriendlyUrl(id, name)} className='hover:underline'>{name}</a>
</div>
</div>
)
}
3 changes: 3 additions & 0 deletions src/js/graphql/gql/areaById.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export const QUERY_AREA_BY_ID = gql`
lat
lng
leftRightIndex
polygon
bbox
}
pathTokens
ancestors
Expand Down Expand Up @@ -101,6 +103,7 @@ export const QUERY_AREA_BY_ID = gql`
lat
lng
bbox
polygon
}
children {
uuid
Expand Down
3 changes: 2 additions & 1 deletion src/js/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BBox, Feature } from '@turf/helpers'
import { BBox, Feature, Position } from '@turf/helpers'
import { ViewState } from 'react-map-gl'
import { BaseItem } from '@algolia/autocomplete-core'
import { RegisterOptions } from 'react-hook-form'
Expand All @@ -19,6 +19,7 @@ export interface AreaMetadataType {
mp_id: string
area_id: string
areaId: string
polygon: Position[] // Pick<LineString, 'coordinates'>
}

export enum SafetyType {
Expand Down
Loading

0 comments on commit bbc2a76

Please sign in to comment.