Skip to content

Commit

Permalink
feat: add pin marker custom function
Browse files Browse the repository at this point in the history
  • Loading branch information
wazolab committed Aug 27, 2024
1 parent 92f8937 commit efb3604
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 19 deletions.
10 changes: 9 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<div id="map" style="height: 100vh;"></div>
<script type="module">
import 'maplibre-gl/dist/maplibre-gl.css'
import { Map, NavigationControl } from "maplibre-gl"
import { Map, NavigationControl, Marker } from "maplibre-gl"
import { UnCluster } from './src'
import { buildCss } from './src/utils/helpers'

Expand Down Expand Up @@ -121,6 +121,7 @@
clusterMode: displayCluster,
markerMode: displayMarker,
unClusterMode: 'circle',
pinMarkerMode: displayPinMarker
},
)

Expand All @@ -140,6 +141,13 @@
});
})

const displayPinMarker = (
coords,
offset
) => {
return new Marker({ scale: 1.3, color: '#f44336', anchor: 'bottom' }).setLngLat(coords).setOffset(offset)
}

const displayMarker = (element, feature, size) => {
element.textContent = feature.properties?.mag

Expand Down
49 changes: 38 additions & 11 deletions src/uncluster.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import type { GeoJSONSource, LngLatLike, MapGeoJSONFeature } from 'maplibre-gl'
import type { GeoJSONSource, LngLatLike, MapGeoJSONFeature, MapMouseEvent } from 'maplibre-gl'
import { Marker, Point } from 'maplibre-gl'
import { createMarker, displayUnclusterInCircle, displayUnclusterDefault, displayMarkerDefault, displayClusterDefault } from './utils/helpers';
import {
displayPinMarkerDefault,
displayUnclusterInCircle,
displayUnclusterDefault,
displayMarkerDefault,
displayClusterDefault
} from './utils/helpers';

type UnClusterMode = 'default' | 'circle'
type ClusterMode = 'default' | ((element: HTMLDivElement, props: MapGeoJSONFeature['properties'], size?: number) => void)
type MarkerMode = 'default' | ((element: HTMLDivElement, feature: MapGeoJSONFeature, size?: number) => void)
type PinMarkerMode = 'default' | ((coords: LngLatLike, offset: Point) => Marker)

export class UnCluster extends EventTarget {
map: maplibregl.Map
Expand All @@ -17,6 +24,7 @@ export class UnCluster extends EventTarget {
markersOnScreen: { [key: string]: Marker }
markerSize: number
pinMarker: Marker | null
pinMarkerMode: PinMarkerMode
selectedClusterId: string | null
selectedFeatureId: string | null
sourceId: string
Expand All @@ -32,7 +40,8 @@ export class UnCluster extends EventTarget {
clusterSize?: number
markerMode?: MarkerMode,
markerSize?: number,
unClusterMode?: UnClusterMode
unClusterMode?: UnClusterMode,
pinMarkerMode?: PinMarkerMode
}
) {
super()
Expand All @@ -47,11 +56,22 @@ export class UnCluster extends EventTarget {
this.markersOnScreen = {}
this.markerSize = options.markerSize || 24
this.pinMarker = null
this.pinMarkerMode = options.pinMarkerMode || 'default'
this.selectedClusterId = null
this.selectedFeatureId = null
this.sourceId = source
this.ticking = false
this.unClusterMode = options.unClusterMode || 'default'

this.map.on('click', this.onClick)
}

onClick = (e: MapMouseEvent) => {
console.log('click', e)
this.selectedClusterId = null
this.selectedFeatureId = null
this.pinMarker?.remove()
this.pinMarker = null
}

render = () => {
Expand All @@ -61,6 +81,13 @@ export class UnCluster extends EventTarget {
this.ticking = true
}

renderPinMarker = (coords: LngLatLike, offset: Point = new Point(0, 0)) => {
if (this.pinMarkerMode === 'default')
return displayPinMarkerDefault(coords, offset)
else
return this.pinMarkerMode(coords, offset)
}

renderMarker = (feature: MapGeoJSONFeature) => {
const element = document.createElement('div')
element.id = this.getFeatureId(feature)
Expand Down Expand Up @@ -165,7 +192,7 @@ export class UnCluster extends EventTarget {
// Create default HTML Cluster
element = this.renderCluster(props)
}
marker = this.markers[id] = createMarker(coords, undefined, { element })
marker = this.markers[id] = new Marker({ element }).setLngLat(coords)
}

newMarkers[id] = marker
Expand All @@ -192,7 +219,7 @@ export class UnCluster extends EventTarget {
const { x, y, height, width } = selectedFeatureHTML.getBoundingClientRect()
const offset = new Point(x - clusterX + (width / 2), y - clusterY + (height / 2))

this.pinMarker = createMarker(marker.getLngLat(), offset).addTo(this.map)
this.pinMarker = this.renderPinMarker(marker.getLngLat(), offset).addTo(this.map)
}
}
}
Expand All @@ -203,7 +230,7 @@ export class UnCluster extends EventTarget {
if (!marker) {
var element = this.renderMarker(feature)

marker = this.markers[id] = createMarker(coords, undefined, { element })
marker = this.markers[id] = new Marker({ element }).setLngLat(coords)
marker.getElement().addEventListener('click', (e: Event) => this.featureClickHandler(e, feature))
}

Expand Down Expand Up @@ -264,7 +291,7 @@ export class UnCluster extends EventTarget {
}

if (coords)
this.pinMarker = createMarker(coords, offset).addTo(this.map)
this.pinMarker = this.renderPinMarker(coords, offset).addTo(this.map)
}
}

Expand All @@ -280,6 +307,7 @@ export class UnCluster extends EventTarget {
}

featureClickHandler = (e: Event, feature: MapGeoJSONFeature) => {
e.stopPropagation()
const id = this.getFeatureId(feature)
const clickedEl = e.currentTarget as HTMLDivElement
const markerOnScreen = this.markersOnScreen[id]
Expand All @@ -302,17 +330,16 @@ export class UnCluster extends EventTarget {
const { x, y, height, width } = clickedEl.getBoundingClientRect()
const offset = new Point(x - clusterX + (width / 2), y - clusterY + (height / 2))

this.pinMarker = createMarker(this.markersOnScreen[clusterId].getLngLat(), offset).addTo(this.map)
this.pinMarker = this.renderPinMarker(this.markersOnScreen[clusterId].getLngLat(), offset).addTo(this.map)
} else {
this.pinMarker = createMarker(markerOnScreen.getLngLat()).addTo(this.map)
this.pinMarker = this.renderPinMarker(markerOnScreen.getLngLat()).addTo(this.map)
}

this.selectedFeatureId = clickedEl.id

const event = new CustomEvent("teritorioClick", {
detail: {
selectedFeatureId: this.selectedFeatureId,
pinMarker: this.pinMarker
selectedFeature: feature,
}
})

Expand Down
10 changes: 3 additions & 7 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LngLatLike, MarkerOptions, MapGeoJSONFeature } from 'maplibre-gl'
import type { LngLatLike, MapGeoJSONFeature } from 'maplibre-gl'
import { Marker, Point } from 'maplibre-gl'

// Helper to apply styles on DOM element
Expand Down Expand Up @@ -113,10 +113,6 @@ export const displayMarkerDefault = (element: HTMLDivElement, size: number) => {
});
}

export function createMarker(
coords: LngLatLike,
offset: Point = new Point(0, 0),
options: MarkerOptions = { scale: 1.3, color: '#f44336', anchor: 'bottom' }
) {
return new Marker({ ...options }).setLngLat(coords).setOffset(offset)
export const displayPinMarkerDefault = (coords: LngLatLike, offset: Point = new Point(0, 0)) => {
return new Marker({ anchor: 'bottom' }).setLngLat(coords).setOffset(offset)
}

0 comments on commit efb3604

Please sign in to comment.