├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── bower.json
├── dist
├── leaflet.timedimension.control.css
├── leaflet.timedimension.control.min.css
├── leaflet.timedimension.min.js
├── leaflet.timedimension.src.js
└── leaflet.timedimension.src.withlog.js
├── examples
├── css
│ └── style.css
├── data
│ ├── easy_currents_track.kml
│ ├── running_mallorca.gpx
│ ├── spill.json
│ └── track_bus699.geojson
├── example1.html
├── example10.html
├── example11.html
├── example12.html
├── example13.html
├── example14.html
├── example15.html
├── example16.html
├── example17.html
├── example18.html
├── example2.html
├── example3.html
├── example4.html
├── example5.html
├── example6.html
├── example7.html
├── example8.html
├── example9.html
├── img
│ ├── .directory
│ ├── GitHub-Mark-32px.png
│ ├── black-arrow.png
│ ├── bus.png
│ ├── grey-arrow.png
│ ├── logo-leaflettimedimension-32.png
│ ├── logo-leaflettimedimension.png
│ ├── logo-socib.png
│ ├── running.png
│ ├── screenshot
│ │ ├── .directory
│ │ ├── 1-aviso.png
│ │ ├── 10-imageoverlay-customcontrol.png
│ │ ├── 11-noaa-cdr-sst.png
│ │ ├── 12-nyc-opendata.png
│ │ ├── 13-wms-timeseries.png
│ │ ├── 14-noaa-nowcast.png
│ │ ├── 15-oil-spill.png
│ │ ├── 16-portus-tilelayers.png
│ │ ├── 17-basic-geojson.png
│ │ ├── 18-velocity-integration.png
│ │ ├── 2-temperature-forecast.png
│ │ ├── 3-hfradar.png
│ │ ├── 4-rain-radar.png
│ │ ├── 5-climate-projections.png
│ │ ├── 6-sapoib.png
│ │ ├── 7-ocean-forecast.png
│ │ ├── 8-hfradar-with-drifters.png
│ │ ├── 9-gxp-kml-tracks.png
│ │ └── screenshot-leaflet-timedimension.png
│ └── surface-drifter.png
├── index.html
├── js
│ ├── baselayers.js
│ ├── example1.js
│ ├── example10-data.json
│ ├── example10.js
│ ├── example11.js
│ ├── example12.js
│ ├── example13.js
│ ├── example14.js
│ ├── example15.js
│ ├── example16.js
│ ├── example17.js
│ ├── example18.js
│ ├── example2.js
│ ├── example3.js
│ ├── example4.js
│ ├── example5.js
│ ├── example6.js
│ ├── example7.js
│ ├── example8.js
│ ├── example9.js
│ └── extras
│ │ ├── leaflet.timedimension.circlelabelmarker.js
│ │ ├── leaflet.timedimension.layer.wms.timeseries.js
│ │ ├── leaflet.timedimension.tilelayer.portus.js
│ │ └── leaflet.timedimension.velocitylayer.js
└── server
│ ├── proxy-datadiscovery.php
│ └── proxy.php
├── package.json
└── src
├── leaflet.timedimension.control.css
├── leaflet.timedimension.control.js
├── leaflet.timedimension.js
├── leaflet.timedimension.layer.geojson.js
├── leaflet.timedimension.layer.js
├── leaflet.timedimension.layer.wms.js
├── leaflet.timedimension.player.js
└── leaflet.timedimension.util.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | bower_components/
3 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(grunt) {
4 |
5 | grunt.loadNpmTasks('grunt-contrib-uglify');
6 | grunt.loadNpmTasks('grunt-contrib-concat');
7 | grunt.loadNpmTasks('grunt-contrib-clean');
8 | grunt.loadNpmTasks('grunt-contrib-cssmin');
9 | grunt.loadNpmTasks('grunt-contrib-jshint');
10 | grunt.loadNpmTasks('grunt-contrib-watch');
11 | grunt.loadNpmTasks("grunt-remove-logging");
12 |
13 | grunt.initConfig({
14 | pkg: grunt.file.readJSON('package.json'),
15 | umd: {
16 | prefix: '(function (factory, window) {\n' +
17 | ' if (typeof define === \'function\' && define.amd) {\n' +
18 | ' // define an AMD module that relies on leaflet\n' +
19 | ' define([\'leaflet\', \'iso8601-js-period\'], factory);\n' +
20 | ' } else if (typeof exports === \'object\') {\n' +
21 | ' // define a Common JS module that relies on leaflet\n' +
22 | ' module.exports = factory(require(\'leaflet\'), require(\'iso8601-js-period\'));\n' +
23 | ' } else if (typeof window !== \'undefined\' && window.L && typeof L !== \'undefined\') {\n' +
24 | ' // get the iso8601 from the expected to be global nezasa scope\n' +
25 | ' var iso8601 = nezasa.iso8601;\n' +
26 | ' // attach your plugin to the global L variable\n' +
27 | ' window.L.TimeDimension = factory(L, iso8601);\n' +
28 | ' }\n' +
29 | ' }(function (L, iso8601) {\n'+
30 | ' // make sure iso8601 module js period module is available under the nezasa scope\n'+
31 | ' if (typeof nezasa === \'undefined\') {\n'+
32 | ' var nezasa = { iso8601: iso8601 };\n'+
33 | ' }\n'+
34 | ' // TimeDimension plugin implementation\n',
35 | postfix: ' \n'+
36 | ' return L.TimeDimension;\n'+
37 | ' }, window)\n'+
38 | ');'
39 | },
40 | meta: {
41 | banner: '/* \n' +
42 | ' * Leaflet TimeDimension v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %> \n' +
43 | ' * \n' +
44 | ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author.name %> \n' +
45 | ' * <%= pkg.author.email %> \n' +
46 | ' * <%= pkg.author.url %> \n' +
47 | ' * \n' +
48 | ' * Licensed under the <%= pkg.license %> license. \n' +
49 | ' * \n' +
50 | ' * Demos: \n' +
51 | ' * <%= pkg.homepage %> \n' +
52 | ' * \n' +
53 | ' * Source: \n' +
54 | ' * <%= pkg.repository.url %> \n' +
55 | ' * \n' +
56 | ' */\n'
57 | },
58 | clean: {
59 | dist: {
60 | src: ['dist/*']
61 | }
62 | },
63 | jshint: {
64 | options: {
65 | globals: {
66 | console: true,
67 | module: true
68 | },
69 | "-W099": true, //ignora tabs e space warning
70 | "-W033": true,
71 | "-W041": true,
72 | "-W004": true,
73 | "-W044": true //ignore regexp
74 | },
75 | files: ['src/*.js']
76 | },
77 | concat: {
78 | js: {
79 | options: {
80 | banner: '<%= meta.banner %>\n'+
81 | '<%= umd.prefix %>',
82 | footer: '<%= umd.postfix %>'
83 | },
84 | src: [
85 | 'src/leaflet.timedimension.js',
86 | 'src/leaflet.timedimension.util.js',
87 | 'src/leaflet.timedimension.layer.js',
88 | 'src/leaflet.timedimension.layer.wms.js',
89 | 'src/leaflet.timedimension.layer.geojson.js',
90 | 'src/leaflet.timedimension.player.js',
91 | 'src/leaflet.timedimension.control.js'
92 | ],
93 | dest: 'dist/leaflet.timedimension.src.withlog.js'
94 | },
95 | css: {
96 | options: {
97 | banner: '<%= meta.banner %>'
98 | },
99 | src: 'src/leaflet.timedimension.control.css',
100 | dest: 'dist/leaflet.timedimension.control.css'
101 | },
102 | },
103 | removelogging: {
104 | dist: {
105 | src: "dist/leaflet.timedimension.src.withlog.js",
106 | dest: "dist/leaflet.timedimension.src.js"
107 | }
108 | },
109 | uglify: {
110 | options: {
111 | banner: '<%= meta.banner %>'
112 | },
113 | dist: {
114 | files: {
115 | 'dist/leaflet.timedimension.min.js': ['dist/leaflet.timedimension.src.js']
116 | }
117 | }
118 | },
119 | cssmin: {
120 | combine: {
121 | files: {
122 | 'dist/leaflet.timedimension.control.min.css': ['dist/leaflet.timedimension.control.css']
123 | }
124 | },
125 | options: {
126 | banner: '<%= meta.banner %>'
127 | },
128 | minify: {
129 | expand: true,
130 | cwd: 'dist/',
131 | files: {
132 | 'dist/leaflet.timedimension.control.min.css': ['dist/leaflet.timedimension.control.css']
133 | }
134 | }
135 | },
136 | watch: {
137 | dist: {
138 | options: {
139 | livereload: true
140 | },
141 | files: ['src/*', 'examples/*'],
142 | tasks: ['clean', 'concat', 'removelogging', 'cssmin', 'jshint']
143 | }
144 | }
145 | });
146 |
147 | grunt.registerTask('default', [
148 | 'clean',
149 | 'concat',
150 | 'removelogging',
151 | 'cssmin',
152 | 'jshint',
153 | 'uglify'
154 | ]);
155 |
156 | };
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 ICTS SOCIB - Servei d'observació i predicció costaner de les Illes Balears.
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "leaflet-timedimension",
3 | "description": "Add time dimension capabilities on a Leaflet map",
4 | "main": [
5 | "dist/leaflet.timedimension.src.js",
6 | "dist/leaflet.timedimension.control.css"
7 | ],
8 | "license": "MIT",
9 | "ignore": [
10 | "**/.*",
11 | "node_modules",
12 | "bower_components",
13 | "test",
14 | "tests",
15 | "examples",
16 | "Gruntfile.js",
17 | "package.json"
18 | ],
19 | "keywords": [
20 | "gis",
21 | "map",
22 | "timedimension",
23 | "leaflet"
24 | ],
25 | "authors": [
26 | {
27 | "name": "Biel Frontera (ICTS SOCIB)",
28 | "email": "datacenter@socib.es",
29 | "homepage": "https://www.socib.es/"
30 | },
31 | {
32 | "name": "Sylvain Marcadal (Ram)",
33 | "email":"sylvain@marcadal.me"
34 | }
35 | ],
36 | "homepage": "https://apps.socib.es/Leaflet.TimeDimension/",
37 | "repository": {
38 | "type": "git",
39 | "url": "git://github.com/socib/Leaflet.TimeDimension.git"
40 | },
41 | "dependencies": {
42 | "iso8601-js-period": "*",
43 | "leaflet": "~0.7.4 || ~1.0.0"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/dist/leaflet.timedimension.control.min.css:
--------------------------------------------------------------------------------
1 | @font-face{font-family:'Glyphicons Halflings';src:url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.eot);src:url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.woff) format('woff'),url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular) format('svg')}.leaflet-bar-timecontrol{background-color:#fff;color:#000}.leaflet-bar-timecontrol *{box-sizing:border-box}.leaflet-bar-timecontrol .leaflet-control-timecontrol{float:left;height:26px;line-height:26px;border:solid #a5a5a5;background-color:#fff;border-width:0 1px 0 0}.leaflet-bar-timecontrol .leaflet-control-timecontrol:first-child{border-radius:4px 0 0 4px}.leaflet-bar-timecontrol .leaflet-control-timecontrol:last-child{border-radius:0 4px 4px 0}.leaflet-bar-timecontrol .leaflet-control-timecontrol:before{font-family:"Glyphicons Halflings";display:block}.leaflet-bar-timecontrol .timecontrol-slider{position:relative;width:auto;cursor:auto}.leaflet-bar-timecontrol a.timecontrol-date,.leaflet-bar-timecontrol a.timecontrol-date:hover{position:relative;min-width:150px;width:auto;padding:0 10px 0 20px;white-space:nowrap}.leaflet-bar-timecontrol a.timecontrol-date.utc,.leaflet-bar-timecontrol a.timecontrol-date.utc:hover{min-width:185px}.leaflet-bar-timecontrol a.timecontrol-date.loading,.leaflet-bar-timecontrol a.timecontrol-date.loading:hover{background-color:#ffefa4}.leaflet-bar-timecontrol .timecontrol-dateslider .slider{width:200px}.leaflet-bar-timecontrol .timecontrol-speed{white-space:nowrap;cursor:auto}.leaflet-bar-timecontrol .timecontrol-speed .slider{width:55px;display:inline-block}.leaflet-bar-timecontrol .timecontrol-speed .speed{width:55px;display:inline-block;float:left;text-align:right}.leaflet-bar-timecontrol .timecontrol-play,.leaflet-bar-timecontrol .timecontrol-play:hover{position:relative}.leaflet-bar-timecontrol .timecontrol-play span{font-size:10px}.leaflet-bar-timecontrol a.timecontrol-play.loading{background-color:#ffefa4}.timecontrol-slider .slider{position:relative;height:12px;margin:6px;border:1px solid #a5a5a5;cursor:pointer}.timecontrol-slider .slider.has-limits{margin-left:15px;margin-right:15px;background-color:#ddd}.timecontrol-slider .slider.has-limits .range{position:absolute;height:10px;background-color:#fff}.timecontrol-slider .knob{position:absolute;width:8px;height:22px;background-color:#ddd;border-radius:2px;border:1px solid #a5a5a5;margin-top:-6px;margin-left:-4px;cursor:ew-resize;cursor:-webkit-grab;cursor:-moz-grab}.timecontrol-slider .knob:after{content:' ';display:block;position:absolute;width:20px;top:-5px;height:32px;left:-7px}.timecontrol-slider .knob.lower,.timecontrol-slider .knob.upper{width:11px;height:20px;border:none;background-color:transparent}.timecontrol-slider .knob.upper{margin-top:-5px;margin-left:-1px}.timecontrol-slider .knob.lower{margin-top:-5px;margin-left:-10px}.timecontrol-slider .knob.lower:after{right:0;left:initial}.timecontrol-slider .knob.upper:after{left:0}.timecontrol-slider .knob.lower:before,.timecontrol-slider .knob.upper:before{display:block;content:'';position:relative;top:2px;width:0;height:0;border-style:solid}.timecontrol-slider .knob.upper:before{border-width:16px 0 0 10px;border-color:transparent transparent transparent #a5a5a5}.timecontrol-slider .knob.lower:before{border-width:0 0 16px 10px;border-color:transparent transparent #a5a5a5}.timecontrol-slider .dragging .knob,.timecontrol-slider .knob.leaflet-drag-target,.timecontrol-slider .slider.dragging{cursor:ew-resize;cursor:grabbing;cursor:-webkit-grabbing;cursor:-moz-grabbing}@-webkit-keyframes icon-rotation{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes icon-rotation{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.timecontrol-loop.looped,.timecontrol-loop.looped:hover{background-color:#ddd;color:#094f8e}.timecontrol-backward:before,.timecontrol-forward:before,.timecontrol-loop:before,.timecontrol-play:before,.timecontrol-stop:before{width:100%;text-align:center}.timecontrol-play:before{position:absolute;content:"\e072"}.timecontrol-play.reverse:before{content:"\e072";-ms-transform:scaleX(-1);-webkit-transform:scaleX(-1);transform:scaleX(-1)}.timecontrol-play.pause:before{content:"\e073"}.timecontrol-play.reverse.pause:before{-ms-transform:none;-webkit-transform:none;transform:none}a.timecontrol-play.loading:before{content:"\e031";opacity:.2;-webkit-animation:icon-rotation 6s infinite linear;animation:icon-rotation 6s infinite linear}.timecontrol-date.loading:before{content:"\e031";left:5px;position:absolute;-webkit-animation:icon-rotation 6s infinite linear;animation:icon-rotation 6s infinite linear}.timecontrol-speed:before{content:"\e141";position:absolute;left:7px}.timecontrol-stop:before{content:"\e074"}.timecontrol-forward:before{content:"\e075"}.timecontrol-backward:before{content:"\e071"}.timecontrol-loop:before{content:"\e030"}@media (max-width:767px){.leaflet-bar-timecontrol .timecontrol-date,.leaflet-bar-timecontrol .timecontrol-slider{clear:both;float:none;border-right:none}}.leaflet-touch .leaflet-bar-timecontrol .leaflet-control-timecontrol{height:30px;line-height:30px}.leaflet-touch .timecontrol-slider .slider{margin-top:10px}
--------------------------------------------------------------------------------
/examples/data/track_bus699.geojson:
--------------------------------------------------------------------------------
1 | {"type": "Feature", "properties": {"name": "Track of bus 699", "times": ["2019-11-23 10:51:06", "2019-11-23 10:52:05", "2019-11-23 10:53:05", "2019-11-23 10:54:04", "2019-11-23 10:55:05", "2019-11-23 10:56:05", "2019-11-23 10:57:05", "2019-11-23 10:58:05", "2019-11-23 10:59:05", "2019-11-23 11:00:06", "2019-11-23 11:01:06", "2019-11-23 11:02:06", "2019-11-23 11:03:05", "2019-11-23 11:04:04", "2019-11-23 11:05:06", "2019-11-23 11:06:05", "2019-11-23 11:07:05", "2019-11-23 11:08:05", "2019-11-23 11:09:05", "2019-11-23 11:10:06", "2019-11-23 11:11:05", "2019-11-23 11:12:05", "2019-11-23 11:13:05", "2019-11-23 11:14:06", "2019-11-23 11:15:05", "2019-11-23 11:16:05", "2019-11-23 11:17:05", "2019-11-23 11:18:05", "2019-11-23 11:19:05", "2019-11-23 11:20:06", "2019-11-23 11:21:05", "2019-11-23 11:22:05", "2019-11-23 11:23:05", "2019-11-23 11:24:06", "2019-11-23 11:25:06", "2019-11-23 11:26:05", "2019-11-23 11:27:05", "2019-11-23 11:28:04", "2019-11-23 11:29:06"]}, "geometry": {"type": "LineString", "coordinates": [[-4.4214296, 36.73835], [-4.422104, 36.737865], [-4.4229302, 36.73773], [-4.4235334, 36.735817], [-4.4222927, 36.73413], [-4.4218254, 36.732475], [-4.4213734, 36.72983], [-4.420156, 36.73], [-4.419239, 36.730686], [-4.417272, 36.732136], [-4.4155564, 36.732613], [-4.4155564, 36.732613], [-4.4147606, 36.729523], [-4.4143534, 36.728085], [-4.414023, 36.727142], [-4.414023, 36.727142], [-4.4145956, 36.726017], [-4.4163203, 36.722366], [-4.4163203, 36.722366], [-4.4142747, 36.72012], [-4.4162464, 36.71957], [-4.418931, 36.71882], [-4.421059, 36.718254], [-4.421595, 36.718174], [-4.424712, 36.717197], [-4.4268923, 36.717003], [-4.427205, 36.717583], [-4.426953, 36.717876], [-4.4264026, 36.715973], [-4.4267263, 36.71531], [-4.4270782, 36.714962], [-4.4300385, 36.71217], [-4.4314194, 36.71117], [-4.4344425, 36.70879], [-4.437068, 36.706684], [-4.4393854, 36.70489], [-4.440271, 36.704346], [-4.4454684, 36.702717], [-4.4454684, 36.702717]]}}
--------------------------------------------------------------------------------
/examples/example1.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
Code
23 |
24 |
27 |
30 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
48 |
49 |
50 |
51 |
52 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/examples/example10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
34 |
35 |
36 |
37 |
Description
38 |
This is a proof-of-concept . We have implemented a new L.TimeDimension.Layer class to manage ImageOverlays and a basic custom control to manage the TimeDimension.
39 |
The chart shows the daily wind average observed at the weather station installed in Cala Millor by SOCIB. If you click in any point of the chart, it will show the image of the selected date at 12:00h.
40 |
Code
41 |
42 |
43 |
46 |
49 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
83 |
84 |
85 |
--------------------------------------------------------------------------------
/examples/example11.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
Code
32 |
33 |
34 |
37 |
40 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/examples/example12.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
37 |
38 |
39 |
40 |
44 |
45 |
46 |
47 |
Code
48 |
49 |
50 |
53 |
56 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/examples/example13.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Information
24 |
43 |
44 |
45 |
Code
46 |
47 |
48 |
51 |
54 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/examples/example14.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Information
24 |
30 |
31 |
32 |
Code
33 |
34 |
35 |
38 |
41 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/examples/example15.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
33 |
34 |
35 |
36 |
40 |
43 |
Information
44 |
48 |
49 |
Code
50 |
51 |
52 |
55 |
58 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/examples/example16.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Leaflet TimeDimension
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
19 |
20 |
21 |
Information
22 |
27 |
28 |
Code
29 |
30 |
Code of L.TimeDimension.Layer.TileLayer.Portus
31 |
32 |
33 |
36 |
39 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
81 |
82 |
83 |
--------------------------------------------------------------------------------
/examples/example17.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Leaflet TimeDimension
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
Code
28 |
29 |
30 |
33 |
36 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/examples/example18.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Leaflet TimeDimension
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
21 |
25 |
26 |
Information
27 |
37 |
38 |
Code
39 |
40 |
41 |
44 |
47 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
82 |
83 |
84 |
--------------------------------------------------------------------------------
/examples/example2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
Code
22 |
23 |
26 |
29 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/examples/example3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
21 |
22 |
23 |
Select start time and end time of the animation loop
24 |
25 | Start time (local time)
26 |
27 |
28 | End time (local time)
29 |
30 |
31 | Apply new time availables range
32 | Apply new time limits range
33 |
34 |
35 |
36 |
37 |
Code
38 |
39 |
42 |
45 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/examples/example4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Code
24 |
25 |
26 |
29 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/examples/example5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
Disclaimer
22 |
This example is not working because the dataset of this climate projections is no longer online. It will be replaced soon. If you know a similar dataset, please open an issue or send a Pull Request.
23 |
24 |
Code
25 |
26 |
27 |
30 |
33 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/examples/example6.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Code
24 |
25 |
26 |
29 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/examples/example7.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Code
24 |
25 |
26 |
29 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/examples/example8.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Code
24 |
25 |
26 |
29 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/examples/example9.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
20 |
21 |
22 |
23 |
Code
24 |
25 |
28 |
29 |
32 |
35 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/examples/img/.directory:
--------------------------------------------------------------------------------
1 | [Dolphin]
2 | PreviewsShown=true
3 | Timestamp=2014,12,18,17,21,52
4 | Version=3
5 |
--------------------------------------------------------------------------------
/examples/img/GitHub-Mark-32px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/GitHub-Mark-32px.png
--------------------------------------------------------------------------------
/examples/img/black-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/black-arrow.png
--------------------------------------------------------------------------------
/examples/img/bus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/bus.png
--------------------------------------------------------------------------------
/examples/img/grey-arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/grey-arrow.png
--------------------------------------------------------------------------------
/examples/img/logo-leaflettimedimension-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/logo-leaflettimedimension-32.png
--------------------------------------------------------------------------------
/examples/img/logo-leaflettimedimension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/logo-leaflettimedimension.png
--------------------------------------------------------------------------------
/examples/img/logo-socib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/logo-socib.png
--------------------------------------------------------------------------------
/examples/img/running.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/running.png
--------------------------------------------------------------------------------
/examples/img/screenshot/.directory:
--------------------------------------------------------------------------------
1 | [Dolphin]
2 | PreviewsShown=true
3 | Timestamp=2014,12,18,17,49,4
4 | Version=3
5 |
--------------------------------------------------------------------------------
/examples/img/screenshot/1-aviso.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/1-aviso.png
--------------------------------------------------------------------------------
/examples/img/screenshot/10-imageoverlay-customcontrol.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/10-imageoverlay-customcontrol.png
--------------------------------------------------------------------------------
/examples/img/screenshot/11-noaa-cdr-sst.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/11-noaa-cdr-sst.png
--------------------------------------------------------------------------------
/examples/img/screenshot/12-nyc-opendata.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/12-nyc-opendata.png
--------------------------------------------------------------------------------
/examples/img/screenshot/13-wms-timeseries.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/13-wms-timeseries.png
--------------------------------------------------------------------------------
/examples/img/screenshot/14-noaa-nowcast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/14-noaa-nowcast.png
--------------------------------------------------------------------------------
/examples/img/screenshot/15-oil-spill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/15-oil-spill.png
--------------------------------------------------------------------------------
/examples/img/screenshot/16-portus-tilelayers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/16-portus-tilelayers.png
--------------------------------------------------------------------------------
/examples/img/screenshot/17-basic-geojson.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/17-basic-geojson.png
--------------------------------------------------------------------------------
/examples/img/screenshot/18-velocity-integration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/18-velocity-integration.png
--------------------------------------------------------------------------------
/examples/img/screenshot/2-temperature-forecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/2-temperature-forecast.png
--------------------------------------------------------------------------------
/examples/img/screenshot/3-hfradar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/3-hfradar.png
--------------------------------------------------------------------------------
/examples/img/screenshot/4-rain-radar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/4-rain-radar.png
--------------------------------------------------------------------------------
/examples/img/screenshot/5-climate-projections.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/5-climate-projections.png
--------------------------------------------------------------------------------
/examples/img/screenshot/6-sapoib.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/6-sapoib.png
--------------------------------------------------------------------------------
/examples/img/screenshot/7-ocean-forecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/7-ocean-forecast.png
--------------------------------------------------------------------------------
/examples/img/screenshot/8-hfradar-with-drifters.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/8-hfradar-with-drifters.png
--------------------------------------------------------------------------------
/examples/img/screenshot/9-gxp-kml-tracks.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/9-gxp-kml-tracks.png
--------------------------------------------------------------------------------
/examples/img/screenshot/screenshot-leaflet-timedimension.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/screenshot/screenshot-leaflet-timedimension.png
--------------------------------------------------------------------------------
/examples/img/surface-drifter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/socib/Leaflet.TimeDimension/fa36ffee7f6390aadce8c055ca7c60ede7c2134c/examples/img/surface-drifter.png
--------------------------------------------------------------------------------
/examples/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Leaflet TimeDimension
5 |
6 |
7 |
8 |
9 |
10 |
11 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/examples/js/baselayers.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Return common layers used in different examples
3 | */
4 | function getCommonBaseLayers(map){
5 | var osmLayer = L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
6 | attribution: '© OpenStreetMap contributors'
7 | });
8 | var bathymetryLayer = L.tileLayer.wms("https://ows.emodnet-bathymetry.eu/wms", {
9 | layers: 'emodnet:mean_atlas_land',
10 | format: 'image/png',
11 | transparent: true,
12 | attribution: "EMODnet Bathymetry",
13 | opacity: 0.8
14 | });
15 | var coastlinesLayer = L.tileLayer.wms("https://ows.emodnet-bathymetry.eu/wms", {
16 | layers: 'coastlines',
17 | format: 'image/png',
18 | transparent: true,
19 | attribution: "EMODnet Bathymetry",
20 | opacity: 0.8
21 | });
22 | var bathymetryGroupLayer = L.layerGroup([bathymetryLayer, coastlinesLayer]);
23 | bathymetryGroupLayer.addTo(map);
24 | return {
25 | "EMODnet Bathymetry": bathymetryGroupLayer,
26 | "OSM": osmLayer
27 | };
28 | }
--------------------------------------------------------------------------------
/examples/js/example1.js:
--------------------------------------------------------------------------------
1 | var map = L.map('map', {
2 | zoom: 5,
3 | fullscreenControl: true,
4 | timeDimension: true,
5 | timeDimensionControl: true,
6 | center: [38.0, 15.0]
7 | });
8 |
9 | var avisoWMS = "https://thredds.socib.es/thredds/wms/observational/satellite/altimetry/aviso/madt/sealevel_med_phy_nrt_L4_agg/sealevel_med_phy_nrt_L4_agg_best.ncd";
10 |
11 | var heigthLayer = L.tileLayer.wms(avisoWMS, {
12 | layers: 'adt',
13 | format: 'image/png',
14 | transparent: true,
15 | colorscalerange: '-0.4,0.4',
16 | abovemaxcolor: "extend",
17 | belowmincolor: "extend",
18 | numcolorbands: 100,
19 | styles: 'boxfill/rainbow'
20 | });
21 | var heigthContourLayer = L.tileLayer.wms(avisoWMS, {
22 | layers: 'adt',
23 | format: 'image/png',
24 | transparent: true,
25 | colorscalerange: '-0.5,0.5',
26 | numcontours: 11,
27 | styles: 'contour/rainbow'
28 | });
29 |
30 | var velocityLayer = L.nonTiledLayer.wms(avisoWMS, {
31 | layers: 'surface_geostrophic_sea_water_velocity',
32 | format: 'image/png',
33 | transparent: true,
34 | colorscalerange: '-20,100',
35 | markerscale: 10,
36 | markerspacing: 8,
37 | abovemaxcolor: "extend",
38 | belowmincolor: "extend",
39 | numcolorbands: 100,
40 | styles: 'prettyvec/greyscale'
41 | });
42 |
43 | var proxy = 'server/proxy.php';
44 | var heightTimeLayer = L.timeDimension.layer.wms(heigthLayer, {
45 | proxy: proxy,
46 | updateTimeDimension: true,
47 | });
48 | var heightContourTimeLayer = L.timeDimension.layer.wms(heigthContourLayer, {
49 | proxy: proxy,
50 | updateTimeDimension: false,
51 | });
52 | var velocityTimeLayer = L.timeDimension.layer.wms(velocityLayer, {
53 | proxy: proxy,
54 | updateTimeDimension: false,
55 | });
56 |
57 | var overlayMaps = {
58 | "AVISO - Sea surface height above geoid": heightTimeLayer,
59 | "AVISO - Sea surface height above geoid (Contour)": heightContourTimeLayer,
60 | "AVISO - Surface geostrophic sea water velocity": velocityTimeLayer
61 | };
62 |
63 | // Legends
64 | var heigthLegend = L.control({
65 | position: 'bottomright'
66 | });
67 | heigthLegend.onAdd = function(map) {
68 | var src = avisoWMS + "?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&LAYER=adt&colorscalerange=-0.4,0.4&PALETTE=rainbow&transparent=TRUE";
69 | var div = L.DomUtil.create('div', 'info legend');
70 | div.innerHTML +=
71 | ' ';
72 | return div;
73 | };
74 |
75 | var velocityLegend = L.control({
76 | position: 'bottomright'
77 | });
78 | velocityLegend.onAdd = function(map) {
79 | var div = L.DomUtil.create('div', 'info legend');
80 | div.innerHTML += ' Surface geostrophic sea water velocity';
81 | return div;
82 | };
83 |
84 |
85 | map.on('overlayadd', function(eventLayer) {
86 | if (eventLayer.name == 'AVISO - Sea surface height above geoid') {
87 | heigthLegend.addTo(this);
88 | } else if (eventLayer.name == 'AVISO - Surface geostrophic sea water velocity') {
89 | velocityLegend.addTo(this);
90 | }
91 | });
92 |
93 | map.on('overlayremove', function(eventLayer) {
94 | if (eventLayer.name == 'AVISO - Sea surface height above geoid') {
95 | map.removeControl(heigthLegend);
96 | } else if (eventLayer.name == 'AVISO - Surface geostrophic sea water velocity') {
97 | map.removeControl(velocityLegend);
98 | }
99 | });
100 |
101 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
102 | L.control.layers(baseLayers, overlayMaps).addTo(map);
103 |
104 | heightTimeLayer.addTo(map);
105 | heightContourTimeLayer.addTo(map);
106 | velocityTimeLayer.addTo(map);
--------------------------------------------------------------------------------
/examples/js/example11.js:
--------------------------------------------------------------------------------
1 | Date.prototype.format = function (mask, utc) {
2 | return dateFormat(this, mask, utc);
3 | };
4 |
5 | var currentMonth = new Date();
6 | currentMonth.setUTCDate(1);
7 | currentMonth.setUTCHours(12, 0, 0, 0);
8 |
9 | var map = L.map('map', {
10 | zoom: 2,
11 | fullscreenControl: true,
12 | timeDimension: true,
13 | timeDimensionOptions:{
14 | timeInterval: "P6M/" + currentMonth.format("yyyy-mm-dd\'T\'HH:MM:ss"),
15 | period: "P1M",
16 | currentTime: currentMonth
17 | },
18 | center: [20.0, 0.0],
19 | });
20 |
21 | L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
22 | attribution: '© OpenStreetMap contributors'
23 | }).addTo(map);
24 |
25 | var proxy = 'server/proxy.php';
26 | var testWMS = "https://www.ncei.noaa.gov/thredds/wms/ncFC/fc-oisst-daily-avhrr-only-dly/OISST_Daily_AVHRR-only_Feature_Collection_best.ncd"
27 | var testLayer = L.tileLayer.wms(testWMS, {
28 | layers: 'sst',
29 | format: 'image/png',
30 | transparent: true,
31 | style: 'boxfill/sst_36',
32 | colorscalerange: '-3,35',
33 | abovemaxcolor: "extend",
34 | belowmincolor: "extend",
35 | attribution: 'NOAAs National Climatic Data Center '
36 | });
37 |
38 | var testTimeLayer = L.timeDimension.layer.wms(testLayer, {
39 | proxy: proxy,
40 | updateTimeDimension: false,
41 | });
42 | testTimeLayer.addTo(map);
43 |
44 | var testLegend = L.control({
45 | position: 'topright'
46 | });
47 | testLegend.onAdd = function(map) {
48 | var src = testWMS + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=sst&PALETTE=sst_36&COLORSCALERANGE=-3,35";
49 | var div = L.DomUtil.create('div', 'info legend');
50 | div.innerHTML +=
51 | ' ';
52 | return div;
53 | };
54 | testLegend.addTo(map);
55 |
56 | L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({
57 | _getDisplayDateFormat: function(date){
58 | return date.format("dS mmmm yyyy");
59 | }
60 | });
61 | var timeDimensionControl = new L.Control.TimeDimensionCustom({
62 | playerOptions: {
63 | buffer: 1,
64 | minBufferReady: -1
65 | }
66 | });
67 | map.addControl(this.timeDimensionControl);
68 |
--------------------------------------------------------------------------------
/examples/js/example12.js:
--------------------------------------------------------------------------------
1 | Date.prototype.format = function (mask, utc) {
2 | return dateFormat(this, mask, utc);
3 | };
4 |
5 |
6 |
7 | // Attibution: SODA API requests based on this example: https://github.com/chriswhong/soda-leaflet
8 | L.TimeDimension.Layer.SODAHeatMap = L.TimeDimension.Layer.extend({
9 |
10 | initialize: function(options) {
11 | var heatmapCfg = this._getHeatmapOptions(options.heatmatOptions || {});
12 | var layer = new HeatmapOverlay(heatmapCfg);
13 | L.TimeDimension.Layer.prototype.initialize.call(this, layer, options);
14 | this._currentLoadedTime = 0;
15 | this._currentTimeData = {
16 | max: this.options.heatmapMax || 10,
17 | data: []
18 | };
19 | this._baseURL = this.options.baseURL || null;
20 | this._period = this.options.period || "P1M";
21 | },
22 |
23 | _getHeatmapOptions: function(options) {
24 | var config = {};
25 | var defaultConfig = {
26 | radius: 15,
27 | maxOpacity: .8,
28 | scaleRadius: false,
29 | useLocalExtrema: false,
30 | latField: 'lat',
31 | lngField: 'lng',
32 | valueField: 'count'
33 | };
34 | for (var attrname in defaultConfig) {
35 | config[attrname] = defaultConfig[attrname];
36 | }
37 | for (var attrname in options) {
38 | config[attrname] = options[attrname];
39 | }
40 | return config;
41 | },
42 |
43 | onAdd: function(map) {
44 | L.TimeDimension.Layer.prototype.onAdd.call(this, map);
45 | map.addLayer(this._baseLayer);
46 | if (this._timeDimension) {
47 | this._getDataForTime(this._timeDimension.getCurrentTime());
48 | }
49 | },
50 |
51 | _onNewTimeLoading: function(ev) {
52 | this._getDataForTime(ev.time);
53 | return;
54 | },
55 |
56 | isReady: function(time) {
57 | return (this._currentLoadedTime == time);
58 | },
59 |
60 | _update: function() {
61 | this._baseLayer.setData(this._currentTimeData);
62 | return true;
63 | },
64 |
65 | _getDataForTime: function(time) {
66 | if (!this._baseURL || !this._map) {
67 | return;
68 | }
69 | var url = this._constructQuery(time);
70 | var oReq = new XMLHttpRequest();
71 | oReq.addEventListener("load", (function(xhr) {
72 | var response = xhr.currentTarget.response;
73 | var data = JSON.parse(response);
74 | delete this._currentTimeData.data;
75 | this._currentTimeData.data = [];
76 | for (var i = 0; i < data.length; i++) {
77 | var marker = data[i];
78 | if (marker.location) {
79 | this._currentTimeData.data.push({
80 | lat: marker.location.latitude,
81 | lng: marker.location.longitude,
82 | count: 1
83 | });
84 | }
85 | }
86 | this._currentLoadedTime = time;
87 | if (this._timeDimension && time == this._timeDimension.getCurrentTime() && !this._timeDimension.isLoading()) {
88 | this._update();
89 | }
90 | this.fire('timeload', {
91 | time: time
92 | });
93 | }).bind(this));
94 |
95 | oReq.open("GET", url);
96 | oReq.send();
97 |
98 | },
99 |
100 | _constructQuery: function(time) {
101 | var bbox = this._map.getBounds();
102 | var sodaQueryBox = [bbox._northEast.lat, bbox._southWest.lng, bbox._southWest.lat, bbox._northEast.lng];
103 |
104 | var startDate = new Date(time);
105 | var endDate = new Date(startDate.getTime());
106 | L.TimeDimension.Util.addTimeDuration(endDate, this._period, false);
107 |
108 | var where = "&$where=created_date > '" +
109 | startDate.format('yyyy-mm-dd') +
110 | "' AND created_date < '" +
111 | endDate.format('yyyy-mm-dd') +
112 | "' AND within_box(location," +
113 | sodaQueryBox +
114 | ")&$order=created_date desc";
115 |
116 | var url = this._baseURL + where;
117 | return url;
118 | }
119 |
120 | });
121 |
122 | L.timeDimension.layer.sodaHeatMap = function(options) {
123 | return new L.TimeDimension.Layer.SODAHeatMap(options);
124 | };
125 |
126 |
127 |
128 | var currentTime = new Date();
129 | currentTime.setUTCDate(1, 0, 0, 0, 0);
130 |
131 | var map = L.map('map', {
132 | zoom: 12,
133 | fullscreenControl: true,
134 | timeDimension: true,
135 | timeDimensionOptions: {
136 | timeInterval: "2010-01-01/" + currentTime.toISOString(),
137 | period: "P1M",
138 | currentTime: currentTime
139 | },
140 | center: [40.74, -73.9],
141 | });
142 |
143 | var layer = new L.StamenTileLayer("toner-lite");
144 | map.addLayer(layer);
145 |
146 | var testSODALayer = L.timeDimension.layer.sodaHeatMap({
147 | baseURL: 'https://data.cityofnewyork.us/resource/erm2-nwe9.json?$select=location,closed_date,complaint_type,street_name,created_date,status,unique_key,agency_name,due_date,descriptor,location_type,agency,incident_address&complaint_type=Noise - Commercial',
148 | });
149 | testSODALayer.addTo(map);
150 | map.attributionControl.addAttribution('NYC OpenData ');
151 |
152 | L.Control.TimeDimensionCustom = L.Control.TimeDimension.extend({
153 | _getDisplayDateFormat: function(date){
154 | return date.format("mmmm yyyy");
155 | }
156 | });
157 | var timeDimensionControl = new L.Control.TimeDimensionCustom({
158 | playerOptions: {
159 | buffer: 1,
160 | minBufferReady: -1
161 | }
162 | });
163 | map.addControl(this.timeDimensionControl);
164 |
--------------------------------------------------------------------------------
/examples/js/example13.js:
--------------------------------------------------------------------------------
1 | var startDate = new Date();
2 | startDate.setUTCHours(0, 0, 0, 0);
3 |
4 | var map = L.map('map', {
5 | zoom: 8,
6 | fullscreenControl: true,
7 | timeDimensionControl: true,
8 | timeDimensionControlOptions: {
9 | position: 'bottomleft',
10 | playerOptions: {
11 | transitionTime: 1000,
12 | }
13 | },
14 | timeDimension: true,
15 | center: [39.3, 2.9]
16 | });
17 |
18 | var sapoWMS = "https://thredds.socib.es/thredds/wms/operational_models/oceanographical/wave/model_run_aggregation/sapo_ib/sapo_ib_best.ncd";
19 | var sapoHeightLayer = L.tileLayer.wms(sapoWMS, {
20 | layers: 'significant_wave_height',
21 | format: 'image/png',
22 | transparent: true,
23 | colorscalerange: '0,3',
24 | abovemaxcolor: "extend",
25 | belowmincolor: "extend",
26 | numcolorbands: 100,
27 | styles: 'areafill/scb_bugnylorrd'
28 | });
29 |
30 | var sapoMeanDirectionLayer = L.nonTiledLayer.wms(sapoWMS, {
31 | layers: 'average_wave_direction',
32 | format: 'image/png',
33 | transparent: true,
34 | colorscalerange: '1,1',
35 | abovemaxcolor: "extend",
36 | belowmincolor: "extend",
37 | markerscale: 15,
38 | markerspacing: 12,
39 | markerclipping: true,
40 | styles: 'prettyvec/greyscale'
41 | });
42 |
43 | var sapoPeakDirectionLayer = L.nonTiledLayer.wms(sapoWMS, {
44 | layers: 'direction_of_the_peak_of_the_spectrum',
45 | format: 'image/png',
46 | transparent: true,
47 | colorscalerange: '0,2',
48 | abovemaxcolor: "extend",
49 | belowmincolor: "extend",
50 | markerscale: 15,
51 | markerspacing: 12,
52 | markerclipping: true,
53 | styles: 'prettyvec/greyscale'
54 | });
55 |
56 | var markers = [{
57 | name: 'Sa Dragonera',
58 | position: [39.555, 2.102],
59 | platformName: 'Buoy at Sa Dragonera',
60 | platform: 18,
61 | instrument: 68,
62 | variable: 17
63 | }, {
64 | name: 'Alcúdia',
65 | position: [39.8, 3.216]
66 | }, {
67 | name: 'Palma',
68 | position: [39.492847, 2.700405],
69 | platformName: 'Buoy at Palma Bay',
70 | platform: 143,
71 | instrument: 296,
72 | variable: 90047
73 | }, {
74 | name: 'Ciutadella',
75 | position: [39.976, 3.761]
76 | }, {
77 | name: 'Ibiza Channel',
78 | platformName: 'Buoy at Ibiza Channel',
79 | position: [38.82445, 0.783667],
80 | platform: 146,
81 | instrument: 314,
82 | variable: 90047
83 | }];
84 |
85 | var proxy = 'server/proxy.php';
86 | var sapoHeightTimeLayer = L.timeDimension.layer.wms.timeseries(sapoHeightLayer, {
87 | proxy: proxy,
88 | updateTimeDimension: true,
89 | markers: markers,
90 | name: "Significant wave height",
91 | units: "m",
92 | enableNewMarkers: true
93 | });
94 |
95 | var sapoMeanDirectionTimeLayer = L.timeDimension.layer.wms(sapoMeanDirectionLayer, {
96 | proxy: proxy
97 | });
98 | var sapoPeakDirectionTimeLayer = L.timeDimension.layer.wms(sapoPeakDirectionLayer, {
99 | proxy: proxy
100 | });
101 |
102 | var sapoLegend = L.control({
103 | position: 'bottomright'
104 | });
105 | sapoLegend.onAdd = function(map) {
106 | var src = sapoWMS + "?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&LAYER=significant_wave_height&colorscalerange=0,3&PALETTE=scb_bugnylorrd&numcolorbands=100&transparent=TRUE";
107 | var div = L.DomUtil.create('div', 'info legend');
108 | div.innerHTML +=
109 | ' ';
110 | return div;
111 | };
112 |
113 | var sapoMeanDirectionLegend = L.control({
114 | position: 'bottomright'
115 | });
116 | sapoMeanDirectionLegend.onAdd = function(map) {
117 | var div = L.DomUtil.create('div', 'info legend');
118 | div.innerHTML += ' mean direction';
119 | return div;
120 | };
121 |
122 | var sapoPeakDirectionLegend = L.control({
123 | position: 'bottomright'
124 | });
125 | sapoPeakDirectionLegend.onAdd = function(map) {
126 | var div = L.DomUtil.create('div', 'info legend');
127 | div.innerHTML += ' peak direction';
128 | return div;
129 | };
130 |
131 | var overlayMaps = {
132 | "SAPO - significant wave height": sapoHeightTimeLayer,
133 | "SAPO - average wave direction": sapoMeanDirectionTimeLayer,
134 | "SAPO - direction of the peak": sapoPeakDirectionTimeLayer
135 | };
136 |
137 | map.on('overlayadd', function(eventLayer) {
138 | if (eventLayer.name == 'SAPO - significant wave height') {
139 | sapoLegend.addTo(this);
140 | } else if (eventLayer.name == 'SAPO - average wave direction') {
141 | sapoMeanDirectionLegend.addTo(this);
142 | } else if (eventLayer.name == 'SAPO - direction of the peak') {
143 | sapoPeakDirectionLegend.addTo(this);
144 | }
145 | });
146 |
147 | map.on('overlayremove', function(eventLayer) {
148 | if (eventLayer.name == 'SAPO - significant wave height') {
149 | map.removeControl(sapoLegend);
150 | } else if (eventLayer.name == 'SAPO - average wave direction') {
151 | map.removeControl(sapoMeanDirectionLegend);
152 | } else if (eventLayer.name == 'SAPO - direction of the peak') {
153 | map.removeControl(sapoPeakDirectionLegend);
154 | }
155 | });
156 |
157 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
158 | L.control.layers(baseLayers, overlayMaps).addTo(map);
159 |
160 | sapoHeightTimeLayer.addTo(map);
161 | sapoPeakDirectionTimeLayer.addTo(map);
162 | sapoMeanDirectionTimeLayer.addTo(map);
--------------------------------------------------------------------------------
/examples/js/example14.js:
--------------------------------------------------------------------------------
1 | var endDate = new Date();
2 | endDate.setUTCMinutes(0, 0, 0);
3 |
4 | var map = L.map('map', {
5 | zoom: 4,
6 | fullscreenControl: true,
7 | timeDimension: true,
8 | timeDimensionControl: true,
9 | timeDimensionOptions:{
10 | timeInterval: "PT4H/" + endDate.toISOString(),
11 | period: "PT4M",
12 | currentTime: endDate
13 | },
14 |
15 | timeDimensionControlOptions: {
16 | autoPlay: false,
17 | playerOptions: {
18 | buffer: 10,
19 | transitionTime: 250,
20 | loop: true,
21 | }
22 | },
23 | center: [38.0, -90.50],
24 | });
25 |
26 | L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
27 | attribution: '© OpenStreetMap contributors'
28 | }).addTo(map);
29 |
30 | var wmsUrl = "https://nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WMSServer"
31 | var radarWMS = L.nonTiledLayer.wms(wmsUrl, {
32 | layers: '1',
33 | format: 'image/png',
34 | transparent: true,
35 | opacity: 0.8,
36 | attribution: 'nowCOAST'
37 | });
38 |
39 | var testTimeLayer = L.timeDimension.layer.wms(radarWMS, {
40 | updateTimeDimension: false,
41 | wmsVersion: '1.3.0'
42 | });
43 | testTimeLayer.addTo(map);
44 |
45 | var theLegend = L.control({
46 | position: 'topright'
47 | });
48 |
49 | theLegend.onAdd = function(map) {
50 | var src = "https://nowcoast.noaa.gov/images/legends/radar.png";
51 | var div = L.DomUtil.create('div', 'info legend');
52 | div.style.width = '270px';
53 | div.style.height = '50px';
54 | div.innerHTML += 'Legend ';
55 | return div;
56 | };
57 | theLegend.addTo(map);
--------------------------------------------------------------------------------
/examples/js/example15.js:
--------------------------------------------------------------------------------
1 | L.TimeDimension.Layer.CDrift = L.TimeDimension.Layer.GeoJson.extend({
2 |
3 | // CDrift data has property time in seconds, not in millis.
4 | _getFeatureTimes: function(feature) {
5 | if (!feature.properties) {
6 | return [];
7 | }
8 | if (feature.properties.hasOwnProperty('coordTimes')) {
9 | return feature.properties.coordTimes;
10 | }
11 | if (feature.properties.hasOwnProperty('times')) {
12 | return feature.properties.times;
13 | }
14 | if (feature.properties.hasOwnProperty('linestringTimestamps')) {
15 | return feature.properties.linestringTimestamps;
16 | }
17 | if (feature.properties.hasOwnProperty('time')) {
18 | return [feature.properties.time * 1000];
19 | }
20 | return [];
21 | },
22 |
23 | // Do not modify features. Just return the feature if it intersects
24 | // the time interval
25 | _getFeatureBetweenDates: function(feature, minTime, maxTime) {
26 | var featureStringTimes = this._getFeatureTimes(feature);
27 | if (featureStringTimes.length == 0) {
28 | return feature;
29 | }
30 | var featureTimes = [];
31 | for (var i = 0, l = featureStringTimes.length; i < l; i++) {
32 | var time = featureStringTimes[i]
33 | if (typeof time == 'string' || time instanceof String) {
34 | time = Date.parse(time.trim());
35 | }
36 | featureTimes.push(time);
37 | }
38 |
39 | if (featureTimes[0] > maxTime || featureTimes[l - 1] < minTime) {
40 | return null;
41 | }
42 | return feature;
43 | },
44 |
45 | });
46 |
47 | L.timeDimension.layer.cDrift = function(layer, options) {
48 | return new L.TimeDimension.Layer.CDrift(layer, options);
49 | };
50 |
51 | var startDate = new Date();
52 | startDate.setUTCHours(0, 0, 0, 0);
53 |
54 | var map = L.map('map', {
55 | zoom: 8,
56 | fullscreenControl: true,
57 | timeDimensionControl: true,
58 | timeDimensionControlOptions: {
59 | position: 'bottomleft',
60 | autoPlay: true,
61 | timeSlider: false,
62 | loopButton: true,
63 | playerOptions: {
64 | transitionTime: 125,
65 | loop: true,
66 | }
67 | },
68 | timeDimension: true,
69 | center: [39.6145, 1.99363]
70 | });
71 |
72 | var oReq = new XMLHttpRequest();
73 | oReq.addEventListener("load", (function(xhr) {
74 | var response = xhr.currentTarget.response;
75 | var data = JSON.parse(response);
76 | var cdriftLayer = L.geoJson(data, {
77 | style: function(feature) {
78 | var color = "#FFF";
79 | if (feature.properties.confidence == '0.9') {
80 | color = "#FF0000";
81 | } else if (feature.properties.confidence == '0.75') {
82 | color = "#FFFF00";
83 | } else if (feature.properties.confidence == '0.5') {
84 | color = "#00FF00";
85 | }
86 | return {
87 | "color": color,
88 | "weight": 2,
89 | "opacity": 0.4
90 | };
91 | }
92 | });
93 |
94 | var cdriftTimeLayer = L.timeDimension.layer.cDrift(cdriftLayer, {
95 | updateTimeDimension: true,
96 | updateTimeDimensionMode: 'replace',
97 | addlastPoint: false,
98 | duration: 'PT20M',
99 | });
100 | cdriftTimeLayer.addTo(map);
101 | map.fitBounds(cdriftLayer.getBounds());
102 |
103 | var cDriftLegend = L.control({
104 | position: 'bottomright'
105 | });
106 | cDriftLegend.onAdd = function(map) {
107 | var div = L.DomUtil.create('div', 'info legend');
108 | div.innerHTML += '50% probability 75% probability 90% probability ';
109 | return div;
110 | };
111 | cDriftLegend.addTo(map);
112 |
113 | map.timeDimension.on('timeload', function(data) {
114 | var date = new Date(map.timeDimension.getCurrentTime());
115 | if (data.time == map.timeDimension.getCurrentTime()) {
116 | var totalTimes = map.timeDimension.getAvailableTimes().length;
117 | var position = map.timeDimension.getAvailableTimes().indexOf(data.time);
118 | map.getContainer().querySelector('.animation-progress-bar').style.width = ((position*100)/totalTimes + "%");
119 | // update map bounding box
120 | map.fitBounds(cdriftTimeLayer.getBounds());
121 | }
122 | });
123 | }));
124 | oReq.open("GET", 'data/spill.json');
125 | oReq.send();
126 |
127 |
128 |
129 |
130 | var sorrento = L.circleMarker([39.6145, 1.99363], {
131 | color: '#FFFFFF',
132 | fillColor: "#f28f43",
133 | fillOpacity: 1,
134 | radius: 5,
135 | weight: 2
136 | }).addTo(map);
137 |
138 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
139 | L.control.layers(baseLayers, {}).addTo(map);
140 |
--------------------------------------------------------------------------------
/examples/js/example16.js:
--------------------------------------------------------------------------------
1 | var startDate = new Date();
2 | startDate.setUTCHours(0, 0, 0, 0);
3 |
4 | var map = L.map('map', {
5 | zoom: 7,
6 | fullscreenControl: true,
7 | timeDimensionControl: true,
8 | timeDimensionControlOptions: {
9 | position: 'bottomleft',
10 | playerOptions: {
11 | transitionTime: 1000,
12 | }
13 | },
14 | timeDimension: true,
15 | timeDimensionOptions: {
16 | timeInterval: startDate.toISOString() + "/PT72H",
17 | period: "PT3H"
18 | },
19 | center: [39.3, 2.9]
20 | });
21 |
22 | var portusLayer = L.tileLayer('https://portus.puertos.es/Portus//pathtiles/wave/MED/VHM0/{d}{h}/map//{z}/{x}/{y}.png', {
23 | attribution: '© Agencia Estatal de Meteorología (AEMET) y Puertos del Estado (OPPE) ',
24 | tms: true,
25 | maxZoom: 7,
26 | });
27 | var portusTimeLayer = L.timeDimension.layer.tileLayer.portus(portusLayer, {});
28 |
29 | var portusBalLayer = L.tileLayer('https://portus.puertos.es/Portus//pathtiles/wave/S12B/VHM0/{d}{h}/map//{z}/{x}/{y}.png', {
30 | attribution: '© Agencia Estatal de Meteorología (AEMET) y Puertos del Estado (OPPE) ',
31 | tms: true,
32 | minZoom: 8
33 | });
34 | var portusBalTimeLayer = L.timeDimension.layer.tileLayer.portus(portusBalLayer, {});
35 |
36 | var overlayMaps = {
37 | "Mediterranean wave": portusTimeLayer,
38 | "Balearic wave": portusBalTimeLayer,
39 | };
40 |
41 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
42 | L.control.layers(baseLayers, overlayMaps).addTo(map);
43 |
44 | portusTimeLayer.addTo(map);
45 | portusBalTimeLayer.addTo(map);
46 |
--------------------------------------------------------------------------------
/examples/js/example17.js:
--------------------------------------------------------------------------------
1 | function addGeoJSONLayer(map, data) {
2 | var icon = L.icon({
3 | iconUrl: 'img/bus.png',
4 | iconSize: [22, 22],
5 | iconAnchor: [11, 11]
6 | });
7 |
8 | var geoJSONLayer = L.geoJSON(data, {
9 | pointToLayer: function (feature, latLng) {
10 | if (feature.properties.hasOwnProperty('last')) {
11 | return new L.Marker(latLng, {
12 | icon: icon
13 | });
14 | }
15 | return L.circleMarker(latLng);
16 | }
17 | });
18 |
19 | var geoJSONTDLayer = L.timeDimension.layer.geoJson(geoJSONLayer, {
20 | updateTimeDimension: true,
21 | duration: 'PT2M',
22 | updateTimeDimensionMode: 'replace',
23 | addlastPoint: true
24 | });
25 |
26 | // Show both layers: the geoJSON layer to show the whole track
27 | // and the timedimension layer to show the movement of the bus
28 | geoJSONLayer.addTo(map);
29 | geoJSONTDLayer.addTo(map);
30 | }
31 |
32 | var map = L.map('map', {
33 | zoom: 14,
34 | fullscreenControl: true,
35 | timeDimensionControl: true,
36 | timeDimensionControlOptions: {
37 | timeSliderDragUpdate: true,
38 | loopButton: true,
39 | autoPlay: true,
40 | playerOptions: {
41 | transitionTime: 1000,
42 | loop: true
43 | }
44 | },
45 | timeDimension: true,
46 | center: [36.72, -4.43]
47 | });
48 |
49 | var osmLayer = L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
50 | attribution: '© OpenStreetMap contributors'
51 | });
52 | osmLayer.addTo(map);
53 |
54 | var oReq = new XMLHttpRequest();
55 | oReq.addEventListener("load", (function (xhr) {
56 | var response = xhr.currentTarget.response;
57 | var data = JSON.parse(response);
58 | addGeoJSONLayer(map, data);
59 | }));
60 | oReq.open('GET', 'data/track_bus699.geojson');
61 | oReq.send();
62 |
--------------------------------------------------------------------------------
/examples/js/example18.js:
--------------------------------------------------------------------------------
1 | // Set 1 hour earlier
2 | var endDate = new Date();
3 | endDate.setUTCHours(endDate.getUTCHours() - 1);
4 | endDate.setUTCMinutes(0, 0, 0);
5 |
6 | L.TimeDimension.Layer.VelocityLayer.Radar = L.TimeDimension.Layer.VelocityLayer.extend({
7 |
8 | initialize: function(options) {
9 | L.TimeDimension.Layer.VelocityLayer.prototype.initialize.call(this, options);
10 | this._socibDataSource = this.options.socibDataSource || null;
11 | this._apiKey = this.options.apiKey || null;
12 | this._proxy = this.options.proxy || null;
13 |
14 | // Update availableTimes from datasource metadata
15 | this._updateTimeDimension = this.options.updateTimeDimension || false;
16 | this._updateTimeDimensionMode = this.options.updateTimeDimensionMode || 'intersect'; // 'union' or 'replace'
17 | this._period = this.options.period || 'PT1H';
18 | this._setDefaultTime = this.options.setDefaultTime || false;
19 | this._endTime = this.options.endTime || null;
20 | this._metadataRequested = false;
21 | if (this._updateTimeDimension) {
22 | this._requestDataSourceMetadata();
23 | }
24 | },
25 |
26 | onAdd: function(map) {
27 | L.TimeDimension.Layer.VelocityLayer.prototype.onAdd.call(this, map);
28 | if (this._updateTimeDimension) {
29 | if (this._endTime === null) {
30 | this._requestDataSourceMetadata();
31 | } else {
32 | this._updateTimeDimensionAvailableTimes();
33 | }
34 | }
35 | },
36 |
37 | _constructQuery: function(time) {
38 | var startDate = new Date(time);
39 | var endDate = new Date(startDate.getTime());
40 | L.TimeDimension.Util.addTimeDuration(endDate, "PT30M", false);
41 | var timeParams =
42 | "&initial_datetime=" +
43 | startDate.toISOString().substring(0, 19) +
44 | "&end_datetime=" +
45 | endDate.toISOString().substring(0, 19);
46 | var url = this._baseURL + this._socibDataSource +
47 | "/data/?max_qc_value=3&standard_name=northward_sea_water_velocity&standard_name=eastward_sea_water_velocity&processing_level=L1&format=json" +
48 | timeParams;
49 | if (this._apiKey) {
50 | url = url + "&api_key=" + this._apiKey;
51 | }
52 | if (this._proxy) {
53 | url = this._proxy + "?url=" + encodeURIComponent(url);
54 | }
55 | return url;
56 | },
57 |
58 | _processLoadedData: function(data) {
59 | if (data.length === 0) {
60 | return [];
61 | }
62 | findVariable = function(standard_name, variable) {
63 | return variable.standard_name === standard_name;
64 | };
65 | var u = data[0].variables.find(findVariable.bind(this, "eastward_sea_water_velocity"));
66 | var v = data[0].variables.find(findVariable.bind(this, "northward_sea_water_velocity"));
67 | var lat = data[0].coordinates.latitude;
68 | var lon = data[0].coordinates.longitude;
69 | var time = data[0].coordinates.time.data;
70 |
71 | var u_header = {
72 | parameterUnit: u.units,
73 | parameterNumberName: u.standard_name,
74 | parameterNumber: 2,
75 | parameterCategory: 2,
76 | la1: lat.data[0],
77 | la2: lat.data[lat.data.length - 1],
78 | lo1: lon.data[0],
79 | lo2: lon.data[lon.data.length - 1],
80 | nx: lon.data.length,
81 | ny: lat.data.length,
82 | refTime: time
83 | };
84 | u_header["dx"] = (u_header["lo2"] - u_header["lo1"]) / u_header["nx"];
85 | u_header["dy"] = (u_header["la1"] - u_header["la2"]) / u_header["ny"];
86 |
87 | var v_header = {
88 | parameterUnit: v.units,
89 | parameterNumberName: v.standard_name,
90 | parameterNumber: 3, // northward-v
91 | parameterCategory: 2,
92 | la1: lat.data[0],
93 | la2: lat.data[lat.data.length - 1],
94 | lo1: lon.data[0],
95 | lo2: lon.data[lon.data.length - 1],
96 | nx: lon.data.length,
97 | ny: lat.data.length,
98 | refTime: time
99 | };
100 | v_header["dx"] = (v_header["lo2"] - v_header["lo1"]) / v_header["nx"];
101 | v_header["dy"] = (v_header["la1"] - v_header["la2"]) / v_header["ny"];
102 |
103 | return [
104 | {
105 | header: u_header,
106 | data: _.flatten(u.data[0])
107 | },
108 | {
109 | header: v_header,
110 | data: _.flatten(v.data[0])
111 | }
112 | ];
113 | },
114 |
115 | _setEndTime: function(endTime) {
116 | this._endTime = endTime;
117 | },
118 |
119 | _getDefaultTime: function() {
120 | return this._endTime;
121 | },
122 |
123 | _updateTimeDimensionAvailableTimes: function() {
124 | if (this._timeDimension && this._updateTimeDimension) {
125 | var startTime = new Date(this._timeDimension.getAvailableTimes()[0]);
126 | var times = L.TimeDimension.Util.explodeTimeRange(startTime, this._endTime, this._period);
127 | this._timeDimension.setAvailableTimes(times, this._updateTimeDimensionMode);
128 | if (this._setDefaultTime) {
129 | var defaultTime = this._getDefaultTime();
130 | if (defaultTime !== this._timeDimension.getCurrentTime()){
131 | this._timeDimension.setCurrentTime(this._getDefaultTime());
132 | }
133 | }
134 | }
135 | },
136 |
137 | _requestDataSourceMetadata: function() {
138 | if (this._metadataRequested) {
139 | return;
140 | }
141 | this._metadataRequested = true;
142 | var url = this._baseURL + this._socibDataSource + "/?";
143 | if (this._apiKey) {
144 | url = url + "&api_key=" + this._apiKey;
145 | }
146 | if (this._proxy) {
147 | url = this._proxy + "?url=" + encodeURIComponent(url);
148 | }
149 | var oReq = new XMLHttpRequest();
150 | oReq.addEventListener("load", (function(xhr) {
151 | var data = null;
152 | try {
153 | var response = xhr.currentTarget.response;
154 | data = JSON.parse(response);
155 | } catch(e) {
156 | console.log("Error parsing API response", e);
157 | }
158 | if (data !== null){
159 | var end_datetime = new Date(Date.parse(data['end_datetime']));
160 | this._setEndTime(end_datetime);
161 | this._updateTimeDimensionAvailableTimes();
162 | }
163 | }).bind(this));
164 | oReq.open("GET", url);
165 | oReq.send();
166 | },
167 |
168 | });
169 |
170 | L.timeDimension.layer.velocityLayer.radar = function(options) {
171 | return new L.TimeDimension.Layer.VelocityLayer.Radar(options);
172 | };
173 |
174 | var map = L.map("map", {
175 | zoom: 10,
176 | center: [38.65, 1.15],
177 | fullscreenControl: true,
178 | timeDimension: true,
179 | timeDimensionControl: true,
180 | timeDimensionOptions: {
181 | timeInterval: "P1M/" + endDate.toISOString(),
182 | period: "PT1H",
183 | currentTime: endDate.getTime()
184 | },
185 | timeDimensionControlOptions: {
186 | autoPlay: false,
187 | playerOptions: {
188 | minBufferReady: -1,
189 | transitionTime: 2000,
190 | loop: true
191 | }
192 | }
193 | });
194 |
195 |
196 | var GSHHS_h_L1 = L.tileLayer.wms(
197 | "https://gis.socib.es/geoserver/gwc/service/wms?", {
198 | layers: 'gshhs%3AGSHHS_h_L1',
199 | transparent: true,
200 | format: 'image/png'
201 | }
202 | );
203 |
204 | var baseLayers = {
205 | "Shoreline from GSHHG": GSHHS_h_L1
206 | };
207 |
208 | L.control.layers(baseLayers, {}).addTo(map);
209 | GSHHS_h_L1.addTo(map);
210 |
211 | var testVelocityRadarLayer = L.timeDimension.layer.velocityLayer.radar({
212 | baseURL: "https://api.socib.es/data-sources/",
213 | socibDataSource: "f8e2429729",
214 | updateTimeDimension: true,
215 | updateTimeDimensionMode: 'intersect',
216 | setDefaultTime: true,
217 | proxy: "server/proxy-api.php",
218 | velocityLayerOptions: {
219 | particleAge: 30
220 | }
221 | });
222 | testVelocityRadarLayer.addTo(map);
223 |
--------------------------------------------------------------------------------
/examples/js/example2.js:
--------------------------------------------------------------------------------
1 | var map = L.map('map', {
2 | zoom: 4.5,
3 | zoomDelta: 0.5,
4 | zoomSnap: 0.5,
5 | fullscreenControl: true,
6 | timeDimension: true,
7 | timeDimensionControl: true,
8 | timeDimensionOptions: {
9 | // times: "2014-12-01T06:00:00Z,2014-12-01T09:00:00Z,2014-12-01T12:00:00Z,2014-12-01T15:00:00Z,2014-12-01T18:00:00Z,2014-12-01T21:00:00Z,2014-12-02T00:00:00Z,2014-12-02T03:00:00Z,2014-12-02T06:00:00Z,2014-12-02T09:00:00Z,2014-12-02T12:00:00Z,2014-12-02T15:00:00Z,2014-12-02T18:00:00Z,2014-12-02T21:00:00Z,2014-12-03T00:00:00Z,2014-12-03T03:00:00Z,2014-12-03T06:00:00Z,2014-12-03T09:00:00Z,2014-12-03T12:00:00Z,2014-12-03T15:00:00Z,2014-12-03T18:00:00Z,2014-12-03T21:00:00Z,2014-12-04T00:00:00Z,2014-12-04T03:00:00Z,2014-12-04T06:00:00Z,2014-12-04T12:00:00Z,2014-12-04T18:00:00Z,2014-12-05T00:00:00Z,2014-12-05T06:00:00Z,2014-12-05T12:00:00Z,2014-12-05T18:00:00Z,2014-12-06T00:00:00Z,2014-12-06T06:00:00Z,2014-12-06T12:00:00Z,2014-12-06T18:00:00Z,2014-12-07T00:00:00Z,2014-12-07T06:00:00Z,2014-12-07T12:00:00Z,2014-12-07T18:00:00Z,2014-12-08T00:00:00Z,2014-12-08T06:00:00Z,2014-12-08T12:00:00Z,2014-12-08T18:00:00Z,2014-12-09T00:00:00Z,2014-12-09T06:00:00Z,2014-12-09T12:00:00Z,2014-12-09T18:00:00Z,2014-12-10T00:00:00Z,2014-12-10T06:00:00Z"
10 | },
11 | center: [45.3, 0.9],
12 | });
13 |
14 |
15 | // https://ogcie.iblsoft.com/metocean/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetCapabilities
16 | var testWMS = "https://ogcie.iblsoft.com/metocean/wms"
17 | L.tileLayer.wms(testWMS, {
18 | layers: 'foreground-lines',
19 | format: 'image/png',
20 | transparent: true,
21 | crs: L.CRS.EPSG4326
22 | }).addTo(map);
23 |
24 | var testLayer = L.tileLayer.wms(testWMS, {
25 | layers: 'gfs-temperature-isbl', // isobaric levels, or -agl for above ground levels
26 | format: 'image/png',
27 | transparent: true,
28 | opacity: 0.3,
29 | crs: L.CRS.EPSG4326,
30 | attribution: 'OGC MetOcean DWG Best Practice Example, IBL Software Engineering'
31 | });
32 | var proxy = 'server/proxy.php';
33 | var testTimeLayer = L.timeDimension.layer.wms(testLayer, {
34 | proxy: proxy,
35 | updateTimeDimension: true,
36 | });
37 | testTimeLayer.addTo(map);
38 |
39 | var testLegend = L.control({
40 | position: 'topright'
41 | });
42 | testLegend.onAdd = function(map) {
43 | var src = testWMS + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=gfs-temperature-isbl&STYLE=default";
44 | var div = L.DomUtil.create('div', 'info legend');
45 | div.innerHTML +=
46 | ' ';
47 | return div;
48 | };
49 | testLegend.addTo(map);
50 |
--------------------------------------------------------------------------------
/examples/js/example3.js:
--------------------------------------------------------------------------------
1 | var map = L.map('map', {
2 | zoom: 10,
3 | fullscreenControl: true,
4 | timeDimension: true,
5 | timeDimensionOptions: {
6 | timeInterval: "2015-09-01/2015-09-03",
7 | period: "PT1H",
8 | currentTime: Date.parse("2015-09-01T00:00:00Z")
9 | },
10 | timeDimensionControl: true,
11 | timeDimensionControlOptions: {
12 | autoPlay: true,
13 | loopButton: true,
14 | timeSteps: 1,
15 | playReverseButton: true,
16 | limitSliders: true,
17 | playerOptions: {
18 | buffer: 0,
19 | transitionTime: 250,
20 | loop: true,
21 | }
22 | },
23 | center: [38.705, 1.15],
24 | });
25 |
26 | L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
27 | attribution: '© OpenStreetMap contributors'
28 | }).addTo(map);
29 |
30 | var testWMS = "https://thredds.socib.es/thredds/wms/observational/hf_radar/hf_radar_ibiza-scb_codarssproc001_L1_agg/hf_radar_ibiza-scb_codarssproc001_L1_agg_best.ncd"
31 | var testLayer = L.tileLayer.wms(testWMS, {
32 | layers: 'sea_water_velocity',
33 | version: '1.3.0',
34 | format: 'image/png',
35 | transparent: true,
36 | styles: 'prettyvec/rainbow',
37 | markerscale: 15,
38 | markerspacing: 10,
39 | abovemaxcolor: "extend",
40 | belowmincolor: "extend",
41 | colorscalerange: "0,0.4",
42 | attribution: 'SOCIB HF RADAR | sea_water_velocity'
43 | });
44 | var proxy = 'server/proxy.php';
45 | var testTimeLayer = L.timeDimension.layer.wms(testLayer, {
46 | proxy: proxy,
47 | updateTimeDimension: true
48 | });
49 | testTimeLayer.addTo(map);
50 |
51 | var testLegend = L.control({
52 | position: 'topright'
53 | });
54 | testLegend.onAdd = function(map) {
55 | var src = testWMS + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=sea_water_velocity&PALETTE=rainbow&colorscalerange=0,0.4";
56 | var div = L.DomUtil.create('div', 'info legend');
57 | div.innerHTML +=
58 | ' ';
59 | return div;
60 | };
61 | testLegend.addTo(map);
62 |
63 | $('#dtp_start').datetimepicker({
64 | inline: true,
65 | value: new Date('2015-09-01'),
66 | format: "c"
67 | });
68 | $('#dtp_end').datetimepicker({
69 | inline: true,
70 | value: new Date('2015-09-03'),
71 | format: "c"
72 | });
73 |
74 | $("#btn_timerange").click(function(){
75 | var startTime = new Date($('#dtp_start').val());
76 | var endTime = new Date($('#dtp_end').val());
77 | var newAvailableTimes = L.TimeDimension.Util.explodeTimeRange(startTime, endTime, 'PT1H');
78 | map.timeDimension.setAvailableTimes(newAvailableTimes, 'replace');
79 | map.timeDimension.setCurrentTime(startTime);
80 | });
81 |
82 | $("#btn_limitrange").click(function(){
83 | var startTime = new Date($('#dtp_start').val());
84 | var endTime = new Date($('#dtp_end').val());
85 | map.timeDimension.setLowerLimit(startTime);
86 | map.timeDimension.setUpperLimit(endTime);
87 | map.timeDimension.setCurrentTime(startTime);
88 | });
--------------------------------------------------------------------------------
/examples/js/example4.js:
--------------------------------------------------------------------------------
1 | var endDate = new Date();
2 | endDate.setUTCMinutes(0, 0, 0);
3 |
4 | var map = L.map('map', {
5 | zoom: 7,
6 | fullscreenControl: true,
7 | center: [52.0, 3.50],
8 | timeDimension: true,
9 | timeDimensionControl: true,
10 | timeDimensionOptions: {
11 | timeInterval: "P2W/" + endDate.toISOString(),
12 | period: "PT5M"
13 | },
14 | timeDimensionControlOptions: {
15 | playerOptions: {
16 | transitionTime: 250,
17 | }
18 | }
19 | });
20 |
21 | L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
22 | attribution: '© OpenStreetMap contributors'
23 | }).addTo(map);
24 |
25 |
26 | // http://geoservices.knmi.nl/adaguc_portal/?srs=EPSG%3A28992&bbox=-47780.898876404506,300000,342780.8988764045,630000&service=http%253A%252F%252Fgeoservices.knmi.nl%252Fcgi-bin%252FRADNL_OPER_R___25PCPRR_L3.cgi%253F&layer=RADNL_OPER_R___25PCPRR_L3_COLOR%2524image%252Fpng%2524true%2524default%25241%25240&selected=0&dims=time$current&baselayers=world_raster$nl_world_line
27 | var testWMS = "https://geoservices.knmi.nl/cgi-bin/RADNL_OPER_R___25PCPRR_L3.cgi"
28 | var testLayer = L.nonTiledLayer.wms(testWMS, {
29 | layers: 'RADNL_OPER_R___25PCPRR_L3_COLOR',
30 | format: 'image/png',
31 | transparent: true,
32 | attribution: 'KNMI'
33 | });
34 | var testTimeLayer = L.timeDimension.layer.wms(testLayer);
35 | testTimeLayer.addTo(map);
36 |
37 | var testLegend = L.control({
38 | position: 'topright'
39 | });
40 | testLegend.onAdd = function(map) {
41 | var src = testWMS + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=RADNL_OPER_R___25PCPRR_L3_COLOR&format=image/png&STYLE=default";
42 | var div = L.DomUtil.create('div', 'info legend');
43 | div.style.width = '65px';
44 | div.style.height = '280px';
45 | div.style['background-image'] = 'url(' + src + ')';
46 | return div;
47 | };
48 | testLegend.addTo(map);
49 |
--------------------------------------------------------------------------------
/examples/js/example5.js:
--------------------------------------------------------------------------------
1 |
2 | var map = L.map('map', {
3 | zoom: 2,
4 | fullscreenControl: true,
5 | timeDimension: true,
6 | timeDimensionOptions:{
7 | timeInterval: "2006-01/2099-12",
8 | period: "P1M"
9 | },
10 | timeDimensionControl: true,
11 | timeDimensionControlOptions:{
12 | timeSteps: 12
13 | },
14 | center: [20.0, 0.0],
15 | });
16 |
17 | L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
18 | attribution: '© OpenStreetMap contributors'
19 | }).addTo(map);
20 |
21 | /*
22 | var proxy = 'server/proxy.php';
23 | var testWMS = "http://data2-glues.ufz.de/thredds/wms/pik_wcrp_cmip3/ncar_pcm1_sresb1_2006-2099_tmp.nc"
24 | var testLayer = L.tileLayer.wms(testWMS, {
25 | layers: 'tmp',
26 | format: 'image/png',
27 | transparent: true,
28 | attribution: 'PIK '
29 | });
30 | var testTimeLayer = L.timeDimension.layer.wms(testLayer, {proxy: proxy});
31 | testTimeLayer.addTo(map);
32 |
33 | var testLegend = L.control({
34 | position: 'topright'
35 | });
36 | testLegend.onAdd = function(map) {
37 | var src = testWMS + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=tmp&PALETTE=tmp";
38 | var div = L.DomUtil.create('div', 'info legend');
39 | div.innerHTML +=
40 | ' ';
41 | return div;
42 | };
43 | testLegend.addTo(map);
44 | */
45 |
46 |
--------------------------------------------------------------------------------
/examples/js/example6.js:
--------------------------------------------------------------------------------
1 | var startDate = new Date();
2 | startDate.setUTCHours(0, 0, 0, 0);
3 |
4 | var map = L.map('map', {
5 | zoom: 8,
6 | fullscreenControl: true,
7 | timeDimensionControl: true,
8 | timeDimensionControlOptions: {
9 | position: 'bottomleft',
10 | playerOptions: {
11 | transitionTime: 1000,
12 | }
13 | },
14 | timeDimension: true,
15 | timeDimensionOptions: {
16 | timeInterval: "2020-09-25/2020-09-30",
17 | period: "PT1H",
18 | currentTime: Date.parse("2020-09-25T12:00:00Z")
19 | },
20 | center: [39.3, 2.9]
21 | });
22 |
23 | var sapoWMS = "https://thredds.socib.es/thredds/wms/operational_models/oceanographical/wave/model_run_aggregation/sapo_ib/sapo_ib_best.ncd";
24 | var sapoHeightLayer = L.tileLayer.wms(sapoWMS, {
25 | layers: 'significant_wave_height',
26 | format: 'image/png',
27 | transparent: true,
28 | colorscalerange: '0,3',
29 | abovemaxcolor: "extend",
30 | belowmincolor: "extend",
31 | numcolorbands: 100,
32 | styles: 'areafill/scb_bugnylorrd'
33 | // styles: 'areafill/scb_greens'
34 | });
35 |
36 | var sapoMeanDirectionLayer = L.nonTiledLayer.wms(sapoWMS, {
37 | layers: 'average_wave_direction',
38 | format: 'image/png',
39 | transparent: true,
40 | colorscalerange: '1,1',
41 | abovemaxcolor: "extend",
42 | belowmincolor: "extend",
43 | markerscale: 15,
44 | markerspacing: 12,
45 | markerclipping: true,
46 | styles: 'prettyvec/greyscale'
47 | });
48 |
49 | var sapoPeakDirectionLayer = L.nonTiledLayer.wms(sapoWMS, {
50 | layers: 'direction_of_the_peak_of_the_spectrum',
51 | format: 'image/png',
52 | transparent: true,
53 | colorscalerange: '0,2',
54 | abovemaxcolor: "extend",
55 | belowmincolor: "extend",
56 | markerscale: 15,
57 | markerspacing: 12,
58 | markerclipping: true,
59 | styles: 'prettyvec/greyscale'
60 | });
61 |
62 | var proxy = 'server/proxy.php';
63 | var sapoHeightTimeLayer = L.timeDimension.layer.wms(sapoHeightLayer, {
64 | proxy: proxy,
65 | updateTimeDimension: false
66 | });
67 |
68 | var sapoMeanDirectionTimeLayer = L.timeDimension.layer.wms(sapoMeanDirectionLayer, {
69 | proxy: proxy
70 | });
71 | var sapoPeakDirectionTimeLayer = L.timeDimension.layer.wms(sapoPeakDirectionLayer, {
72 | proxy: proxy
73 | });
74 |
75 | var sapoLegend = L.control({
76 | position: 'bottomright'
77 | });
78 | sapoLegend.onAdd = function(map) {
79 | var src = sapoWMS + "?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetLegendGraphic&LAYER=significant_wave_height&colorscalerange=0,3&PALETTE=scb_bugnylorrd&numcolorbands=100&transparent=TRUE";
80 | var div = L.DomUtil.create('div', 'info legend');
81 | div.innerHTML +=
82 | ' ';
83 | return div;
84 | };
85 |
86 | var sapoMeanDirectionLegend = L.control({
87 | position: 'bottomright'
88 | });
89 | sapoMeanDirectionLegend.onAdd = function(map) {
90 | var div = L.DomUtil.create('div', 'info legend');
91 | div.innerHTML += ' mean direction';
92 | return div;
93 | };
94 |
95 | var sapoPeakDirectionLegend = L.control({
96 | position: 'bottomright'
97 | });
98 | sapoPeakDirectionLegend.onAdd = function(map) {
99 | var div = L.DomUtil.create('div', 'info legend');
100 | div.innerHTML += ' peak direction';
101 | return div;
102 | };
103 |
104 | var overlayMaps = {
105 | "SAPO - significant wave height": sapoHeightTimeLayer,
106 | "SAPO - average wave direction": sapoMeanDirectionTimeLayer,
107 | "SAPO - direction of the peak": sapoPeakDirectionTimeLayer
108 | };
109 |
110 | map.on('overlayadd', function(eventLayer) {
111 | if (eventLayer.name == 'SAPO - significant wave height') {
112 | sapoLegend.addTo(this);
113 | } else if (eventLayer.name == 'SAPO - average wave direction') {
114 | sapoMeanDirectionLegend.addTo(this);
115 | } else if (eventLayer.name == 'SAPO - direction of the peak') {
116 | sapoPeakDirectionLegend.addTo(this);
117 | }
118 | });
119 |
120 | map.on('overlayremove', function(eventLayer) {
121 | if (eventLayer.name == 'SAPO - significant wave height') {
122 | map.removeControl(sapoLegend);
123 | } else if (eventLayer.name == 'SAPO - average wave direction') {
124 | map.removeControl(sapoMeanDirectionLegend);
125 | } else if (eventLayer.name == 'SAPO - direction of the peak') {
126 | map.removeControl(sapoPeakDirectionLegend);
127 | }
128 | });
129 |
130 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
131 | L.control.layers(baseLayers, overlayMaps).addTo(map);
132 |
133 | sapoHeightTimeLayer.addTo(map);
134 | sapoPeakDirectionTimeLayer.addTo(map);
135 | sapoMeanDirectionTimeLayer.addTo(map);
--------------------------------------------------------------------------------
/examples/js/example7.js:
--------------------------------------------------------------------------------
1 | var currentTime = new Date();
2 | currentTime.setUTCHours(0, 0, 0, 0);
3 | var endDate = new Date(currentTime.getTime());
4 | L.TimeDimension.Util.addTimeDuration(endDate, "P3D", true);
5 |
6 | var map = L.map('map', {
7 | zoom: 8,
8 | center: [39.4, 2.5],
9 | fullscreenControl: true,
10 | timeDimensionControl: true,
11 | timeDimension: true,
12 | timeDimensionOptions: {
13 | timeInterval: "P1M/" + endDate.toISOString(),
14 | period: "PT6H",
15 | currentTime: currentTime.getTime()
16 | },
17 | timeDimensionControlOptions: {
18 | playerOptions: {
19 | loop: true,
20 | transitionTime: 1500,
21 | buffer: 10
22 | }
23 | }
24 | });
25 |
26 | var wmopWMS = "https://thredds.socib.es/thredds/wms/operational_models/oceanographical/hydrodynamics/model_run_aggregation/wmop_surface/wmop_surface_best.ncd";
27 | var wmopTemperatureLayer = L.tileLayer.wms(wmopWMS, {
28 | layers: 'temp',
29 | format: 'image/png',
30 | transparent: true,
31 | abovemaxcolor: "extend",
32 | belowmincolor: "extend",
33 | numcolorbands: 40,
34 | styles: 'boxfill/sst_36',
35 | zIndex: 1,
36 | });
37 |
38 | var wmopTemperatureContourLayer = L.tileLayer.wms(wmopWMS, {
39 | layers: 'temp',
40 | format: 'image/png',
41 | transparent: true,
42 | numcontours: 11,
43 | styles: 'contour/sst_36',
44 | zIndex: 10,
45 | });
46 |
47 | var wmopSalinityLayer = L.tileLayer.wms(wmopWMS, {
48 | layers: 'salt',
49 | format: 'image/png',
50 | transparent: true,
51 | abovemaxcolor: "extend",
52 | belowmincolor: "extend",
53 | numcolorbands: 40,
54 | styles: 'boxfill/mpl_rdbu_r'
55 | });
56 |
57 | var wmopSalinityContourLayer = L.tileLayer.wms(wmopWMS, {
58 | layers: 'salt',
59 | format: 'image/png',
60 | transparent: true,
61 | numcontours: 11,
62 | styles: 'contour/sst_36'
63 | });
64 |
65 | var wmopVelocityLayer = L.nonTiledLayer.wms(wmopWMS, {
66 | layers: 'sea_surface_velocity',
67 | format: 'image/png',
68 | transparent: true,
69 | colorscalerange: '0,3',
70 | abovemaxcolor: "extend",
71 | belowmincolor: "extend",
72 | markerscale: 10,
73 | markerspacing: 8,
74 | styles: 'prettyvec/greyscale'
75 | });
76 |
77 | var proxy = 'server/proxy.php';
78 | var wmopVelocityTimeLayer = L.timeDimension.layer.wms(wmopVelocityLayer, {proxy: proxy, updateTimeDimension: true});
79 | var overlayMaps = {
80 | "WMOP - Velocity": wmopVelocityTimeLayer
81 | };
82 |
83 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
84 | var layersControl = L.control.layers(baseLayers, overlayMaps);
85 | layersControl.addTo(map);
86 |
87 | wmopVelocityTimeLayer.addTo(map);
88 |
89 | var getLayerMinMax = function(layer, callback) {
90 | var url = wmopWMS + '?service=WMS&version=1.1.1&request=GetMetadata&item=minmax';
91 | url = url + '&layers=' + layer.options.layers;
92 | url = url + '&srs=EPSG:4326';
93 | var size = map.getSize();
94 | url = url + '&BBox=' + map.getBounds().toBBoxString();
95 | url = url + '&height=' + size.y;
96 | url = url + '&width=' + size.x;
97 | url = proxy + '?url=' + encodeURIComponent(url);
98 |
99 | var oReq = new XMLHttpRequest();
100 | oReq.addEventListener("load", (function(xhr) {
101 | var response = xhr.currentTarget.response;
102 | var data = JSON.parse(response);
103 | var range = data.max - data.min;
104 | var min = Math.floor(data.min) - 1;
105 | var max = Math.floor(data.max + 2);
106 | layer.options.colorscalerange = min + "," + max;
107 | layer.wmsParams.colorscalerange = min + "," + max;
108 | if (callback !== undefined) {
109 | callback();
110 | }
111 | }));
112 | oReq.open("GET", url);
113 | oReq.send();
114 | };
115 |
116 | var addTimeDimensionLayer = function(layer, name, addToMap){
117 | var timeDimensionLayer = L.timeDimension.layer.wms(layer, {proxy: proxy});
118 | layersControl.addOverlay(timeDimensionLayer, name);
119 | if (addToMap)
120 | timeDimensionLayer.addTo(map);
121 | }
122 |
123 | getLayerMinMax(wmopTemperatureLayer, function(){
124 | addTimeDimensionLayer(wmopTemperatureLayer, 'WMOP - Temperature', true);
125 | wmopTemperatureContourLayer.wmsParams.colorscalerange = wmopTemperatureLayer.wmsParams.colorscalerange;
126 | wmopTemperatureContourLayer.options.colorscalerange = wmopTemperatureLayer.wmsParams.colorscalerange;
127 | addTimeDimensionLayer(wmopTemperatureContourLayer, 'WMOP - Temperature (Contour)', true);
128 | });
129 | getLayerMinMax(wmopSalinityLayer, function(){
130 | addTimeDimensionLayer(wmopSalinityLayer, 'WMOP - Salinity', false);
131 | wmopSalinityContourLayer.wmsParams.colorscalerange = wmopSalinityLayer.wmsParams.colorscalerange;
132 | wmopSalinityContourLayer.options.colorscalerange = wmopSalinityLayer.wmsParams.colorscalerange;
133 | addTimeDimensionLayer(wmopSalinityContourLayer, 'WMOP - Salinity (Contour)', false);
134 | });
135 |
--------------------------------------------------------------------------------
/examples/js/example8.js:
--------------------------------------------------------------------------------
1 | L.TimeDimension.Layer.DrifterDeployment = L.TimeDimension.Layer.GeoJson.extend({
2 |
3 | initialize: function(layer, options) {
4 | layer = L.geoJson();
5 | L.TimeDimension.Layer.GeoJson.prototype.initialize.call(this, layer, options);
6 | this._id_platform = this.options.id_platform;
7 | this._id_deployment = this.options.id_deployment;
8 | },
9 |
10 | onAdd: function(map) {
11 | L.TimeDimension.Layer.prototype.onAdd.call(this, map);
12 | var proxy = "server/proxy-datadiscovery.php";
13 | var url = "https://apps.socib.es/DataDiscovery/deployment-info?" +
14 | "id_platform=" + this._id_platform + "&id_deployment=" + this._id_deployment +
15 | "&sample=50";
16 | url = proxy + '?url=' + encodeURIComponent(url);
17 | var oReq = new XMLHttpRequest();
18 | oReq.addEventListener("load", (function(xhr) {
19 | var response = xhr.currentTarget.response;
20 | var data = JSON.parse(response);
21 | this._baseLayer = this._createLayer(data);
22 | this._onReadyBaseLayer();
23 | }.bind(this)));
24 | oReq.open("GET", url);
25 | oReq.send();
26 | },
27 |
28 | _createLayer: function(featurecollection) {
29 | // lastPosition
30 | this._color = this._pickRandomColor();
31 |
32 |
33 | this._icon = L.icon({
34 | iconUrl: 'img/surface-drifter.png',
35 | iconSize: [20, 20],
36 | iconAnchor: [10, 20]
37 | });
38 |
39 | var layer = L.geoJson(null, {
40 | pointToLayer: (function(feature, latLng) {
41 | if (feature.properties.hasOwnProperty('last')) {
42 | return new L.Marker(latLng, {
43 | icon: this._icon
44 | });
45 | }
46 | return L.circleMarker(latLng, {
47 | fillColor: this._color,
48 | fillOpacity: 0.5,
49 | stroke: false,
50 | radius: 3
51 | });
52 | }).bind(this),
53 | style: (function(feature) {
54 | return {
55 | "color": this._color,
56 | "weight": 2,
57 | "opacity": 1
58 | };
59 | }).bind(this)
60 | });
61 | if (!featurecollection.features) {
62 | return layer;
63 | }
64 | layer.addData(featurecollection.features[0]);
65 | for (var i = 1, l = featurecollection.features.length; i < l; i++) {
66 | var point = featurecollection.features[i];
67 | // fix Point
68 | if (point.geometry.type == 'point') {
69 | point.geometry.type = 'Point';
70 | }
71 | layer.addData(point);
72 | }
73 | // save last point
74 | this._lastPoint = featurecollection.features[featurecollection.features.length - 1];
75 | return layer;
76 | },
77 |
78 | _pickRandomColor: function() {
79 | var colors = ["#00aaff", "#ffaa00", "#ff00aa", "#ff0000", "#00ffaa", "#00ff00", "#0000ff", "#aa00ff", "#aaff00"];
80 | var index = Math.floor(Math.random() * colors.length);
81 | return colors[index];
82 | },
83 |
84 | _addDeploymentTrajectory: function(layer, trajectory_feature) {
85 | // remove the old one
86 | if (this._deploymentTrajectory) {
87 | layer.removeLayer(this._deploymentTrajectory);
88 | }
89 | var getStyle = (function(feature) {
90 | return {
91 | "color": this._color,
92 | "weight": 2,
93 | "opacity": 1
94 | };
95 | }).bind(this);
96 | var deploymentTrajectory = L.geoJson(trajectory_feature, {
97 | style: getStyle
98 | });
99 | // deploymentTrajectory.on('click', deployment.popupFunction.bind(this, deployment, undefined));
100 | deploymentTrajectory.addTo(layer);
101 | // save for later
102 | this._deploymentTrajectory = deploymentTrajectory;
103 | },
104 |
105 | _addDeploymenPoint: function(layer, point, isLastPoint) {
106 | var deploymentPoint = L.geoJson(point, {
107 | pointToLayer: (function(feature, latLng) {
108 | if (isLastPoint) {
109 | return new L.Marker(latLng, {
110 | icon: this._icon
111 | });
112 | } else {
113 | return L.circleMarker(latLng, {
114 | fillColor: this._color,
115 | fillOpacity: 0.5,
116 | stroke: false,
117 | radius: 3
118 | });
119 | }
120 | }).bind(this)
121 | });
122 | // deploymentPoint.on('click', deployment.popupFunction.bind(this, deployment, point));
123 | deploymentPoint.addTo(layer);
124 | if (isLastPoint)
125 | this._lastPoint = deploymentPoint;
126 | }
127 |
128 |
129 | });
130 |
131 | L.timeDimension.layer.drifterDeployment = function(options) {
132 | return new L.TimeDimension.Layer.DrifterDeployment(null, options);
133 | };
134 |
135 |
136 |
137 | var map = L.map('map', {
138 | zoom: 10,
139 | fullscreenControl: true,
140 | timeDimension: true,
141 | timeDimensionOptions: {
142 | timeInterval: "2014-09-30/2014-10-30",
143 | period: "PT1H",
144 | currentTime: Date.parse("2014-09-30T09:00:00Z")
145 | },
146 | timeDimensionControl: true,
147 | timeDimensionControlOptions: {
148 | autoPlay: true,
149 | playerOptions: {
150 | buffer: 10,
151 | transitionTime: 500,
152 | loop: true,
153 | }
154 | },
155 | center: [38.705, 1.15],
156 | });
157 |
158 | var Esri_WorldImagery = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
159 | attribution: 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, ' +
160 | 'AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
161 | });
162 |
163 | var baseLayers = {
164 | "ESRI Satellite": Esri_WorldImagery,
165 | };
166 |
167 | L.control.layers(baseLayers, {}).addTo(map);
168 | Esri_WorldImagery.addTo(map);
169 |
170 | var testWMS = "https://thredds.socib.es/thredds/wms/observational/hf_radar/hf_radar_ibiza-scb_codarssproc001_L1_agg/hf_radar_ibiza-scb_codarssproc001_L1_agg_best.ncd"
171 | var testLayer = L.nonTiledLayer.wms(testWMS, {
172 | layers: 'sea_water_velocity',
173 | format: 'image/png',
174 | transparent: true,
175 | styles: 'prettyvec/mpl_reds',
176 | markerscale: 15,
177 | markerspacing: 6,
178 | numcolorbands: 10,
179 | abovemaxcolor: "extend",
180 | belowmincolor: "extend",
181 | colorscalerange: "0,0.4",
182 | attribution: 'SOCIB HF RADAR'
183 | });
184 | var proxy = 'server/proxy.php';
185 | var testTimeLayer = L.timeDimension.layer.wms(testLayer, {
186 | proxy: proxy,
187 | updateTimeDimension: true,
188 | });
189 | testTimeLayer.addTo(map);
190 |
191 | var testLegend = L.control({
192 | position: 'topright'
193 | });
194 | testLegend.onAdd = function(map) {
195 | var src = testWMS + "?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetLegendGraphic&LAYER=sea_water_velocity&PALETTE=mpl_reds&numcolorbands=10&colorscalerange=0,0.4";
196 | var div = L.DomUtil.create('div', 'info legend');
197 | div.innerHTML +=
198 | ' ';
199 | return div;
200 | };
201 | testLegend.addTo(map);
202 |
203 | var drifters = [
204 | [243, 416],
205 | [244, 417],
206 | [245, 418],
207 | [246, 419],
208 | [248, 421],
209 | [249, 422],
210 | [162, 423],
211 | [161, 424],
212 | [250, 425],
213 | [253, 427],
214 | [252, 428]
215 | ];
216 |
217 | for (var i = 0, l = drifters.length; i < l; i++) {
218 | var drifterLayer = L.timeDimension.layer.drifterDeployment({
219 | id_platform: drifters[i][0],
220 | id_deployment: drifters[i][1],
221 | duration: "P1D",
222 | addlastPoint: true
223 | });
224 | drifterLayer.addTo(map);
225 | }
--------------------------------------------------------------------------------
/examples/js/example9.js:
--------------------------------------------------------------------------------
1 | var startDate = new Date();
2 | startDate.setUTCHours(0, 0, 0, 0);
3 |
4 | var map = L.map('map', {
5 | zoom: 12,
6 | fullscreenControl: true,
7 | center: [39.3, 4]
8 | });
9 |
10 | // start of TimeDimension manual instantiation
11 | var timeDimension = new L.TimeDimension({
12 | period: "PT5M",
13 | });
14 | // helper to share the timeDimension object between all layers
15 | map.timeDimension = timeDimension;
16 | // otherwise you have to set the 'timeDimension' option on all layers.
17 |
18 | var player = new L.TimeDimension.Player({
19 | transitionTime: 100,
20 | loop: false,
21 | startOver:true
22 | }, timeDimension);
23 |
24 | var timeDimensionControlOptions = {
25 | player: player,
26 | timeDimension: timeDimension,
27 | position: 'bottomleft',
28 | autoPlay: true,
29 | minSpeed: 1,
30 | speedStep: 0.5,
31 | maxSpeed: 15,
32 | timeSliderDragUpdate: true
33 | };
34 |
35 | var timeDimensionControl = new L.Control.TimeDimension(timeDimensionControlOptions);
36 | map.addControl(timeDimensionControl);
37 |
38 | var icon = L.icon({
39 | iconUrl: 'img/running.png',
40 | iconSize: [22, 22],
41 | iconAnchor: [5, 25]
42 | });
43 |
44 | var customLayer = L.geoJson(null, {
45 | pointToLayer: function (feature, latLng) {
46 | if (feature.properties.hasOwnProperty('last')) {
47 | return new L.Marker(latLng, {
48 | icon: icon
49 | });
50 | }
51 | return L.circleMarker(latLng);
52 | }
53 | });
54 |
55 | var gpxLayer = omnivore.gpx('data/running_mallorca.gpx', null, customLayer).on('ready', function() {
56 | map.fitBounds(gpxLayer.getBounds(), {
57 | paddingBottomRight: [40, 40]
58 | });
59 | });
60 |
61 | var gpxTimeLayer = L.timeDimension.layer.geoJson(gpxLayer, {
62 | updateTimeDimension: true,
63 | addlastPoint: true,
64 | waitForReady: true
65 | });
66 |
67 | var kmlLayer = omnivore.kml('data/easy_currents_track.kml');
68 | var kmlTimeLayer = L.timeDimension.layer.geoJson(kmlLayer, {
69 | updateTimeDimension: true,
70 | addlastPoint: true,
71 | waitForReady: true
72 | });
73 |
74 |
75 | var overlayMaps = {
76 | "GPX Layer": gpxTimeLayer,
77 | "KML Layer": kmlTimeLayer
78 | };
79 | var baseLayers = getCommonBaseLayers(map); // see baselayers.js
80 | L.control.layers(baseLayers, overlayMaps).addTo(map);
81 | gpxTimeLayer.addTo(map);
--------------------------------------------------------------------------------
/examples/js/extras/leaflet.timedimension.circlelabelmarker.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.TimeDimension.CircleLabelMarker: circleMarker + divIcon containing
3 | * the numerical value of the baseLayer (from a THREDDS server).
4 | */
5 |
6 | L.TimeDimension.Layer.CircleLabelMarker = L.TimeDimension.Layer.extend({
7 |
8 | initialize: function(layer, options) {
9 | L.TimeDimension.Layer.prototype.initialize.call(this, layer, options);
10 | this._serieId = this.options.serieId;
11 | this._dataLayer = this.options.dataLayer;
12 | this._labelMarker = null;
13 | this._position = layer.getLatLng();
14 | this._proxy = this.options.proxy || null;
15 | this._data = [];
16 | },
17 |
18 | addTo: function(map) {
19 | map.addLayer(this);
20 | map.addLayer(this._baseLayer);
21 | var time = this._timeDimension.getCurrentTime();
22 | if (!this._existsValueForTime(time)){
23 | this._loadDataForTime(time, (function() {
24 | this._update();
25 | }).bind(this));
26 | }else{
27 | this._update();
28 | }
29 |
30 | return this;
31 | },
32 |
33 | eachLayer: function(method, context) {
34 | if (this._labelMarker) {
35 | method.call(context, this._labelMarker);
36 | }
37 | return L.TimeDimension.Layer.prototype.eachLayer.call(this, method, context);
38 | },
39 |
40 | _onNewTimeLoading: function(ev) {
41 | if (this._existsValueForTime(ev.time)) {
42 | this.fire('timeload', {
43 | time: ev.time
44 | });
45 | } else {
46 | this._loadDataForTime(ev.time, (function() {
47 | this.fire('timeload', {
48 | time: ev.time
49 | });
50 | }).bind(this));
51 | }
52 | return;
53 | },
54 |
55 | isReady: function(time) {
56 | return this._existsValueForTime(time);
57 | },
58 |
59 | _update: function() {
60 | if (!this._map)
61 | return;
62 | var time = this._timeDimension.getCurrentTime();
63 | var value = this._getValueForTime(time);
64 | if (value && !isNaN(value)) {
65 | value = value.toFixed(2);
66 | }else{
67 | value = '';
68 | }
69 | if (this._labelMarker) {
70 | this._map.removeLayer(this._labelMarker);
71 | delete this._labelMarker;
72 | }
73 | var icon = L.divIcon({
74 | className: 'marker-label-icon',
75 | html: value,
76 | iconSize: [40, 15],
77 | iconAnchor: [-8, 12],
78 | });
79 | this._labelMarker = L.marker(this._position, {
80 | icon: icon
81 | });
82 | this._labelMarker.addTo(this._map);
83 | return true;
84 | },
85 |
86 | _getValueForTime: function(time) {
87 | if (this._dataLayer && this._dataLayer.chart && this._serieId) {
88 | var data = this._dataLayer.chart.get(this._serieId).options.data;
89 | for (var i = 0, l = data.length; i < l; i++) {
90 | if (data[i][0] == time) {
91 | return data[i][1];
92 | } else if (data[i][0] < time) {
93 | break;
94 | }
95 | }
96 | }
97 | for (var i = 0, l = this._data.length; i < l; i++) {
98 | if (this._data[i][0] == time) {
99 | return this._data[i][1];
100 | }
101 | }
102 | return null;
103 | },
104 |
105 | _existsValueForTime: function(time) {
106 | if (this._dataLayer && this._dataLayer.chart && this._serieId) {
107 | var data = this._dataLayer.chart.get(this._serieId).options.data;
108 | for (var i = 0, l = data.length; i < l; i++) {
109 | if (data[i][0] == time) {
110 | return true;
111 | } else if (data[i][0] < time) {
112 | break;
113 | }
114 | }
115 | }
116 | for (var i = 0, l = this._data.length; i < l; i++) {
117 | if (this._data[i][0] == time) {
118 | return true;
119 | }
120 | }
121 | return false;
122 | },
123 |
124 | _loadDataForTime: function(time, callback) {
125 | if (!this._dataLayer || !this._map || !this._map.getBounds().contains(this._position)){
126 | if (callback !== undefined) {
127 | callback(null);
128 | }
129 | return;
130 | }
131 | var point = this._map.latLngToContainerPoint(this._position);
132 | var url = this._dataLayer.getURL() + '?SERVICE=WMS&VERSION=1.1.1&REQUEST=GetFeatureInfo&SRS=EPSG:4326';
133 | url = url + '&LAYER=' + this._dataLayer.wmsParams.layers;
134 | url = url + '&QUERY_LAYERS=' + this._dataLayer.wmsParams.layers;
135 | url = url + '&X=' + point.x + '&Y=' + point.y + '&I=' + point.x + '&J=' + point.y;
136 | var size = this._map.getSize();
137 | url = url + '&BBox=' + this._map.getBounds().toBBoxString();
138 | url = url + '&WIDTH=' + size.x + '&HEIGHT=' + size.y;
139 | url = url + '&INFO_FORMAT=text/xml';
140 | var url_without_time = url;
141 | url = url + '&TIME=' + new Date(time).toISOString();
142 |
143 | if (this._proxy) url = this._proxy + '?url=' + encodeURIComponent(url);
144 |
145 | var oReq = new XMLHttpRequest();
146 | oReq.addEventListener("load", (function(xhr) {
147 | var data = xhr.currentTarget.responseXML;
148 | var result = null;
149 | data.querySelectorAll('FeatureInfo').forEach(function(fi) {
150 | var this_data = fi.querySelector('value').textContent;
151 | try {
152 | this_data = parseFloat(this_data);
153 | } catch (e) {
154 | this_data = null;
155 | }
156 | result = this_data;
157 | });
158 | this._data.push([time, result]);
159 | if (callback !== undefined) {
160 | callback(result);
161 | }
162 | }).bind(this));
163 | oReq.overrideMimeType('application/xml');
164 | oReq.open("GET", url);
165 | oReq.send();
166 | }
167 | });
168 |
169 | L.timeDimension.layer.circleLabelMarker = function(layer, options) {
170 | return new L.TimeDimension.Layer.CircleLabelMarker(layer, options);
171 | };
--------------------------------------------------------------------------------
/examples/js/extras/leaflet.timedimension.velocitylayer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.TimeDimension.Layer.VelocityLayer: TimeDimension for VelocityLayer
3 | */
4 | Date.prototype.format = function(mask, utc) {
5 | return dateFormat(this, mask, utc);
6 | };
7 |
8 | if (!Array.prototype.find) {
9 | Array.prototype.find = function(predicate) {
10 | if (this === null) {
11 | throw new TypeError("Array.prototype.find called on null or undefined");
12 | }
13 | if (typeof predicate !== "function") {
14 | throw new TypeError("predicate must be a function");
15 | }
16 | var list = Object(this);
17 | var length = list.length >>> 0;
18 | var thisArg = arguments[1];
19 | var value;
20 |
21 | for (var i = 0; i < length; i++) {
22 | value = list[i];
23 | if (predicate.call(thisArg, value, i, list)) {
24 | return value;
25 | }
26 | }
27 | return undefined;
28 | };
29 | }
30 |
31 | L.CustomVelocityLayer = L.VelocityLayer.extend({
32 | options: {
33 | displayValues: true,
34 | displayOptions: {
35 | velocityType: 'GBR Water',
36 | displayPosition: 'bottomleft',
37 | displayEmptyString: 'No currents data'
38 | },
39 | data: [],
40 | maxVelocity: 0.3,
41 | velocityScale: 0.1 // arbitrary default 0.005
42 | },
43 |
44 | initialize: function(options) {
45 | L.setOptions(this, options);
46 | L.VelocityLayer.prototype.initialize.call(this, this.options);
47 | }
48 | });
49 |
50 | L.customVelocityLayer = function(options) {
51 | return new L.CustomVelocityLayer(options);
52 | };
53 |
54 | L.TimeDimension.Layer.VelocityLayer = L.TimeDimension.Layer.extend({
55 |
56 | initialize: function(options) {
57 | var layer = new L.customVelocityLayer(
58 | options.velocityLayerOptions || {}
59 | );
60 | L.TimeDimension.Layer.prototype.initialize.call(this, layer, options);
61 | this._currentLoadedTime = 0;
62 | this._currentTimeData = [];
63 | this._baseURL = this.options.baseURL || null;
64 | },
65 |
66 | onAdd: function(map) {
67 | L.TimeDimension.Layer.prototype.onAdd.call(this, map);
68 | if (this._timeDimension) {
69 | this._getDataForTime(this._timeDimension.getCurrentTime());
70 | }
71 | },
72 |
73 | _onNewTimeLoading: function(ev) {
74 | this._getDataForTime(ev.time);
75 | return;
76 | },
77 |
78 | isReady: function(time) {
79 | return (this._currentLoadedTime == time);
80 | },
81 |
82 | _update: function() {
83 | if (this._currentTimeData && this._currentTimeData.length > 0) {
84 | this._map.addLayer(this._baseLayer);
85 | this._baseLayer.setData(this._currentTimeData);
86 | } else {
87 | this._map.removeLayer(this._baseLayer);
88 | }
89 |
90 | return true;
91 | },
92 |
93 | _getDataForTime: function(time) {
94 | if (!this._baseURL || !this._map) {
95 | return;
96 | }
97 | var url = this._constructQuery(time);
98 | var oReq = new XMLHttpRequest();
99 | oReq.addEventListener("load", (function(xhr) {
100 | var data = [];
101 | try {
102 | var response = xhr.currentTarget.response;
103 | data = JSON.parse(response);
104 | } catch(e) {
105 | console.log("Error parsing API response", e);
106 | }
107 | delete this._currentTimeData;
108 | this._currentTimeData = this._processLoadedData(data);
109 | this._currentLoadedTime = time;
110 | if (this._timeDimension && time == this._timeDimension.getCurrentTime() && !this._timeDimension.isLoading()) {
111 | this._update();
112 | }
113 | this.fire('timeload', {
114 | time: time
115 | });
116 | }).bind(this));
117 |
118 | oReq.open("GET", url);
119 | oReq.send();
120 | },
121 |
122 | _constructQuery: function(time) {
123 | var time = new Date(time);
124 | var timeParams = "&time=" +
125 | time.format('isoDateTime');
126 | var url = this._baseURL + timeParams;
127 | return url;
128 | },
129 |
130 | _processLoadedData: function(data) {
131 | return data;
132 | }
133 | });
134 |
135 | L.timeDimension.layer.velocityLayer = function(options) {
136 | return new L.TimeDimension.Layer.VelocityLayer(options);
137 | };
138 |
--------------------------------------------------------------------------------
/examples/server/proxy-datadiscovery.php:
--------------------------------------------------------------------------------
1 | = 0; $i--) {
9 | $line = $http_response_header[$i];
10 | if (substr_compare($line, 'Content-Type', 0, 12, true) == 0) {
11 | $content_type = $line;
12 | break;
13 | }
14 | }
15 | header($content_type);
16 | echo $result;
17 | } else{
18 | header('HTTP/1.0 400 Bad Request');
19 | echo 'Request not valid';
20 | }
21 | ?>
22 |
--------------------------------------------------------------------------------
/examples/server/proxy.php:
--------------------------------------------------------------------------------
1 | = 0){
6 | $result = file_get_contents($url);
7 | $nlines = count($http_response_header);
8 | for ($i = $nlines-1; $i >= 0; $i--) {
9 | $line = $http_response_header[$i];
10 | if (substr_compare($line, 'Content-Type', 0, 12, true) == 0) {
11 | $content_type = $line;
12 | break;
13 | }
14 | }
15 | header($content_type);
16 | echo $result;
17 | } else{
18 | header('HTTP/1.0 400 Bad Request');
19 | echo 'Request not valid';
20 | }
21 | ?>
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "leaflet-timedimension",
3 | "version": "1.1.1",
4 | "description": "Add time dimension capabilities on a Leaflet map",
5 | "keywords": [
6 | "gis",
7 | "map",
8 | "timedimension",
9 | "leaflet"
10 | ],
11 | "homepage": "https://apps.socib.es/Leaflet.TimeDimension/",
12 | "bugs": {
13 | "url": "https://github.com/socib/Leaflet.TimeDimension/issues"
14 | },
15 | "license": "MIT",
16 | "author": {
17 | "name": "Biel Frontera (ICTS SOCIB)",
18 | "email": "datacenter@socib.es",
19 | "url": "https://www.socib.es/"
20 | },
21 | "contributors": [
22 | {
23 | "name": "Sylvain Marcadal (Ram)",
24 | "email": "sylvain@marcadal.me",
25 | "url": "https://github.com/ram-one"
26 | }
27 | ],
28 | "repository": {
29 | "type": "git",
30 | "url": "git://github.com/socib/Leaflet.TimeDimension.git"
31 | },
32 | "dependencies": {
33 | "iso8601-js-period": "^0.2.1",
34 | "leaflet": "~0.7.4 || ~1"
35 | },
36 | "devDependencies": {
37 | "grunt": "~1",
38 | "grunt-contrib-clean": "~0.7.0",
39 | "grunt-contrib-concat": "~1",
40 | "grunt-contrib-cssmin": "~2.2",
41 | "grunt-contrib-jshint": "~1.1",
42 | "grunt-contrib-uglify": "~3.1.0",
43 | "grunt-contrib-watch": "~1",
44 | "grunt-remove-logging": "~0.2.0"
45 | },
46 | "main": "dist/leaflet.timedimension.src.js",
47 | "style": "dist/leaflet.timedimension.control.css"
48 | }
49 |
--------------------------------------------------------------------------------
/src/leaflet.timedimension.control.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'Glyphicons Halflings';
3 | src: url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.eot');
4 | src: url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.woff') format('woff'), url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('//netdna.bootstrapcdn.com/bootstrap/3.0.0/fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
5 | }
6 | .leaflet-bar-timecontrol{
7 | background-color: #fff;
8 | color: black;
9 | }
10 | .leaflet-bar-timecontrol * {
11 | box-sizing: border-box;
12 | }
13 | .leaflet-bar-timecontrol .leaflet-control-timecontrol {
14 | float: left;
15 | height: 26px;
16 | line-height: 26px;
17 | border: solid #a5a5a5;
18 | background-color: #fff;
19 | border-width: 0 1px 0 0;
20 | }
21 | .leaflet-bar-timecontrol .leaflet-control-timecontrol:first-child {
22 | border-radius: 4px 0 0 4px;
23 | }
24 | .leaflet-bar-timecontrol .leaflet-control-timecontrol:last-child {
25 | border-radius: 0 4px 4px 0;
26 | }
27 | .leaflet-bar-timecontrol .leaflet-control-timecontrol:before {
28 | font-family: "Glyphicons Halflings";
29 | display: block;
30 | }
31 | .leaflet-bar-timecontrol .timecontrol-slider {
32 | position: relative;
33 | width: auto;
34 | cursor: auto;
35 | }
36 | .leaflet-bar-timecontrol a.timecontrol-date,
37 | .leaflet-bar-timecontrol a.timecontrol-date:hover {
38 | position: relative;
39 | min-width: 150px;
40 | width: auto;
41 | padding: 0 10px 0 20px;
42 | white-space: nowrap;
43 | }
44 | .leaflet-bar-timecontrol a.timecontrol-date.utc,
45 | .leaflet-bar-timecontrol a.timecontrol-date.utc:hover {
46 | min-width: 185px;
47 | }
48 | .leaflet-bar-timecontrol a.timecontrol-date.loading,
49 | .leaflet-bar-timecontrol a.timecontrol-date.loading:hover {
50 | background-color: #ffefa4;
51 | }
52 | .leaflet-bar-timecontrol .timecontrol-dateslider .slider {
53 | width: 200px;
54 | }
55 | .leaflet-bar-timecontrol .timecontrol-speed {
56 | white-space: nowrap;
57 | cursor: auto;
58 | }
59 | .leaflet-bar-timecontrol .timecontrol-speed .slider {
60 | width: 55px;
61 | display: inline-block;
62 | }
63 | .leaflet-bar-timecontrol .timecontrol-speed .speed {
64 | width: 55px;
65 | display: inline-block;
66 | float: left;
67 | text-align: right;
68 | }
69 | .leaflet-bar-timecontrol .timecontrol-play,
70 | .leaflet-bar-timecontrol .timecontrol-play:hover {
71 | position: relative;
72 | }
73 | .leaflet-bar-timecontrol .timecontrol-play span {
74 | font-size: 10px;
75 | }
76 | .leaflet-bar-timecontrol a.timecontrol-play.loading {
77 | background-color: #ffefa4;
78 | }
79 |
80 | /**
81 | * Slider/Knobs styles
82 | */
83 |
84 | .timecontrol-slider .slider {
85 | position: relative;
86 | height: 12px;
87 | margin: 6px;
88 | border: 1px solid #a5a5a5;
89 | cursor: pointer;
90 | }
91 | .timecontrol-slider .slider.has-limits {
92 | margin-left: 15px;
93 | margin-right: 15px;
94 | background-color: #ddd;
95 | }
96 | .timecontrol-slider .slider.has-limits .range {
97 | position: absolute;
98 | height: 10px;
99 | background-color: #fff;
100 | /*opacity: 0.5;*/
101 | }
102 | .timecontrol-slider .knob {
103 | position: absolute;
104 | width: 8px;
105 | height: 22px;
106 | background-color: #ddd;
107 | border-radius: 2px;
108 | border: 1px solid #a5a5a5;
109 | /*use margins because on ie,leaflet will use top/left for positionning*/
110 | margin-top: -6px;
111 | margin-left: -4px;
112 | cursor: ew-resize;
113 | cursor: -webkit-grab;
114 | cursor: -moz-grab;
115 | }
116 | .timecontrol-slider .knob:after {
117 | /** Big transparent block on top of the knob for easier grabbing on touch device*/
118 | content: ' ';
119 | display: block;
120 | position: absolute;
121 | width: 20px;
122 | top:-5px;
123 | height: 32px;
124 | left: -7px;
125 | /* opacity: 0.5;
126 | background: red;*/
127 |
128 | }
129 | .timecontrol-slider .knob.upper,
130 | .timecontrol-slider .knob.lower {
131 | width: 11px;
132 | height: 20px;
133 | border: none;
134 | background-color: transparent;
135 | }
136 | .timecontrol-slider .knob.upper {
137 | margin-top: -5px;
138 | margin-left: -1px;
139 | }
140 | .timecontrol-slider .knob.lower {
141 | margin-top: -5px;
142 | margin-left: -10px;
143 | }
144 | .timecontrol-slider .knob.lower:after {
145 | right:0px;
146 | left: initial;
147 | }
148 | .timecontrol-slider .knob.upper:after {
149 | left:0px;
150 | }
151 | .timecontrol-slider .knob.upper:before,
152 | .timecontrol-slider .knob.lower:before {
153 | display: block;
154 | content: '';
155 | position: relative;
156 | top: 2px;
157 | width: 0;
158 | height: 0;
159 | border-style: solid;
160 | }
161 | .timecontrol-slider .knob.upper:before {
162 | border-width: 16px 0 0 10px;
163 | border-color: transparent transparent transparent #a5a5a5;
164 | }
165 | .timecontrol-slider .knob.lower:before {
166 | border-width: 0 0 16px 10px;
167 | border-color: transparent transparent #a5a5a5;
168 | }
169 |
170 | .timecontrol-slider .slider.dragging,
171 | .timecontrol-slider .dragging .knob,
172 | .timecontrol-slider .knob.leaflet-drag-target {
173 | cursor: ew-resize;
174 | cursor: grabbing;
175 | cursor: -webkit-grabbing;
176 | cursor: -moz-grabbing;
177 | }
178 |
179 | /**
180 | * Icons definitions
181 | */
182 |
183 | @-webkit-keyframes icon-rotation {
184 | from {
185 | -webkit-transform: rotate(0deg);
186 | transform: rotate(0deg);
187 | }
188 | to {
189 | -webkit-transform: rotate(360deg);
190 | transform: rotate(360deg);
191 | }
192 | }
193 | @keyframes icon-rotation {
194 | from {
195 | -webkit-transform: rotate(0deg);
196 | transform: rotate(0deg);
197 | }
198 | to {
199 | -webkit-transform: rotate(360deg);
200 | transform: rotate(360deg);
201 | }
202 | }
203 | .timecontrol-loop.looped,
204 | .timecontrol-loop.looped:hover {
205 | background-color: #ddd;
206 | color: #094F8E;
207 | }
208 |
209 | .timecontrol-backward:before,
210 | .timecontrol-forward:before,
211 | .timecontrol-stop:before,
212 | .timecontrol-play:before,
213 | .timecontrol-loop:before {
214 | width: 100%;
215 | text-align: center;
216 | }
217 |
218 | .timecontrol-play:before {
219 | position: absolute;
220 | content: "\e072";
221 | }
222 | /*.timecontrol-play.play:before {
223 | content: "\e072";
224 | }*/
225 | .timecontrol-play.reverse:before {
226 | content: "\e072";
227 | -ms-transform: scaleX(-1);
228 | -webkit-transform: scaleX(-1);
229 | transform: scaleX(-1);
230 | }
231 | .timecontrol-play.pause:before {
232 | content: "\e073";
233 | }
234 | .timecontrol-play.reverse.pause:before {
235 | -ms-transform: none;
236 | -webkit-transform: none;
237 | transform: none;
238 | }
239 |
240 | a.timecontrol-play.loading:before {
241 | content: "\e031";
242 | opacity: 0.2;
243 | -webkit-animation: icon-rotation 6s infinite linear;
244 | animation: icon-rotation 6s infinite linear;
245 | }
246 | .timecontrol-date.loading:before {
247 | content: "\e031";
248 | left: 5px;
249 | position: absolute;
250 | -webkit-animation: icon-rotation 6s infinite linear;
251 | animation: icon-rotation 6s infinite linear;
252 | }
253 | .timecontrol-speed:before {
254 | content: "\e141";
255 | position: absolute;
256 | left: 7px;
257 | }
258 | .timecontrol-stop:before {
259 | content: "\e074";
260 | }
261 | .timecontrol-forward:before {
262 | content: "\e075";
263 | }
264 | .timecontrol-backward:before {
265 | content: "\e071";
266 | }
267 | .timecontrol-loop:before {
268 | content: "\e030";
269 | }
270 |
271 | @media (max-width: 767px){
272 | .leaflet-bar-timecontrol .timecontrol-date,
273 | .leaflet-bar-timecontrol .timecontrol-slider{
274 | clear: both;
275 | float: none;
276 | border-right: none;
277 | }
278 | }
279 | .leaflet-touch .leaflet-bar-timecontrol .leaflet-control-timecontrol{
280 | height: 30px;
281 | line-height: 30px;
282 | }
283 | .leaflet-touch .timecontrol-slider .slider{
284 | margin-top: 10px;
285 | }
--------------------------------------------------------------------------------
/src/leaflet.timedimension.layer.geojson.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.TimeDimension.Layer.GeoJson:
3 | */
4 |
5 | L.TimeDimension.Layer.GeoJson = L.TimeDimension.Layer.extend({
6 |
7 | initialize: function(layer, options) {
8 | L.TimeDimension.Layer.prototype.initialize.call(this, layer, options);
9 | this._updateTimeDimension = this.options.updateTimeDimension || false;
10 | this._updateTimeDimensionMode = this.options.updateTimeDimensionMode || 'extremes'; // 'union', 'replace' or extremes
11 | this._duration = this.options.duration || null;
12 | this._addlastPoint = this.options.addlastPoint || false;
13 | this._waitForReady = this.options.waitForReady || false;
14 | this._updateCurrentTime = this.options.updateCurrentTime || this._updateTimeDimension;
15 | this._availableTimes = [];
16 | this._loaded = false;
17 | if (this._baseLayer.getLayers().length == 0) {
18 | if (this._waitForReady){
19 | this._baseLayer.on("ready", this._onReadyBaseLayer, this);
20 | }else{
21 | this._loaded = true;
22 | }
23 | } else {
24 | this._loaded = true;
25 | this._setAvailableTimes();
26 | }
27 | // reload available times if data is added to the base layer
28 | this._baseLayer.on('layeradd', (function () {
29 | if (this._loaded) {
30 | this._setAvailableTimes();
31 | }
32 | }).bind(this));
33 | },
34 |
35 | onAdd: function(map) {
36 | L.TimeDimension.Layer.prototype.onAdd.call(this, map);
37 | if (this._loaded) {
38 | this._setAvailableTimes();
39 | }
40 | },
41 |
42 | eachLayer: function(method, context) {
43 | if (this._currentLayer) {
44 | method.call(context, this._currentLayer);
45 | }
46 | return L.TimeDimension.Layer.prototype.eachLayer.call(this, method, context);
47 | },
48 |
49 | isReady: function(time) {
50 | return this._loaded;
51 | },
52 |
53 | _update: function() {
54 | if (!this._map)
55 | return;
56 | if (!this._loaded) {
57 | return;
58 | }
59 |
60 | var time = this._timeDimension.getCurrentTime();
61 |
62 | var maxTime = this._timeDimension.getCurrentTime(),
63 | minTime = 0;
64 | if (this._duration) {
65 | var date = new Date(maxTime);
66 | L.TimeDimension.Util.subtractTimeDuration(date, this._duration, true);
67 | minTime = date.getTime();
68 | }
69 |
70 | // new coordinates:
71 | var layer = L.geoJson(null, this._baseLayer.options);
72 | var layers = this._baseLayer.getLayers();
73 | for (var i = 0, l = layers.length; i < l; i++) {
74 | var feature = this._getFeatureBetweenDates(layers[i].feature, minTime, maxTime);
75 | if (feature) {
76 | layer.addData(feature);
77 | if (this._addlastPoint && feature.geometry.type == "LineString") {
78 | if (feature.geometry.coordinates.length > 0) {
79 | var properties = feature.properties;
80 | properties.last = true;
81 | layer.addData({
82 | type: 'Feature',
83 | properties: properties,
84 | geometry: {
85 | type: 'Point',
86 | coordinates: feature.geometry.coordinates[feature.geometry.coordinates.length - 1]
87 | }
88 | });
89 | }
90 | }
91 | }
92 | }
93 |
94 | if (this._currentLayer) {
95 | this._map.removeLayer(this._currentLayer);
96 | }
97 | if (layer.getLayers().length) {
98 | layer.addTo(this._map);
99 | this._currentLayer = layer;
100 | }
101 | },
102 |
103 | _setAvailableTimes: function() {
104 | var times = [];
105 | var layers = this._baseLayer.getLayers();
106 | for (var i = 0, l = layers.length; i < l; i++) {
107 | if (layers[i].feature) {
108 | var featureTimes = this._getFeatureTimes(layers[i].feature);
109 | for (var j = 0, m = featureTimes.length; j < m; j++) {
110 | times.push(featureTimes[j]);
111 | }
112 | }
113 | }
114 | this._availableTimes = L.TimeDimension.Util.sort_and_deduplicate(times);
115 | this._updateCurrentTime = this._updateCurrentTime || (this._timeDimension && this._timeDimension.getAvailableTimes().length == 0);
116 | if (this._timeDimension && (this._updateTimeDimension || this._timeDimension.getAvailableTimes().length == 0)) {
117 | this._timeDimension.setAvailableTimes(this._availableTimes, this._updateTimeDimensionMode);
118 | }
119 | if (this._updateCurrentTime && this._timeDimension && this._availableTimes.length) {
120 | this._timeDimension.setCurrentTime(this._availableTimes[0]);
121 | }
122 | },
123 |
124 | _getFeatureTimes: function(feature) {
125 | if (!feature.featureTimes) {
126 | if (!feature.properties) {
127 | feature.featureTimes = [];
128 | } else if (feature.properties.hasOwnProperty('coordTimes')) {
129 | feature.featureTimes = feature.properties.coordTimes;
130 | } else if (feature.properties.hasOwnProperty('times')) {
131 | feature.featureTimes = feature.properties.times;
132 | } else if (feature.properties.hasOwnProperty('linestringTimestamps')) {
133 | feature.featureTimes = feature.properties.linestringTimestamps;
134 | } else if (feature.properties.hasOwnProperty('time')) {
135 | feature.featureTimes = [feature.properties.time];
136 | } else {
137 | feature.featureTimes = [];
138 | }
139 | // String dates to ms
140 | for (var i = 0, l = feature.featureTimes.length; i < l; i++) {
141 | var time = feature.featureTimes[i];
142 | if (typeof time == 'string' || time instanceof String) {
143 | time = Date.parse(time.trim());
144 | feature.featureTimes[i] = time;
145 | }
146 | }
147 | }
148 | return feature.featureTimes;
149 | },
150 |
151 | _getFeatureBetweenDates: function(feature, minTime, maxTime) {
152 | var featureTimes = this._getFeatureTimes(feature);
153 | if (featureTimes.length == 0) {
154 | return feature;
155 | }
156 |
157 | var index_min = null,
158 | index_max = null,
159 | l = featureTimes.length;
160 |
161 | if (featureTimes[0] > maxTime || featureTimes[l - 1] < minTime) {
162 | return null;
163 | }
164 |
165 | if (featureTimes[l - 1] >= minTime) {
166 | for (var i = 0; i < l; i++) {
167 | if (index_min === null && featureTimes[i] >= minTime) {
168 | // set index_min the first time that current time is greater or equal to the minTime
169 | index_min = i;
170 | }
171 | if (featureTimes[i] > maxTime) {
172 | index_max = i;
173 | break;
174 | }
175 | }
176 | }
177 | if (index_min === null) {
178 | index_min = 0;
179 | }
180 | if (index_max === null) {
181 | index_max = l;
182 | }
183 | var new_coordinates = [];
184 | if (feature.geometry.coordinates[0].length) {
185 | new_coordinates = feature.geometry.coordinates.slice(index_min, index_max);
186 | } else {
187 | new_coordinates = feature.geometry.coordinates;
188 | }
189 | return {
190 | type: 'Feature',
191 | properties: feature.properties,
192 | geometry: {
193 | type: feature.geometry.type,
194 | coordinates: new_coordinates
195 | }
196 | };
197 | },
198 |
199 | _onReadyBaseLayer: function() {
200 | this._loaded = true;
201 | this._setAvailableTimes();
202 | this._update();
203 | },
204 |
205 | });
206 |
207 | L.timeDimension.layer.geoJson = function(layer, options) {
208 | return new L.TimeDimension.Layer.GeoJson(layer, options);
209 | };
210 |
--------------------------------------------------------------------------------
/src/leaflet.timedimension.layer.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.TimeDimension.Layer: an abstract Layer that can be managed/synchronized with a TimeDimension.
3 | * The constructor recieves a layer (of any kind) and options.
4 | * Any children class should implement `_onNewTimeLoading`, `isReady` and `_update` functions
5 | * to react to time changes.
6 | */
7 |
8 | L.TimeDimension.Layer = (L.Layer || L.Class).extend({
9 |
10 | includes: (L.Evented || L.Mixin.Events),
11 | options: {
12 | opacity: 1,
13 | zIndex: 1
14 | },
15 |
16 | initialize: function(layer, options) {
17 | L.setOptions(this, options || {});
18 | this._map = null;
19 | this._baseLayer = layer;
20 | this._currentLayer = null;
21 | this._timeDimension = this.options.timeDimension || null;
22 | },
23 |
24 | addTo: function(map) {
25 | map.addLayer(this);
26 | return this;
27 | },
28 |
29 | onAdd: function(map) {
30 | this._map = map;
31 | if (!this._timeDimension && map.timeDimension) {
32 | this._timeDimension = map.timeDimension;
33 | }
34 | this._timeDimension.on("timeloading", this._onNewTimeLoading, this);
35 | this._timeDimension.on("timeload", this._update, this);
36 | this._timeDimension.registerSyncedLayer(this);
37 | this._update();
38 | },
39 |
40 | onRemove: function(map) {
41 | this._timeDimension.unregisterSyncedLayer(this);
42 | this._timeDimension.off("timeloading", this._onNewTimeLoading, this);
43 | this._timeDimension.off("timeload", this._update, this);
44 | this.eachLayer(map.removeLayer, map);
45 | this._map = null;
46 | },
47 |
48 | eachLayer: function(method, context) {
49 | method.call(context, this._baseLayer);
50 | return this;
51 | },
52 |
53 | setZIndex: function(zIndex) {
54 | this.options.zIndex = zIndex;
55 | if (this._baseLayer.setZIndex) {
56 | this._baseLayer.setZIndex(zIndex);
57 | }
58 | if (this._currentLayer && this._currentLayer.setZIndex) {
59 | this._currentLayer.setZIndex(zIndex);
60 | }
61 | return this;
62 | },
63 |
64 | setOpacity: function(opacity) {
65 | this.options.opacity = opacity;
66 | if (this._baseLayer.setOpacity) {
67 | this._baseLayer.setOpacity(opacity);
68 | }
69 | if (this._currentLayer && this._currentLayer.setOpacity) {
70 | this._currentLayer.setOpacity(opacity);
71 | }
72 | return this;
73 | },
74 |
75 | bringToBack: function() {
76 | if (!this._currentLayer) {
77 | return;
78 | }
79 | this._currentLayer.bringToBack();
80 | return this;
81 | },
82 |
83 | bringToFront: function() {
84 | if (!this._currentLayer) {
85 | return;
86 | }
87 | this._currentLayer.bringToFront();
88 | return this;
89 | },
90 |
91 | _onNewTimeLoading: function(ev) {
92 | // to be implemented for each type of layer
93 | this.fire('timeload', {
94 | time: ev.time
95 | });
96 | return;
97 | },
98 |
99 | isReady: function(time) {
100 | // to be implemented for each type of layer
101 | return true;
102 | },
103 |
104 | _update: function() {
105 | // to be implemented for each type of layer
106 | return true;
107 | },
108 |
109 | getBaseLayer: function() {
110 | return this._baseLayer;
111 | },
112 |
113 | getBounds: function() {
114 | var bounds = new L.LatLngBounds();
115 | if (this._currentLayer) {
116 | bounds.extend(this._currentLayer.getBounds ? this._currentLayer.getBounds() : this._currentLayer.getLatLng());
117 | }
118 | return bounds;
119 | }
120 |
121 | });
122 |
123 | L.timeDimension.layer = function(layer, options) {
124 | return new L.TimeDimension.Layer(layer, options);
125 | };
--------------------------------------------------------------------------------
/src/leaflet.timedimension.player.js:
--------------------------------------------------------------------------------
1 | /*jshint indent: 4, browser:true*/
2 | /*global L*/
3 |
4 |
5 | /*
6 | * L.TimeDimension.Player
7 | */
8 | //'use strict';
9 | L.TimeDimension.Player = (L.Layer || L.Class).extend({
10 |
11 | includes: (L.Evented || L.Mixin.Events),
12 | initialize: function(options, timeDimension) {
13 | L.setOptions(this, options);
14 | this._timeDimension = timeDimension;
15 | this._paused = false;
16 | this._buffer = this.options.buffer || 5;
17 | this._minBufferReady = this.options.minBufferReady || 1;
18 | this._waitingForBuffer = false;
19 | this._loop = this.options.loop || false;
20 | this._steps = 1;
21 | this._timeDimension.on('timeload', (function(data) {
22 | this.release(); // free clock
23 | this._waitingForBuffer = false; // reset buffer
24 | }).bind(this));
25 | this.setTransitionTime(this.options.transitionTime || 1000);
26 |
27 | this._timeDimension.on('limitschanged availabletimeschanged timeload', (function(data) {
28 | this._timeDimension.prepareNextTimes(this._steps, this._minBufferReady, this._loop);
29 | }).bind(this));
30 | },
31 |
32 |
33 | _tick: function() {
34 | var maxIndex = this._getMaxIndex();
35 | var maxForward = (this._timeDimension.getCurrentTimeIndex() >= maxIndex) && (this._steps > 0);
36 | var maxBackward = (this._timeDimension.getCurrentTimeIndex() == 0) && (this._steps < 0);
37 | if (maxForward || maxBackward) {
38 | // we reached the last step
39 | if (!this._loop) {
40 | this.pause();
41 | this.stop();
42 | this.fire('animationfinished');
43 | return;
44 | }
45 | }
46 |
47 | if (this._paused) {
48 | return;
49 | }
50 | var numberNextTimesReady = 0,
51 | buffer = this._bufferSize;
52 |
53 | if (this._minBufferReady > 0) {
54 | numberNextTimesReady = this._timeDimension.getNumberNextTimesReady(this._steps, buffer, this._loop);
55 | // If the player was waiting, check if all times are loaded
56 | if (this._waitingForBuffer) {
57 | if (numberNextTimesReady < buffer) {
58 | console.log('Waiting until buffer is loaded. ' + numberNextTimesReady + ' of ' + buffer + ' loaded');
59 | this.fire('waiting', {
60 | buffer: buffer,
61 | available: numberNextTimesReady
62 | });
63 | return;
64 | } else {
65 | // all times loaded
66 | console.log('Buffer is fully loaded!');
67 | this.fire('running');
68 | this._waitingForBuffer = false;
69 | }
70 | } else {
71 | // check if player has to stop to wait and force to full all the buffer
72 | if (numberNextTimesReady < this._minBufferReady) {
73 | console.log('Force wait for load buffer. ' + numberNextTimesReady + ' of ' + buffer + ' loaded');
74 | this._waitingForBuffer = true;
75 | this._timeDimension.prepareNextTimes(this._steps, buffer, this._loop);
76 | this.fire('waiting', {
77 | buffer: buffer,
78 | available: numberNextTimesReady
79 | });
80 | return;
81 | }
82 | }
83 | }
84 | this.pause();
85 | this._timeDimension.nextTime(this._steps, this._loop);
86 | if (buffer > 0) {
87 | this._timeDimension.prepareNextTimes(this._steps, buffer, this._loop);
88 | }
89 | },
90 |
91 | _getMaxIndex: function(){
92 | return Math.min(this._timeDimension.getAvailableTimes().length - 1,
93 | this._timeDimension.getUpperLimitIndex() || Infinity);
94 | },
95 |
96 | start: function(numSteps) {
97 | if (this._intervalID) return;
98 | this._steps = numSteps || 1;
99 | this._waitingForBuffer = false;
100 | var startedOver = false;
101 | if (this.options.startOver){
102 | if (this._timeDimension.getCurrentTimeIndex() === this._getMaxIndex()){
103 | this._timeDimension.setCurrentTimeIndex(this._timeDimension.getLowerLimitIndex() || 0);
104 | startedOver = true;
105 | }
106 | }
107 | this.release();
108 | this._intervalID = window.setInterval(
109 | L.bind(this._tick, this),
110 | this._transitionTime);
111 | if (!startedOver)
112 | this._tick();
113 | this.fire('play');
114 | this.fire('running');
115 | },
116 |
117 | stop: function() {
118 | if (!this._intervalID) return;
119 | clearInterval(this._intervalID);
120 | this._intervalID = null;
121 | this._waitingForBuffer = false;
122 | this.fire('stop');
123 | },
124 |
125 | pause: function() {
126 | this._paused = true;
127 | },
128 |
129 | release: function () {
130 | this._paused = false;
131 | },
132 |
133 | getTransitionTime: function() {
134 | return this._transitionTime;
135 | },
136 |
137 | isPlaying: function() {
138 | return this._intervalID ? true : false;
139 | },
140 |
141 | isWaiting: function() {
142 | return this._waitingForBuffer;
143 | },
144 | isLooped: function() {
145 | return this._loop;
146 | },
147 |
148 | setLooped: function(looped) {
149 | this._loop = looped;
150 | this.fire('loopchange', {
151 | loop: looped
152 | });
153 | },
154 |
155 | setTransitionTime: function(transitionTime) {
156 | this._transitionTime = transitionTime;
157 | if (typeof this._buffer === 'function') {
158 | this._bufferSize = this._buffer.call(this, this._transitionTime, this._minBufferReady, this._loop);
159 | console.log('Buffer size changed to ' + this._bufferSize);
160 | } else {
161 | this._bufferSize = this._buffer;
162 | }
163 | if (this._intervalID) {
164 | this.stop();
165 | this.start(this._steps);
166 | }
167 | this.fire('speedchange', {
168 | transitionTime: transitionTime,
169 | buffer: this._bufferSize
170 | });
171 | },
172 |
173 | getSteps: function() {
174 | return this._steps;
175 | }
176 | });
177 |
--------------------------------------------------------------------------------
/src/leaflet.timedimension.util.js:
--------------------------------------------------------------------------------
1 | /*
2 | * L.TimeDimension.Util
3 | */
4 |
5 | L.TimeDimension.Util = {
6 | getTimeDuration: function(ISODuration) {
7 | if (typeof nezasa === 'undefined') {
8 | throw "iso8601-js-period library is required for Leatlet.TimeDimension: https://www.npmjs.com/package/iso8601-js-period";
9 | }
10 | return nezasa.iso8601.Period.parse(ISODuration, true);
11 | },
12 |
13 | addTimeDuration: function(date, duration, utc) {
14 | if (typeof utc === 'undefined') {
15 | utc = true;
16 | }
17 | if (typeof duration == 'string' || duration instanceof String) {
18 | duration = this.getTimeDuration(duration);
19 | }
20 | var l = duration.length;
21 | var get = utc ? "getUTC" : "get";
22 | var set = utc ? "setUTC" : "set";
23 |
24 | if (l > 0 && duration[0] != 0) {
25 | date[set + "FullYear"](date[get + "FullYear"]() + duration[0]);
26 | }
27 | if (l > 1 && duration[1] != 0) {
28 | date[set + "Month"](date[get + "Month"]() + duration[1]);
29 | }
30 | if (l > 2 && duration[2] != 0) {
31 | // weeks
32 | date[set + "Date"](date[get + "Date"]() + (duration[2] * 7));
33 | }
34 | if (l > 3 && duration[3] != 0) {
35 | date[set + "Date"](date[get + "Date"]() + duration[3]);
36 | }
37 | if (l > 4 && duration[4] != 0) {
38 | date[set + "Hours"](date[get + "Hours"]() + duration[4]);
39 | }
40 | if (l > 5 && duration[5] != 0) {
41 | date[set + "Minutes"](date[get + "Minutes"]() + duration[5]);
42 | }
43 | if (l > 6 && duration[6] != 0) {
44 | date[set + "Seconds"](date[get + "Seconds"]() + duration[6]);
45 | }
46 | },
47 |
48 | subtractTimeDuration: function(date, duration, utc) {
49 | if (typeof duration == 'string' || duration instanceof String) {
50 | duration = this.getTimeDuration(duration);
51 | }
52 | var subDuration = [];
53 | for (var i = 0, l = duration.length; i < l; i++) {
54 | subDuration.push(-duration[i]);
55 | }
56 | this.addTimeDuration(date, subDuration, utc);
57 | },
58 |
59 | parseAndExplodeTimeRange: function(timeRange, overwritePeriod) {
60 | var tr = timeRange.split('/');
61 | var startTime = new Date(Date.parse(tr[0]));
62 | var endTime = new Date(Date.parse(tr[1]));
63 | var period = (tr.length > 2 && tr[2].length) ? tr[2] : "P1D";
64 | if (overwritePeriod !== undefined && overwritePeriod !== null){
65 | period = overwritePeriod;
66 | }
67 | return this.explodeTimeRange(startTime, endTime, period);
68 | },
69 |
70 | explodeTimeRange: function(startTime, endTime, ISODuration, validTimeRange) {
71 | var duration = this.getTimeDuration(ISODuration);
72 | var result = [];
73 | var currentTime = new Date(startTime.getTime());
74 | var minHour = null,
75 | minMinutes = null,
76 | maxHour = null,
77 | maxMinutes = null;
78 | if (validTimeRange !== undefined) {
79 | var validTimeRangeArray = validTimeRange.split('/');
80 | minHour = validTimeRangeArray[0].split(':')[0];
81 | minMinutes = validTimeRangeArray[0].split(':')[1];
82 | maxHour = validTimeRangeArray[1].split(':')[0];
83 | maxMinutes = validTimeRangeArray[1].split(':')[1];
84 | }
85 | while (currentTime < endTime) {
86 | if (validTimeRange === undefined ||
87 | (currentTime.getUTCHours() >= minHour && currentTime.getUTCHours() <= maxHour)
88 | ) {
89 | if ((currentTime.getUTCHours() != minHour || currentTime.getUTCMinutes() >= minMinutes) &&
90 | (currentTime.getUTCHours() != maxHour || currentTime.getUTCMinutes() <= maxMinutes)) {
91 | result.push(currentTime.getTime());
92 | }
93 | }
94 | this.addTimeDuration(currentTime, duration);
95 | }
96 | if (currentTime >= endTime){
97 | result.push(endTime.getTime());
98 | }
99 | return result;
100 | },
101 |
102 | parseTimeInterval: function(timeInterval) {
103 | var parts = timeInterval.split("/");
104 | if (parts.length != 2) {
105 | throw "Incorrect ISO9601 TimeInterval: " + timeInterval;
106 | }
107 | var startTime = Date.parse(parts[0]);
108 | var endTime = null;
109 | var duration = null;
110 | if (isNaN(startTime)) {
111 | // -> format duration/endTime
112 | duration = this.getTimeDuration(parts[0]);
113 | endTime = Date.parse(parts[1]);
114 | startTime = new Date(endTime);
115 | this.subtractTimeDuration(startTime, duration, true);
116 | endTime = new Date(endTime);
117 | } else {
118 | endTime = Date.parse(parts[1]);
119 | if (isNaN(endTime)) {
120 | // -> format startTime/duration
121 | duration = this.getTimeDuration(parts[1]);
122 | endTime = new Date(startTime);
123 | this.addTimeDuration(endTime, duration, true);
124 | } else {
125 | // -> format startTime/endTime
126 | endTime = new Date(endTime);
127 | }
128 | startTime = new Date(startTime);
129 | }
130 | return [startTime, endTime];
131 | },
132 |
133 | parseTimesExpression: function(times, overwritePeriod) {
134 | var result = [];
135 | if (!times) {
136 | return result;
137 | }
138 | if (typeof times == 'string' || times instanceof String) {
139 | var timeRanges = times.split(",");
140 | var timeRange;
141 | var timeValue;
142 | for (var i=0, l=timeRanges.length; i 0 && b.length > 0) {
166 | if (a[0] < b[0]) {
167 | a.shift();
168 | } else if (a[0] > b[0]) {
169 | b.shift();
170 | } else /* they're equal */ {
171 | result.push(a.shift());
172 | b.shift();
173 | }
174 | }
175 | return result;
176 | },
177 |
178 | union_arrays: function(arrayA, arrayB) {
179 | var a = arrayA.slice(0);
180 | var b = arrayB.slice(0);
181 | var result = [];
182 | while (a.length > 0 && b.length > 0) {
183 | if (a[0] < b[0]) {
184 | result.push(a.shift());
185 | } else if (a[0] > b[0]) {
186 | result.push(b.shift());
187 | } else /* they're equal */ {
188 | result.push(a.shift());
189 | b.shift();
190 | }
191 | }
192 | if (a.length > 0) {
193 | result = result.concat(a);
194 | } else if (b.length > 0) {
195 | result = result.concat(b);
196 | }
197 | return result;
198 | },
199 |
200 | sort_and_deduplicate: function(arr) {
201 | arr = arr.slice(0).sort(function (a, b) {
202 | return a - b;
203 | });
204 | var result = [];
205 | var last = null;
206 | for (var i = 0, l = arr.length; i < l; i++) {
207 | if (arr[i] !== last){
208 | result.push(arr[i]);
209 | last = arr[i];
210 | }
211 | }
212 | return result;
213 | }
214 |
215 | };
216 |
--------------------------------------------------------------------------------