Skip to content

Commit

Permalink
Replace custom date filtering with maplibre-gl-dates (#479)
Browse files Browse the repository at this point in the history
* Replaced custom date filtering with maplibre-gl-dates

* maplibre-gl-dates v1.1.0

* maplibre-gl-dates v1.2.0

* maplibre-gl-dates v1.2.1
  • Loading branch information
1ec5 authored Aug 24, 2024
1 parent d1916bd commit 802ccc3
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 121 deletions.
16 changes: 16 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@
"@material/mwc-top-app-bar": "^0.27.0",
"@material/web": "^1.4.0",
"@mdi/js": "^7.4.47",
"@openhistoricalmap/maplibre-gl-dates": "^1.2.1",
"@types/leaflet": "^1.9.12",
"d3": "^7.8.2",
"d3-array": "^3.2.4",
Expand All @@ -126,4 +127,4 @@
"pwa-helpers": "^0.9.1",
"tippy.js": "^6.3.7"
}
}
}
7 changes: 4 additions & 3 deletions src/components/GrampsjsMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import {html, LitElement} from 'lit'
import 'leaflet'
import 'maplibre-gl'
import '@maplibre/maplibre-gl-leaflet'
import '@openhistoricalmap/maplibre-gl-dates'
import './GrampsjsMapOverlay.js'
import './GrampsjsMapMarker.js'
import {fireEvent, filterByDecimalYear} from '../util.js'
import {fireEvent} from '../util.js'
import '../LocateControl.js'

const {L} = window
Expand Down Expand Up @@ -136,7 +137,7 @@ class GrampsjsMap extends LitElement {
if (this._currentLayer === 'OpenHistoricalMap') {
const mapLibreMap = this._gl.getMaplibreMap()
mapLibreMap.on('styledata', () =>
filterByDecimalYear(mapLibreMap, this.year)
mapLibreMap.filterByDate(`${this.year}`)
)
}
fireEvent(this, 'map:layerchange', {layer: this._currentLayer})
Expand All @@ -159,7 +160,7 @@ class GrampsjsMap extends LitElement {
this.year > 0 &&
this._currentLayer === 'OpenHistoricalMap'
) {
filterByDecimalYear(this._gl.getMaplibreMap(), this.year)
this._gl.getMaplibreMap().filterByDate(`${this.year}`)
return
}
if (
Expand Down
117 changes: 0 additions & 117 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,123 +611,6 @@ export function linkUrls(text, textOnly = true) {
)}`
}

// OpenHistoricalMap functions

/**
* Returns a `Date` object representing the given UTC date components.
*
* @param year A one-based year in the proleptic Gregorian calendar.
* @param month A zero-based month.
* @param day A one-based day.
* @returns A date object.
*/
function dateFromUTC(year, month, day) {
const date = new Date(Date.UTC(year, month, day))
// Date.UTC() treats a two-digit year as an offset from 1900.
date.setUTCFullYear(year)
return date
}

/**
* Converts the given ISO 8601-1 date to a decimal year.
*
* @param isoDate A date string in ISO 8601-1 format.
* @returns A floating point number of years since year 0.
*/
function decimalYearFromISODate(isoDate) {
// Require a valid YYYY, YYYY-MM, or YYYY-MM-DD date, but allow the year
// to be a variable number of digits or negative, unlike ISO 8601-1.
if (!isoDate || !/^-?\d{1,4}(?:-\d\d){0,2}$/.test(isoDate)) return undefined

const ymd = isoDate.split('-')
// A negative year results in an extra element at the beginning.
if (ymd[0] === '') {
ymd.shift()
ymd[0] *= -1
}
const year = +ymd[0]
const date = dateFromUTC(year, +ymd[1] - 1, +ymd[2])
if (Number.isNaN(date)) return undefined

// Add the year and the fraction of the date between two New Year’s Days.
const nextNewYear = dateFromUTC(year + 1, 0, 1).getTime()
const lastNewYear = dateFromUTC(year, 0, 1).getTime()
return year + (date.getTime() - lastNewYear) / (nextNewYear - lastNewYear)
}

/**
* Returns a modified version of the given filter that only evaluates to
* true if the feature coincides with the given decimal year.
*
* @param filter The original layer filter.
* @param decimalYear The decimal year to filter by.
* @returns A filter similar to the given filter, but with added conditions
* that require the feature to coincide with the decimal year.
*/
function constrainFilterByDate(filter, decimalYear) {
const newFilter = filter
if (filter && filter[0] === 'all' && filter[1] && filter[1][0] === 'any') {
if (
filter[1][2] &&
filter[1][2][0] === '<' &&
filter[1][2][1] === 'start_decdate'
) {
newFilter[1][2][2] = decimalYear + 1
}
if (
newFilter[2][2] &&
newFilter[2][2][0] === '>=' &&
newFilter[2][2][1] === 'end_decdate'
) {
newFilter[2][2][2] = decimalYear
}
return newFilter
}

const dateFilter = [
'all',
['any', ['!has', 'start_decdate'], ['<', 'start_decdate', decimalYear + 1]],
['any', ['!has', 'end_decdate'], ['>=', 'end_decdate', decimalYear]],
]
if (filter) {
dateFilter.push(filter)
}
return dateFilter
}

/**
* Filters the map’s features by the `date` data attribute.
*
* @param map The MapboxGL map object to filter the style of.
* @param year The numeric ear to filter by
*/
export function filterByDecimalYear(map, decimalYear) {
// eslint-disable-next-line array-callback-return
map.getStyle().layers.map(layer => {
if (!('source-layer' in layer)) return

const filter = constrainFilterByDate(map.getFilter(layer.id), decimalYear)
map.setFilter(layer.id, filter)
})
}

/**
* Filters the map’s features by the `date` data attribute.
*
* @param map The MapboxGL map object to filter the style of.
* @param date The date to filter by in YYYY-MM-DD format.
*/
export function filterByDate(map, dateP) {
let date = dateP
if (date === null || date === '') {
;[date] = new Date().toISOString().split('T')
}
const decimalYear = date && decimalYearFromISODate(date)
if (!decimalYear) return

filterByDecimalYear(map, decimalYear)
}

export function getGregorianYears(date) {
const MOD_TEXTONLY = 6
if (
Expand Down

0 comments on commit 802ccc3

Please sign in to comment.