A calendar plugin for leaflet maps. The plugin allows you to browse through remote sensing datasets that vary over time. You add a datepicker to your Leaflet web-map to give end-user control over the date of the data displayed.
There are two main elements needed:
1:- the date picker, to select the date and
2:- extensions to the leaflet layers types so that information is updated when the date is changed.
Click the images for examples:
This plugin uses the Vue Datepicker, but you do not need to be using Vue. It is standalone.
Simple install:
add to your html file
<script src="https://unpkg.com/leaflet-datepicker/dist/leaflet-datepicker.umd.cjs" integrity="..." crossorigin=""></script>
<script src="https://unpkg.com/leaflet-datepicker/dist/style.css" integrity="..." crossorigin=""></script>
(Best practice is to include integrity keys, e.g. from https://www.srihash.org)
if you are using npm, install leaflet-datepicker
import 'leaflet-datepicker'
import '../node_modules/leaflet-calendar/dist/style.css'
if you are using vite, also install @vitejs/plugin-vue (as dev dependency). Add the vue plugin in vite.config.js:
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
... //the rest of your config
Inherits L.Control
This creates a leaflet 'control' with a datepicker inside it. The datepicker can be daily, monthly or annual. This changes the value of map.date, when the calendar is changes, and also emits the date used a "dayChanged", "monthChanged" and or "yearChanged" event.
The frequency of the datepicker is set by the 'freq' option for each layer added to the map. The highest frequency 'freq' option set for layers added to the map is used as the date picker. e.g:
- If no layers have the 'freq' option, then the datepicker does not show (but there is an empty space in allocated for it)
- If one layer has the freq option set as 'yearly', then a calendar with years only is shown
- If one layer has the 'monthly' option, and one has the 'yearly' option, then the monthly calendar is shown
- If one layer has the 'daily' option set, and two layers have 'monthly', and three have 'yearly', the daily calendar is shown.
The date is stored as a date object in map.date. The datepicker can by styled using the 'date-control' css element, and the #datepicker css id.
The datepicker is used with the TimeLocal extensions to Leaflet layers.
map.date=new Date() ;
L.control.datepicker().addTo(map) ;
There are lots of options in the vue-datepicker which are not-supported by the plugin (but it would be easy enough to add them). For example there is no support of date-ranges, time of day, multi-calendars etc
Option | Type | Default | Description |
---|---|---|---|
position |
String
| 'topright' |
'topright'|'topleft'|'bottomleft'|'bottomright'
which corner to show the datepicker on the map. |
frequency |
String
| 'monthly' |
'daily'|'monthly'|'yearly'|'none'
which frequency to start the datepicker on. This is changed later by the freq option for each layer added. |
minDate |
[String|Date object]
| '1980' |
the first date you can pick in the datepicker, default 1980 |
maxDate |
[String|Date object]
| yesterday |
the last date you can pick in the datepicker, |
These are the layers types which are supported and then change when the date on the map is change.
First create map.date and add the datepicker control, then you can add these layers to your javascript.
Layers from local files have urls formed with a url template, using keywords surrounded by {}.
The allowed keywords are :
- {year}: four digit year (e.g. would be replace with 2022 if this is the year selected in the calendar)
- {month}: 1/2 digit month as a number (e.g. would shown 1 for Jan, and 10 for October)
- {day}: 1/2 digit day as a number (e.g. would show 1 for the 1st and 30 for the 30th)
- {dateStr}: returned from this.options.dateStr(obj) function. Where obj contains a date object and a day,month and year strings.
e.g.
dateStr:(obj) => { return obj.date.toISOString()}
would let us use a {dateStr} template var in the url, which in turn would return the data in2023-04-20T04:30:06.608Z
format
Look at the examples for each layer type below.
aka L.GeoJSON.TimeLocal
inherits L.GeoJSON.FromURL
Load a GeoJSONs file from local storage or a url template, with one file per timestep.
//Constructor function:
L.geoJSON.timeLocal(
startDate,
urlTemplate,
options
)
L.geoJSON.timeLocal(
date,
"data/duration/duration_{year}.json",
{
freq: 'yearly',
}
).addTo(map)
which would show data/duration/duration_2022.json
on the map if 2022 was the year selected in the calendar
Option | Type | Default | Description |
---|---|---|---|
freq |
String
| 'daily' |
Frequency of steps between data in this data set. Options are 'daily','monthly','yearly' |
dateStr |
Function(obj)
| None |
use this to create a custom dateStr var in the urlTemplate |
inherits L.ImageOverlay
Load an image from local storage based on the specified date.
//Constructor function:
L.imageOverlay.timeLocal(
startDate,
urlTemplate,
bounds,
options
)
L.imageOverlay.timeLocal(
map.date,
"tracker_data/chlor_conc_anoms/occci_chlor_conc_anoms_{year}_{month}.png",
[[-39.23, -42.24],[-41.45, 135.0]],
{
freq: 'monthly',
alt: 'No data for Chlorophyll Conc for this month'
}
)
Bounds is unchanged from L.ImageOverlay
Option | Type | Default | Description |
---|---|---|---|
freq |
String
| 'daily' |
Frequency of steps between data in this data set. Options are 'daily','monthly','yearly' |
dateStr |
Function(obj)
| None |
function to create a custom dateStr var to use in the url template. |
inherits L.TileLayer
Used to load a single image from web (TMS server) based on the specified time. Url must include {time}
.
Other options are inherited from L.TileLayer
L.tileLayer.time(
"https://gibs.earthdata.nasa.gov/wmts/epsg3031/best/{layer}/default/{time}/{tileMatrixSet}/{z}/{y}/{x}.png",
{
layer: "AMSRU2_Sea_Ice_Concentration_12km",
tileMatrixSet: "1km",
tileSize: 256,
format: "image/png",
transparent: true,
freq:'daily',
attribution: "<a href='https://seaice.uni-bremen.de/sea-ice-concentration/amsre-amsr2/'>AMSR2</a>",
}
)
Option | Type | Default | Description |
---|---|---|---|
freq |
String
| 'daily' |
Frequency of steps between data in this data set. Options are 'daily','monthly','yearly' |
dateStr |
Function(date)
| returns YY-MM-DD |
you might need to tweak it to suit the format required by the server |
Inherits L.TileLayer
Used to load a WMS from web based on the specified time. Url must include {dateStr}
L.tileLayer.wms.time(
"https://my.cmems-du.eu/thredds/wms/METOFFICE-GLO-SST-L4-REP-OBS-SST",
{
layers: "analysed_sst",
styles: "boxfill/occam" ,
format: "image/png",
transparent: "true",
freq: "monthly",
attribution: "OSTIA",
tileSize: 256,
dateStr: (date) => {
return `${date.getFullYear()}-${String(date.getMonth()+1).padStart(2,0)}-15T12:00:00.000Z` ; //custom date format
},
bounds: [[15, -180],[-80, 180]],
}
),
Option | Type | Default | Description |
---|---|---|---|
freq |
String
| 'daily' |
Frequency of steps between data in this data set. Options are 'daily','monthly','yearly' |
dateStr |
Function(date)
| returns YYYY-MM-DDTHH:mm:ss.sssZ |
default date format is Zulu time, as this is more common for WMS servers |