Skip to content

Commit

Permalink
feat: show superposed POIs #226
Browse files Browse the repository at this point in the history
  • Loading branch information
wazolab committed Aug 7, 2024
1 parent 478d0e3 commit 5c1047f
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 129 deletions.
8 changes: 1 addition & 7 deletions components/MainMap/MapFeatures.vue
Original file line number Diff line number Diff line change
Expand Up @@ -122,28 +122,24 @@ export default defineNuxtComponent({
const { config } = storeToRefs(useSiteStore())
const mapStore = useMapStore()
const { center, selectedFeature } = storeToRefs(mapStore)
const mapStyleLoaded = ref(false)
return {
center,
config,
device,
mapBase: ref<InstanceType<typeof MapBase>>(),
mapStore,
mapStyleLoaded,
selectedFeature,
}
},
data(): {
map: Map
markers: { [id: string]: Marker }
selectedFeatureMarker?: Marker
selectedBackground: MapStyleEnum
} {
return {
map: null!,
markers: {},
selectedBackground: DEFAULT_MAP_STYLE,
}
},
Expand Down Expand Up @@ -264,11 +260,9 @@ export default defineNuxtComponent({
})
this.showSelectedFeature()
this.mapStyleLoaded = true
},
// Map interactions
onClick(e: MapMouseEvent) {
let selectedFeatures = STYLE_LAYERS.map((layerId) => {
return this.map.queryRenderedFeatures(e.point, {
Expand Down Expand Up @@ -320,7 +314,7 @@ export default defineNuxtComponent({
// Map view
onMapRender() {
if (this.mapStyleLoaded && this.selectedFeature) {
if (this.map && this.map.getSource(POI_SOURCE) && this.map.isSourceLoaded(POI_SOURCE) && this.selectedFeature && !this.selectedFeatureMarker) {
const marker = createMarker((this.selectedFeature.geometry as GeoJSON.Point).coordinates as [number, number])
this.setSelectedFeatureMarker(marker)
}
Expand Down
18 changes: 6 additions & 12 deletions components/Map/MapBase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,12 @@ export default defineNuxtComponent({
map: MapGL
poiFilter: PoiFilter | null
poiLayerTemplate: LayerSpecification | undefined
markers: { [id: string]: Marker }
fullAttribution: string
} {
return {
map: null!,
poiFilter: null,
poiLayerTemplate: undefined,
markers: {},
fullAttribution: '',
}
},
Expand Down Expand Up @@ -201,6 +199,7 @@ export default defineNuxtComponent({
.filter(feature => !!feature)
.map((feature, index) => {
feature.id = index
return feature
})
},
Expand Down Expand Up @@ -244,7 +243,7 @@ export default defineNuxtComponent({
cluster: cluster === undefined ? true : cluster,
clusterRadius: 32,
clusterProperties: clusterProps,
clusterMaxZoom: 15,
clusterMaxZoom: 20,
tolerance: 0.6,
data: {
type: 'FeatureCollection',
Expand Down Expand Up @@ -345,7 +344,7 @@ export default defineNuxtComponent({
this.$emit('mapStyleLoad', style)
},
onMapRender(
async onMapRender(
eventName:
| 'mapData'
| 'mapDragEnd'
Expand All @@ -356,14 +355,9 @@ export default defineNuxtComponent({
| 'mapZoomEnd',
event: any,
) {
if (
this.map
&& this.map.getSource(POI_SOURCE)
&& this.map.isSourceLoaded(POI_SOURCE)
) {
this.markers = updateMarkers(
if (this.map && this.map.getSource(POI_SOURCE) && this.map.isSourceLoaded(POI_SOURCE)) {
await updateMarkers(
this.map as MapGL,
this.markers,
POI_SOURCE,
this.fitBounds,
(feature: ApiPoi, marker?: Marker) => this.$emit('featureClick', feature, marker),
Expand Down Expand Up @@ -418,7 +412,7 @@ export default defineNuxtComponent({
</div>
</template>

<style scoped>
<style lang="scss" scoped>
:deep(.cluster-item) {
cursor: pointer;
}
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/embedded.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ describe('pois table', () => {
cy.get('.category-selector input').wait(1000).click()
cy.contains('Aire de passage', { timeout: 30000 }).click({ timeout: 30000 })

cy.get('#m0', { timeout: 30000 }).click()
cy.get('#0', { timeout: 30000 }).click()
cy.url().should('include', `/embedded/22/1`)

cy.get('#selected-category-22 button').click()
Expand Down
2 changes: 1 addition & 1 deletion cypress/e2e/pois/map.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ describe('home content', () => {
})

it('contain map and poi', () => {
cy.get('#m0')
cy.get('#0')

cy.htmlvalidate()
})
Expand Down
4 changes: 2 additions & 2 deletions cypress/e2e/tracking.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,14 @@ describe('home content', () => {
})

// Click on map POI
cy.get('#m0', { timeout: 10000 }).click()
cy.get('#0', { timeout: 10000 }).click()
asserts.push((event: Event) => {
assert(event.type === 'popup' && event.poiId === 1, 'Click on map POI')
})
cy.get('#PoiCard-1').should('be.visible')

// Click on an other map POI
cy.get('#m1').click({ force: true }) // Force click on non visible element
cy.get('#1').click({ force: true }) // Force click on non visible element
asserts.push((event: Event) => {
assert(
event.type === 'popup' && event.poiId === 2,
Expand Down
50 changes: 50 additions & 0 deletions lib/clusters.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
import { createApp } from 'vue'
import type { Marker } from 'maplibre-gl'
import type { ApiPoi } from './apiPois'
import TeritorioIconBadge from '~/components/UI/TeritorioIconBadge.vue'

function getMarkerDonutSegment(start: number, end: number, r: number, r0: number, colorFill: string): string {
if (end - start === 1)
end -= 0.00001
Expand Down Expand Up @@ -39,6 +44,51 @@ function getMarkerDonutSegment(start: number, end: number, r: number, r0: number
].join(' ')
}

export function createDeclusterizedCluster(
features: GeoJSON.Feature[],
clusterCoords: [number, number],
markerClickCallBack: ((feature: ApiPoi, marker?: Marker) => void) | undefined,
): HTMLElement {
const clusterWrapper = document.createElement('div')
features.forEach((feature, index) => {
const el = document.createElement('div')
el.id = `m${feature.id}`

createApp(TeritorioIconBadge, {
colorFill: feature.properties?.display.color_fill,
picto: feature.properties?.display.icon,
image: feature.properties!['image:thumbnail'],
size: null,
text: feature.properties?.display.name,
}).mount(el)

if (feature.properties?.editorial?.popup_fields) {
// POI event listener
el.addEventListener('click', (e: MouseEvent) => {
e.stopPropagation()

const middle = features.length / 2
const offset
= index + 1 <= middle
? ((index + 1 - middle) * 32) - 16
: ((index - middle) * 32) + 16

const marker = createMarker(clusterCoords).setOffset([offset, -10])

if (markerClickCallBack)
markerClickCallBack(feature as ApiPoi, marker)
})
}

clusterWrapper.append(el)
})
clusterWrapper.classList.add('cluster-item', 'supercluster')
clusterWrapper.style.display = 'flex'
clusterWrapper.style.flexWrap = 'wrap'
clusterWrapper.style.maxWidth = '200px'
return clusterWrapper
}

export function createMarkerDonutChart(countPerColor: Record<string, number>, totalCount: number): HTMLElement {
const r
= totalCount >= 1000
Expand Down
Loading

0 comments on commit 5c1047f

Please sign in to comment.