Giter Site home page Giter Site logo

skeate / leaflet.timeline Goto Github PK

View Code? Open in Web Editor NEW
379.0 14.0 66.0 11.48 MB

Display arbitrary GeoJSON on a map with a timeline slider and play button

Home Page: https://skeate.github.io/Leaflet.timeline

License: ISC License

JavaScript 2.54% TypeScript 91.66% CSS 5.80%
leaflet geojson timeline

leaflet.timeline's Introduction

Build Status Code Climate Test Coverage npm version

Join the chat at https://gitter.im/skeate/Leaflet.timeline

Leaflet.timeline

Show any changing geospatial data over time, from points to polygons.

If you want smooth motion of markers from point to point, this is not your plugin. Please check out LeafletPlayback, or for real-time data, try Leaflet Realtime, both plugins from which I may or may not have pilfered some ideas.

Examples

To run the examples locally, run npm run build and then open the one of the examples in docs/examples.

USGS provides GeoJSON(P) files with earthquake data, including time and magnitude. For this example, that data is read, parsed to the right format (start and end values in the GeoJSON properties), and added to a Leaflet.timeline.

I found some historical country border data here, though unfortunately it was not in GeoJSON. I converted it with ogr2ogr:

$ ogr2ogr -f "GeoJSON" \
  -select CNTRY_NAME,COWSYEAR,COWSMONTH,COWSDAY,COWEYEAR,COWEMONTH,COWEDAY \
  borders.json cshapes.shp

then wrangled the data into the right format (docs/examples/borders-parse.js). After that, it was just a matter of passing the data to Leaflet.timeline and letting it handle everything.

Usage

There are actually two classes here. L.Timeline and L.TimelineSliderControl.

L.Timeline

L.Timeline is a subclass of L.GeoJSON, so use it as you would that. The data you pass in should be something like this:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {
        "start": "1970-01-01",
        "end": "2014-12-04"
      },
      "geometry": { ... }
    }
  ]
}

Though you can also pass in a getInterval function to parse the data as you wish. (see below)

The date can really be any numerical value -- if you're using this for timed data, a Unix timestamp (the ms version for easier JS usage) probably makes sense.

Options

see also all GeoJSON's options

getInterval (Function -- optional)

This is a function which should return an object with start and end properties. By default it assumes a structure as above.

Optionally, the boolean keys startExclusive and endExclusive allow this interval to be considered exclusive, i.e., only matching time > start (time < end), instead of time >= start(time <= end), respectively.

drawOnSetTime (Boolean -- optional, default true)

Make the layer draw as soon as setTime is called. If this is set to false, you will need to call updateDisplayedLayers() manually when you want it to actually update.

Events

change

Fired when the selected time changes (either through manually sliding or through playback).

L.TimelineSliderControl

This is the actual control that allows playback and whatnot. It can control multiple L.Timelines.

Options

start

default: earliest start in GeoJSON

The beginning/minimum value of the timeline.

end

default: latest end in GeoJSON

The end/maximum value of the timeline.

position

default: bottomleft

Position for the timeline controls. Probably doesn't really matter as you'll likely want to expand them anyway.

formatOutput

default: (date) -> date.toString()

A function that takes in a Unix timestamp and outputs a string. Ideally for formatting the timestamp, but hey, you can do whatever you want.

enablePlayback

default: true

Show playback controls (i.e. prev/play/pause/next).

enableKeyboardControls

default: false

Allow playback to be controlled using the spacebar (play/pause) and right/left arrow keys (next/previous).

steps

default: 1000

How many steps to break the timeline into. Each step will then be (end-start) / steps. Only affects playback.

duration

default: 10000

Minimum time, in ms, for the playback to take. Will almost certainly actually take at least a bit longer -- after each frame, the next one displays in duration/steps ms, so each frame really takes frame processing time PLUS step time.

showTicks

default: true

Show tick marks on slider (if the browser supports it), representing changes in value(s).

waitToUpdateMap

default: false

Wait until the user is finished changing the date to update the map. By default, both the map and the date update for every change. With complex data, this can slow things down, so set this to true to only update the displayed date.

autoPlay

default: false

Slider starts playing automatically after loading.

Methods

setTime

Sets the current timeline time. Will parse any dates in just about any format you throw at it.

getDisplayed

Returns the original GeoJSON of the features that are currently being displayed on the map.

Contributing

To get the project running locally, clone this repo and run these commands within the project folder:

npm install
npm test -- --watchAll

To view the examples, you'll need to build:

npm run build

Then open up the HTML files in the "docs/examples" folders in your browser.

Please create a pull request from your fork of the project, and provide details of the intent of the changes.

Change log

1.4.2

  • Bugfix: Prevent keyboard controls from triggering in other inputs or textareas (#146)

1.4.1

  • Minor package change (removing extra files)

1.4.0

  • Migrate to Typescript
  • Upgrade Diesal dependency to improve performance on large datasets

1.3.0

  • Add aria-labels (#136)
  • Add autoplay option (#116)

1.0.0

  • 100% test coverage
  • BUGFIX: times is no longer shared among all Timeline instances
  • Switch to pointer events for better mobile support (hopefully)
  • More build tweaks, including setting up a dev server

1.0.0-beta

  • Completely rewrote in ES6
  • Overhauled build system with webpack
  • Separated layer from control, allowing the control to handle multiple layers at the same time
  • Added tests!

0.4.3

  • Build tweaks

0.4.2

  • Fixed a version check issue

0.4.1

  • Fixed an issue where removing the L.timeline would not remove the control

0.4.0

  • Fixed an issue where too wide of a range of dates would case playback to go backwards
  • Added options to pass in methods to handle the data, so you can use a different format if you want
  • Added a grunt build pipeline (thanks to @vencax for this and the two changes above)
  • Fixed a bug where next/previous buttons wouldn't work as expected if input wasn't sorted (.. by sorting the input)

0.3.0

  • Fixed Pause button not turning back into Play button on playback completion
  • Fixed clicks on control buttons zooming map
  • Fixed getDisplayed and event timing
  • Major performance improvements
  • Add waitToUpdateMap option to allow dragging the slider without updating the map until user is done

0.2.0

  • Added previous/next/pause
  • Change behavior of play button (will play from wherever it is rather than reset to the beginning)
  • Lots of code restructuring
  • Add more extensive default styling, using Sass

0.1.0

  • It kinda works?

leaflet.timeline's People

Contributors

dependabot[bot] avatar dmundra avatar ebrelsford avatar gitter-badger avatar greenkeeper[bot] avatar jaliflo avatar jskeate avatar magamig avatar markstuart avatar melgish avatar simon04 avatar skeate avatar skorasaurus avatar theopolisme avatar vencax avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

leaflet.timeline's Issues

Toggling Layers

Hey!

I wasn't sure if I should submit this as an issue or not. If I follow instructions and my stuff runs backwards, that's an issue. If I can't get something to work because I just don't know enough, well, that's a different story.

Here's my deal.

For the most part, when I want to implement toggleable layers, I add my data to layerGroups or set a filter function on a Mapbox featureLayer. But because L.timeline works akin to L.geojson, those options seem out of reach.

I have a dataset that I can divide into 11 different categories based on the value in features.properties.purp. I was thinking maybe I could set up 11 arrays and then loop through the json object and push each element to its corresponding array?

        var agLayer = [];

        $.getJSON("js/permitsOntario.json", function(permits) {          
            var timeline = L.timeline(permits, {
              steps: 2000,
              waitToUpdateMap: true,
              onEachFeature: onEachFeature,
              formatDate: function(date){
                return moment(date).format("YYYY-MM-DD");
              },
              pointToLayer: function (feature, latlng) {
                return L.circleMarker(latlng, permitsStyle(feature));
              }
            });  
            for (prop in permits) {
                if (!permits.hasOwnProperty(prop)) {
                        continue;
                 }
                if (feature.properties.purp === "Agricultural") {
                    agLayer.push(permits[i]);
                }
            };
            timeline.addTo(map);
        });

Then use an unordered list with id'd links and an onClick that would allow the user to choose which arrays are active and which aren't?

I tried this but kept getting Reference error: feature is not defined.

I feel like I'm reaching. It doesn't help that my geojson is huge (40 000 records), which is the biggest reason why I want users to be able to toggle layers on and off.

Thoughts?

License?

Hi, are you releasing this project as open source?

If you're not particular, I recommend adding the MIT license, which is available here: http://opensource.org/licenses/MIT

The standard place for your license is LICENSE.txt (or LICENSE.md) in your project root.

Thanks!

Nick

1.0.0 Beta, error: Cannot read 'classList'

Here is a screen shot of the error.

image

Although the documentation does not call for it, it seems that .addTimelines is a public method in the source, and that is how you add the Timelayer to the TimeLinreSlider, that line (38) is where I am getting this error.

38: timeSlider.addTimelines([timeLayer]);

define(['leaflet', 'timeline'],
 function (LEAFLET, TIMELINE) {
     var myself = function () {
         var self = this;
         var timeLayer;
         var timeSlider;
         var carMarkerOptions = {
             radius: 0
         };

         this.setup = function () {
         }
         this.load = function () {
             if (typeof timeLayer != 'undefined') {
                 console.log('remove the timeline layer');
                 Mapper.layerControl.removeLayer(timeLayer);
                 Mapper.theMap.removeLayer(timeLayer);
             }
             var data = Settings.geojson;
             var steps = data.samples;
             var ticks = (steps < 500);
             var duration = data.duration;
             timeLayer = new L.Timeline(data);

             timeSlider = new L.TimelineSliderControl( {
                 style: this.styler,
                 formatOutput: function (date) {
                     return date.toISOString();
                 },
                 onEachFeature: this.setupFeature,
                 //filter: this.show,
                 pointToLayer: this.setupMarker,
                 steps: steps * 5,
                 duration: duration,
                 showTicks: ticks,
                 waitToUpdateMap: false
             });
             timeSlider.addTimelines([timeLayer]);
             timeLayer.addTo(Mapper.theMap);
             timeSlider.addTo(Mapper.theMap);
             timeLayer.on('change', this.newTime);
             Mapper.layerControl.addOverlay(timeLayer, "Playback");
         }
         this.show = function (feature, layer) {
             var type = feature.properties.type;
             switch (type) {
                 case "Oxford.GPS":
                     return false;
                 default:
                     return true;
             }
         }
         this.setupFeature = function (feature, layer) {
             switch (feature.properties.type) {
                 case "Oxford.GPS":
                     return;
                 default:
                     layer.bindPopup(Tools.popText(feature.properties), { maxWidth: 500 });
             }
         }
         this.setupMarker = function (feature, latlng) {
             switch (feature.properties.type) {
                 case "Oxford.GPS":
                     return L.circleMarker(latlng, carMarkerOptions);
                 default:
                     return L.circleMarker(latlng, carMarkerOptions);
             }
         }
         this.styler = function (feature) {
             switch (feature.properties.type) {
                 case "demo":
                     return self.demoStyle(feature);
                 case "Oxford.GPS":
                     return { "opacity": 0.4 };
                 case "IBEO.Objects":
                     return self.lineStyle(feature);
                 case "SVS":
                     return self.polyStyle(feature);
                 default:
                     alert("overlay.styler: unknown feature type: " + feature.properties.type);
                     return { "opacity": 0.4 }
             }
         }
         this.newTime = function (e) {
             var currentTime = timeLayer.time;
             var currentLayers = timeLayer.displayedLayers;
             $.each(currentLayers, function (index, layer) {
                 var bag = layer.geoJSON.properties;
                 var type = bag.type;
                 var loc = layer.geoJSON.geometry.coordinates;
                 switch (type) {
                     case "Oxford.GPS":
                         Overlays.doGPS(loc, bag);
                         break;
                     case "IBEO.Objects":
                         break;
                     case "SVS":
                         break;
                     default:
                         console.log("overlays.newTime: unknown GeoJSON type: " + type);
                 }
             });
         }
         this.doGPS = function (loc, props) {
             CarState.lat = loc[1];
             CarState.lon = loc[0];
             CarState.alt = loc[2];
             CarState.heading = props.heading;
             CarState.time = props.start;
             CarState.valid = props.valid;
             switch (props.correction) {
                 case 0:
                     CarState.correction = "None";
                     break;
                 case 1:
                     CarState.correction = "WAAS";
                     break;
                 case 2:
                     CarState.correction = "Differential";
                     break;
                 case 3:
                     CarState.correction = "RTK";
                     break;
                 case 4:
                     CarState.correction = "Other";
                     break;
             }
             Mapper.update();
         }
         this.demoStyle = function (feature) {
             var color = "#FFF";
             if (feature.properties.confidence == '0.9') {
                 color = "#FF0000";
             } else if (feature.properties.confidence == '0.75') {
                 color = "#FFFF00";
             } else if (feature.properties.confidence == '0.5') {
                 color = "#00FF00";
             }
             return {
                 "color": color,
                 "weight": 2,
                 "opacity": 0.4
             };
         }
         this.lineStyle = function (feature) {
             var color = "Crimson";
             var opacity = (feature.properties.confidence != null) ? feature.properties.confidence : 100;
             return {
                 "color": color,
                 "weight": 2,
                 "opacity": opacity
             };
         }
         this.polyStyle = function (feature) {
             var color = "YellowGreen";
             var opacity = (feature.properties.confidence != null) ? feature.properties.confidence : 100;
             return {
                 "color": "Black",
                 "weight": 1,
                 "fillOpacity": opacity,
                 "fillColor": color
             };
         }
     };
     return new myself();
 });

Playback function does not work

Hi! just sending more feedback.

my timeline works great but playback function does not work at all..

here's my code:

its timeline + heatmaplayer



<html>
  <head>
    <title>Leaflet.timeline</title>
    <script src="../lib/leaflet.js"></script>


    <script src="../lib/moment.js"></script>
    <script src="../lib/leaflet.timeline.js"></script>


    <link href="../lib/leaflet.css" rel="stylesheet">
    <link href="../lib/leaflet.timeline.css" rel="stylesheet">
    <script src="../heatmap/build/heatmap.js"></script>
    <script src="../heatmap/plugins/leaflet-heatmap.js"></script>


    <style>
      @import url(http://fonts.googleapis.com/css?family=Open+Sans); 
      html, body{
        margin: 0;
        padding: 0;
        font-family: "Open Sans", sans-serif;
      }
      #info{
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: 15vw;
        margin: 10px;
      }
      #map{
        position: fixed;
        top: 0;
        left: 20vw;
        bottom: 0;
        right: 0;
      }
      .leaflet-bottom.leaflet-left{
        width: 98%;
      }
      .leaflet-control-container .leaflet-timeline-controls{
        box-sizing: border-box;
        width: 100%;

        margin-bottom: 15px;
      }
    </style>
  </head>

  <body>

    <div id="info">
      <h2>Detecciรณn de anomalรญas tรฉrmicas</h2>
      <p>Mediante el anรกlisis de imรกgenes satelitales sobre las Concesiones de explotaciรณn de hidrocarburos. La detecciรณn de una anomalรญa tรฉrmica implica una probabilidad de venteo.</p>
      <ul id="displayed-list"></ul>
    </div>

    <div id="map"></div>

    <script>


    var Esri_WorldImagery = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
    attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
    });

    var gmaps_spa= L.tileLayer('https://mts1.google.com/vt/lyrs=m&hl=es&gl=AR&src=app&rlbl=1&x={x}&y={y}&z={z}',{
    attribution: 'Map data &copy;2014 Google, Inav/Geosistemas SRL'});










    // heatmap
      <?php
$Conn =  pg_connect(--CONNECTION--);
$sql_vent="--QUERY--";
$result_vent= pg_query($Conn, $sql_vent);
$cant = pg_num_rows($result_vent);
$indu = 0;
$xmlshmap[] = '';
while ($row2 = pg_fetch_array($result_vent, NULL, PGSQL_ASSOC)) {
$xmlshmap[$indu] =$row2['feature'];
$indu++;
}
$heatmap_comma = implode(",", $xmlshmap);

?>

    var testData  = {
  data: [
  <?php 
  echo $heatmap_comma;
  ?>]
};



var cfg = {
  // radius should be small ONLY if scaleRadius is true (or small radius is intended)
  // if scaleRadius is false it will be the constant radius used in pixels
  "radius": 0.3,
  "maxOpacity": .6, 
  // scales the radius based on map zoom
  "scaleRadius": true, 
  // if set to false the heatmap uses the global maximum for colorization
  // if activated: uses the data maximum within the current map boundaries 
  //   (there will always be a red spot with useLocalExtremas true)
  "useLocalExtrema": true,
  // which field name in your data represents the latitude - default "lat"
  latField: 'lat',
  // which field name in your data represents the longitude - default "lng"
  lngField: 'lng',
  // which field name in your data represents the data value - default "value"
  valueField: 'count'
};


var heatmapLayer = new HeatmapOverlay(cfg);



      var map = L.map('map', {
        layers: [Esri_WorldImagery,heatmapLayer],
        center: new L.LatLng(-40.433823,-63.371094),
        zoom: 4,
        maxBounds: [[90,-180], [-90, 180]]
      });



heatmapLayer.setData(testData);

    var baseMaps = {
    "ESRI Satelital": Esri_WorldImagery,
    'Google Calle':gmaps_spa
    };

    var overlayMaps = {
    "Mapa Calor": heatmapLayer
};

L.control.layers(baseMaps, overlayMaps).addTo(map);


///heatmap







//////////


      function updateList(timeline){
        var displayed = timeline.getDisplayed();
        var list = document.getElementById('displayed-list');
        list.innerHTML = "";
        displayed.forEach(function(quake){
          var li = document.createElement('li');
          li.innerHTML = quake.properties.title;
          list.appendChild(li);
        });
      }


      function eqfeed_callback(data){
        // wrangle data into format Leaflet.timeline expects
        // earthquake data only has a time, so we'll use that as a "start"
        // and the "end" will be that + some value based on magnitude
        data.features.forEach(function(quake){

          quake.properties.start = quake.properties.time;
          quake.properties.end   = quake.properties.time;  // time + 1 * 1800000;
        });

        var timeline = L.timeline(data, {


        enablePlayback : true,
        steps: 8000,
        duration: 8000,
        waitToUpdateMap:false,

          formatDate: function(date){

            return moment(date).format("YYYY-MM-DD");
          },


          pointToLayer: function(data, latlng){

            return L.circleMarker(latlng, {

              radius: 9,
              color: "#FFFFFF",
              fillColor:"#8C45FF",
              "fillOpacity": 0.9
            }).bindPopup(data.properties.title+'<a href="'+data.properties.url+'"><br>Descargar informe</a>');
          }
        });


        timeline.addTo(map);
        timeline.on('change', function(e){
          updateList(e.target);
        });
        updateList(timeline);
      }










    </script>


<script>

<?php
$Conn =  pg_connect(--CONNECTION--);
$sql_vent="--QUERY--";
$result_vent= pg_query($Conn, $sql_vent) or die("Error en la consulta");
$cant = pg_num_rows($result_vent);
$indu = 0;
$xmlsvent[] = '';
while ($row2 = pg_fetch_array($result_vent, NULL, PGSQL_ASSOC)) {
$xmlsvent[$indu] =$row2['feature'];
$indu++;
}
$venteos_comma = implode(",", $xmlsvent);
?>
eqfeed_callback({"type":"FeatureCollection","metadata":{"generated":1421867571 ,"url":"http://sig.se.gob.ar","title":"Venteos Detectados S.E.","status":200,"api":"1.0.13","count":<?php echo $cant; ?>},"features":[
<?php echo $venteos_comma;?>



],"bbox":[-174.767,-17.0355,0,154.7646,65.149,201.8]});
</script>




  </body>
</html>

historical dates

Hi there - thank for the plugin!

I'm working with pre-1970 dates, which seems not to work properly. The slider won't play back or select dates properly, and it gets stuck on 1970-01-01.

Could pre-1970 dates be added easily?

Many thanks

An in-range update of webpack is breaking the build ๐Ÿšจ

Version 3.8.1 of webpack was just published.

Branch Build failing ๐Ÿšจ
Dependency webpack
Current Version 3.8.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

webpack is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • โŒ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Release Notes v3.8.1

Bugfixes:

  • add missing keys to stats schema for validation
Commits

The new version differs by 3 commits.

  • b8e6b4a 3.8.1
  • bb5a072 Merge pull request #5840 from webpack/bugfix/missing-stats-keys
  • c4bb0f4 add missing stats keys

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those donโ€™t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot ๐ŸŒด

Leaflet.timeline in a website using webpack

Hi,
I wonder wether it's possible to use leaflet.timeline in my website project by installing it with webpack?
I tried
npm install --save leaflet.timeline
and some files got copied into the node_modules sub directory.
But importing leaflet.timeline into my website's js file using
import ltl from 'leaflet.timeline';
leads to an
Module not found: Error: Can't resolve 'leaflet.timeline' in ...
message when I try to build it with webpack.
What am I doing wrong?
Or isn't it possible this way?
Do I have to build the leaflet.timeline.js by my self and copy it manually into my website and require it using <script>-tags?

An in-range update of babel-preset-env is breaking the build ๐Ÿšจ

Version 1.3.0 of babel-preset-env just got published.

Branch Build failing ๐Ÿšจ
Dependency babel-preset-env
Current Version 1.2.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-preset-env is โ€œonlyโ€ a devDependency of this project it might not break production or downstream projects, but โ€œonlyโ€ your build or test tools โ€“ preventing new deploys or publishes.

I recommend you give this issue a high priority. Iโ€™m sure you can resolve this ๐Ÿ’ช


Status Details
  • โŒ continuous-integration/travis-ci/push The Travis CI build failed Details
Release Notes v1.3.0

v1.3.0 (2017-03-30)

๐Ÿ› Bug Fix

We now properly check for Symbol.species support in ArrayBuffer and include the
polyfill if necessary. This should, as a side effect, fix ArrayBuffer-related
errors on IE9.

๐Ÿ’… Polish

We've simplified things by adding electron as a target instead of doing a bunch of
things at runtime. Electron targets should now also be displayed in the debug output.

If you are targeting the node environment exclusively, the always-included web polyfills
(like dom.iterable, and a few others) will now no longer be included.

๐Ÿ“ Documentation

๐Ÿ  Internal

  • npmignore: Add related to build data and codecov. (#216) (@yavorsky)
Commits

The new version differs by 8 commits .

  • 8b2dc4f 1.3.0
  • 6ebf857 Update changelog
  • 046f326 Add check for ArrayBuffer[Symbol.species] (#233)
  • aead61c Fill data with electron as a target. (#229)
  • 48a329b separate default builtins for platforms (#226)
  • a4d585c remove deprecated projects (#223) [skip ci]
  • 88cbe17 Merge pull request #216 from babel/update-npmignore
  • cf94af3 npmignore: Add related to build data and codecov.

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot ๐ŸŒด

Multiple GeoJSON timeline layers, with a single timeline control

I really like the simplicity and speed of your plug in. There is a much more complex one for leaflet: https://github.com/socib/Leaflet.TimeDimension but I see no advantages for GeoJSON with it. Except for one feature I could really use (unless I am missing something, and it is already possible).

How can I have multiple GeoJSON (actually your sub-class timeline) all controlled synchronounsly from one timeline control? Yes, I could manage the visibility within the layer via properties, but then I lose out on all the layer control plugins (tree, select) and and the other features that come with leveraging the native Leaflet layer model.

I have not dived into the source, but it seems like this would be a great feature for those who need to compare event streams and look for conjunctions of events.

Display range

Hello,

Is it possible to display a range with Leaflet.timeline?
The idea would be to display all the earthquakes which happened between 14:00:00 and 16:30:00.

Thanks

Add more events, event feedback

Right now only the L.Timeline layer has an event, and it doesn't tell you anything (though you can access most of what you might want to know directly through the L.Timeline object).

Would be nice to have the slider control also trigger events, and pass data through the events as well (layer event could tell you the displayed shapes, control event could tell you all displayed shapes for all layers, e.g.)

From #23

Any way to do a timeline from a set of TileLayers?

I've got a RESTful API pushing .png-based TileLayers and associated metadata (datetime, lat/lon, etc.)

I'd like to create a time slider or animation to display them as per the user's inputs.

What is a good starting point?

Playback only plays backwards

Hi!

I've seriously been waiting for something like this for ages. Thank you for putting the work into it.

One thing, though. I seem to have gotten the timeline to work, at least the draggable part, but the play button will only go backwards. If I press play as soon as the page loads, nothing happens. If I drag the circle to anywhere along the timeline and then press play, the timeline and dots play perfectly, but in reverse.

Any ideas?

Link: http://pennybeames.net/maps/PermitsTOTime.html

Code:

      var timeline = L.timeline(permits, {
          formatDate: function(date){
            return moment(date).format("YYYY-MM-DD");
          },
            pointToLayer: function (feature, latlng) {
            return L.circleMarker(latlng, permitsStyle(feature));},
            onEachFeature: onEachFeature
        });
        timeline.addTo(map);

Issue with ticks not being refreshed

Hi,

I think I have found an issue with the refresh of the timeline ticks. I am building an interactive map that allows to load different sets of data for the timeline. However only the first time the Timeline is rendered the ticks display correctly. Subsequently even creating completely new instances of the timeline does not reset the ticks but adds them on top of one another. I have pinpointed the issue to the fact that the "times" property of the Timeline was not reset upon initialisation of the timeline. Unfortunately I am not familiar with cofeescript so can not submit a pull request. here is what I have changed in the JS file to make it work.

initialize: function(timedGeoJSON, options) {
      this.times = [];
     ...
    },

Hope this will help in fixing the bug.

Kind regards

Jusef

Multiple timelines controlled by layer control

Hi all,
I created several timelines for several days and want to control them by means of something like L.control.layers(),addTo(), i.e. when I choose "timeline1", only "timeline1" should be visible etc.
I'm only able to control the L.circleMarker's..

My question: Is it possible to connect the whole timeline "box" with a layer control?

Thanks in advance!

Timeline features not removed on change with multiple timeline layers

I'm using the new 1.0.0-beta framework which allows multiple timeline layers to be controlled by a single TimeSliderControl. When a single timeline layer is controlled by the slider, everything works as expected. However, when two layers are added to the TimeSliderControl, it looks like features are not removed correctly on the map. Initial inspection shows that in the multiple timeline case, timeline.getDisplayed() returns an empty array when there are certainly items on the map. This prevents them from being removed in the Timeline.updateDisplayedLayers() method.

Add value start/end hooks

Right now when the time is set in the range of a feature, the feature is inserted. When the time is set outside of the range of the feature, it's removed.

This behavior could be configurable -- perhaps to color data when the time is right, and make it greyscale when not?

From @rpavery on gitter

V1.0.0beta not working?

Can you write a more basic example of how to set up this plugin on a leaflet map? Also, some of the older versions of this plugin don't seem to work with the 1.0beta.

More ways to display the data

The timeline works great, thank you for all your work! I have a suggestion for enhancing the system. Instead of having just a single mode of making data visible/invisible it would be great to have more ways to display the data. Here are a few exmaples of what I mean:

1= Object appears at startTime and disappears at stopTime (default value)
2= Object starts visible and disappears after startTime (before demolition of house)
3= Object starts invisible and appears after stopTime (finished house)
4= Object starts visible, disappears after startTime and becomes visible after stopTime
5= Object starts invisible and stays invisible until stopTime, when it appears
6= Object starts invisible, appears at start time and stays visible after stop time
7= Object is visible the entire time (the ability to have data that is visible the whole time mixed with time coded data)

Also it would be great to have styles for the events, for example:
timeline.event1.startStyle = (weight: 1, color: "#000000", opacity: 1, fillColor: "#babababa", fillOpacity: 0.3)
timeline.event1.stopStyle = (weight: 2, color: "#000000", opacity: 1, fillColor: "#babababa", fillOpacity: 0.5)

formatOutput change

Thank you for this great timeline.
I was wondering, is it possible to add a set string to the displayed value on the timeslider control?
For example, I am displaying prehistoric events, and to do that, I am adding "-00" to the values in the geojson file (like "-003000"), and thus it displays - in front ("-3000").
However, I would like the timeslider control to display for example "3000 BCE" instead of "-3000". Is that possible?
I thought I found the place to do that with formatOutput like this:
L.TimelineSliderControl = L.Control.extend({
initialize: function() {
var t = arguments.length <= 0 || void 0 === arguments[0] ? {} : arguments[0],
e = {
duration: 5,
enableKeyboardControls: !0,
enablePlayback: !0,
formatOutput: function(t) {
return "" + (t || " BCE")
}, ...etc. ....
but it doesn't do anything to the displayed timestamp on the timeslider.
I also tried different combinations like:
return " BCE" + (t || โ€โ€)
return "" + (t || โ€โ€) + " BCE"
return "" + (t || โ€โ€) || " BCE"
return "" + (t || โ€โ€) & " BCE"
etc., but nothing seems to change on the timeslider display.

Should be done in the CSS instead? And in that case where and how?
If it's possible, the best thing would be if it would also display AD with positive numbers.

Thanks :)

some of the sources not available

in the earthqukes.html file, leaflet-src.js, leaflet.timeline.js and leaflet.css could not be found within the downloaded folder.

I replaced leaflet-src.js with

<script src="https://unpkg.com/[email protected]/dist/leaflet.js" integrity="sha512-lInM/apFSqyy1o6s89K4iQUKg6ppXEgsVxT35HbzUupEVRh2Eu9Wdl4tHj7dZO0s1uvplcYGmt3498TtHq+log==" crossorigin=""></script>

and

leaflet.css with

it worked.

but i need clarification if leaflet.timeline.js is the same as Timeline.js in src folder?

and what abput TimelineSliderControl.js? when do we use it?

really hope for an answer. thanks

Version 10 of node.js has been released

Version 10 of Node.js (code name Dubnium) has been released! ๐ŸŽŠ

To see what happens to your code in Node.js 10, Greenkeeper has created a branch with the following changes:

  • Added the new Node.js version to your .travis.yml

If youโ€™re interested in upgrading this repo to Node.js 10, you can open a PR with these changes. Please note that this issue is just intended as a friendly reminder and the PR as a possible starting point for getting your code running on Node.js 10.

More information on this issue

Greenkeeper has checked the engines key in any package.json file, the .nvmrc file, and the .travis.yml file, if present.

  • engines was only updated if it defined a single version, not a range.
  • .nvmrc was updated to Node.js 10
  • .travis.yml was only changed if there was a root-level node_js that didnโ€™t already include Node.js 10, such as node or lts/*. In this case, the new version was appended to the list. We didnโ€™t touch job or matrix configurations because these tend to be quite specific and complex, and itโ€™s difficult to infer what the intentions were.

For many simpler .travis.yml configurations, this PR should suffice as-is, but depending on what youโ€™re doing it may require additional work or may not be applicable at all. Weโ€™re also aware that you may have good reasons to not update to Node.js 10, which is why this was sent as an issue and not a pull request. Feel free to delete it without comment, Iโ€™m a humble robot and wonโ€™t feel rejected ๐Ÿค–


FAQ and help

There is a collection of frequently asked questions. If those donโ€™t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot ๐ŸŒด

nice! need get popup info from each itm

Hi this is really a great plugin,

i was wondering how can i add a simple popup info from each element (Earthquakes demo for example), on click over each eartquake on map to display a simple popup with the info related to each earthquake?

thanks!!

An in-range update of cross-env is breaking the build ๐Ÿšจ

Version 3.2.0 of cross-env just got published.

Branch Build failing ๐Ÿšจ
Dependency cross-env
Current Version 3.1.4
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As cross-env is โ€œonlyโ€ a devDependency of this project it might not break production or downstream projects, but โ€œonlyโ€ your build or test tools โ€“ preventing new deploys or publishes.

I recommend you give this issue a high priority. Iโ€™m sure you can resolve this ๐Ÿ’ช


Status Details
  • โŒ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Release Notes v3.2.0

<a name"3.2.0">

3.2.0 (2017-03-04)

Features

  • revamp: revamp the entire lib (backward compatible) (#63) (dad00c46)
Commits

The new version differs by 4 commits .

  • dad00c4 feat(revamp): revamp the entire lib (backward compatible) (#63)
  • e33a85c docs(README): Add doc for cross-var. (#58)
  • 5e590ec docs(README): added how to use cross-env to run npm sub-scripts (#53)
  • afdb2de docs(README): mention Bashย onย Windows (#49)

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot ๐ŸŒด

Getting the correct date

Hi, the thing is working great,

thou i got a strange issue:

im getting date for each point from a postgresql table like this:

extract(epoch from ven.fecha at time zone 'utc')

for example:
sql:
select to_timestamp(1230955200) ;
result:
2009-01-03 02:00:00-02

So great, i'm using that timestamp, but it gets really all confused:

http://i.imgur.com/73yxR97.png

so i noticed that earthquake example got a similiar date timestamp but with 13 characters, not 10.

so i just added 3 zeros at the end, and everything works great now

i'm still wondering whats the correct way to extract date columns to use with this plugin

correct timestamp: 1230955200 + three zeros = 1230955200000
that got my date label at timebar OK.

ranges is undefined

Need to have this return an empty array:

if (node === null || node.max < value) {
        return;
      }

Next / Previous buttons strange behaviour

Hi @skeate, thanks for making a great plugin :)

I was looking at your demos and I noticed something odd with the way the next/prev buttons work in the country borders demo. I click on the next button and it takes me a long way across the timeline and then starts to just cycle back and forth between two points around that time. If I try to use the prev button it jumps back and then gets stuck in another loop on successive clicks. Is this just an issue with the data for that map? The other demo works as expected.

Another thing I see with the use of the next/prev buttons is that using them doesn't update the date/time display on the far right of the slider. Is this expected to work? Or would you like a PR for a new feature?

Webpack won't build the required JS and CSS files

In earthquakes.html file, the following files are linked:

<script src="leaflet-src.js"></script>
<script src="leaflet.timeline.min.js"></script>
<link href="leaflet.css" rel="stylesheet">

While I opened up in the browser, it's 404 Not found.

In terminal, the webpack build was successful, but no files are copied to examples/ directory. Could someone help me what am I missing?

phpstorm64_2017-03-22_17-59-57

Update examples that are linked to

(This plugin is great and I'm looking forward to using it!)

Examples such as the borders are slightly out of sync with the examples in master and the docs. This is slightly confusing because I often view-source on examples.

layer control and timeline out of sync

Thank you for a great timeline plugin.
I have several different layers on my map showing GeoJSON data through time with the timeline and it's working great. However, when I try to add a layer control where these layers can be switched on/off, it seems the layer control is not synchronizing with the timeline. The polygons are synchronized, but the different marker layers seem to not "listen" to the layer control and the timeline. When clicked on and then off in the layer control, the markers do not disappear from the map as they should when they are off time range, and they kind of "accumulate" on the map instead.

I tried playing around with layer/feature groupings and add them to the timecontrol, but then I just keep getting an error saying "Cannot read property 'filter' of undefined" in leaflet.timeline.min.js
and also referring to my own code line 624 (see image).
error_message

I am kind of stuck on figuring out the problem at this point. I hope someone can help.

You can see the map and the whole code here: http://prehistoricmap.com/homeland/test_icon.html

Changing properties of features over time

I have a list of features that change over time. (Long/Lat stay the same, size of features increases and decreases at certain dates).

At the moment I use multiple features for the same location with corresponding start/end times. I would prefer them to be one feature with changing properties.

Is there an easy way to do this?

Database "caching" of GeoJSON layers

With the ability to handle multiple GeoJSON layers in the Timeline (#23) comes the risk of running out of memory by keeping all data in core.

I did some work a year+ ago on using PouchDB (layers over indexdb) to cache raster tiles. http://gis.stackexchange.com/questions/62070/offline-slippy-map-tiles-database-for-leaflet.

@calvinmetcalf has done some great work on serving GeoJSON from PouchDB (https://github.com/calvinmetcalf/leaflet.pouch)

Now we have the refactoring and separation of the Timeline from the GeoJSON layers (#23). What about being able to use a PouchDB back-end DB for dealing with 20MB+ (I have gone as big as 1GB for my PouchDB raster work). My experience has been that serving from the browser-internal database is pretty fast. There is lots of locality of reference.

One approach would be to extend the leaflet.GeoJSON.PouchDB plugin with an additional index of the Date field, and do searches for start>date>end as map based query indexes. The trick is that both Tileline and Leaflet.GeoJSON.Pouch are peer sub-classes of GeoJSON layer.

Perhaps easier would be to just have option on Leaflet.Timeliner to have a method called:

fetchGeoJSON(layer, start, end) 

which which would be fired to load the GeoJSON data on demand. That would leave it to the user to manage the Database. I worked with a similar (very short, and cute) thing called functional.tilelayer by @ismyrnow https://github.com/ismyrnow/Leaflet.functionaltilelayer that did async calls to a DB to return tiles. In this case it would return GeoJSON, not tiles. The advantage here is that one could also invoke remote calls instead of just to the local DB.

I don't think we would have to go to GeoJSON tiles for now, but that is also a possibility for some.

Can the timeline be autostarted?

For my use it would be nice to have it run when loaded.

Thank you. I've almost got it going as it should. Took me a while to figure out how to load a regular GeoJSON. Newbie problem.

setTime does not update slider knob position

Calling setTime on timelineSliderControl does not cause the position of the slider knob to update. Clicking prev/next will cause the knob to move correctly to the ticks before/after the updated time; however, the play button will play it from the original start time, not from the updated time.

Also, it seems that the setTime method needs to be called on both timelineSliderControl and timeline in order to update both. Perhaps setting the time of the control should automatically update the timeline, since one typically wouldn't want the timeline and slider to be out of sync.

Confused about the scripts

The demo at http://skeate.github.io/Leaflet.timeline/earthquakes.html as well as the code in /examples use a different JavaScript file than shown in /src.
leaflet.timeline.js is only found in the demo while Timeline.js and TimelineSliderControl.js are not used. I'm guessing the demo is more up to date.

The Readme refers to the two "unused" JavaScript files too.

The problem with leaflet.timeline.js is that it is minified and therefore difficult to debug. I can't remember where I found this.

Thank you for listening and looking forward to using this script.

Update: made my own unminified leaflet.timeline.js by putting Timeline.js, TimelineSliderControl.js and IntervalTree together in one script. Works with the demo, so will proceed to experiment. Plus I get the same error when used in my app, but hope will have better luck debugging.

SASS syntax?

I'm using SCSS (not taking sides)

I ran sass-convert leaflet.timeline.sass leaflet.timeline.scss and got complaints about the ; in the SASS. I'd change it except I can't really keep my own git straight and I don't pretend to know the correct syntax. The converter worked after removing all semi-colons. Thanks for listening

Trouble loading GeoJSON files into Timeline

Hello people.
I am doing a project, where I need to load some geoJSON files into a Leaflet map, shown in time with points and polygons.
So far we had succes with loading and showing the GeoJSON files on the map:

<!DOCTYPE html>
<html>
  <head>
      <script 
         src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js">
      </script>
      
      <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
      
      <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

      <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>
      
      <!--<link rel="stylesheet" href="http://prehistoricmap.com/Timeline/dist/leaflet.timeline.min.css" /> -->
      
      <!--<script 
         src="http://prehistoricmap.com/Timeline/dist/leaflet.timeline.min.js">
      </script> -->
      
      
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width">
      
      <script>
var map;
function addDataToMap(data, map) {
    var dataLayer = L.geoJson(data);
    dataLayer.addTo(map);
}

$.getJSON("http://prehistoricmap.com/thanh_lab/latlong4.geojson", function(data) { addDataToMap(data, map); }); 

$(document).ready(function () {
  
map = L.map('map').setView([0, 0], 2);
  L.tileLayer('https://{s}.tiles.mapbox.com/v3/ebrelsford.ho06j5h0/{z}/{x}/{y}.png', {
      maxZoom: 18,
      attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery &copy; <a href="http://mapbox.com">Mapbox</a>'
      }).addTo(map);
 
 var slider = L.timelineSliderControl({
    formatOutput: function(date){
      return moment(date).format("YYYY");
    }
  });
  map.addControl(slider);

  var pointTimeline = L.timeline(points);
  pointTimeline.addTo(map);
  slider.addTimelines(pointTimeline);
});
    </script>

  </head>
  <body>
    <div id="map"></div>
  </body>
</html>

We also had success with showing the data in time with the Timeline (when copying the data directly into the HTML code):

<!DOCTYPE html>
<html>
  <head>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
    <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>

    <script src="http://prehistoricmap.com/thanh_lab/Leaflet.timeline/dist/leaflet.timeline.min.js"></script>
    <link rel="stylesheet" href="http://prehistoricmap.com/thanh_lab/Leaflet.timeline/dist/leaflet.timeline.min.css"/>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">

    <script>
var map;

var points = {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "start": "1970", "end": "1972" }, "geometry": { "type": "Point", "coordinates": [ 11.924550479340329, 55.94619451008279 ] } },
{ "type": "Feature", "properties": { "start": "1975", "end": "1976" }, "geometry": { "type": "Point", "coordinates": [ 12.06219628503271, 55.909617190392566 ] } },
{ "type": "Feature", "properties": { "start": "1979", "end": "1980" }, "geometry": { "type": "Point", "coordinates": [ 12.06219628503271, 55.909617190392566 ] } },
{ "type": "Feature", "properties": { "start": "1980", "end": "1985" }, "geometry": { "type": "Point", "coordinates": [ 12.284822339303718, 55.639778377234506 ] } }
]
};

$(document).ready(function () {

  map = L.map('map').setView([0, 0], 2);

  L.tileLayer('https://{s}.tiles.mapbox.com/v3/ebrelsford.ho06j5h0/{z}/{x}/{y}.png', {
      maxZoom: 18,
      attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery &copy; <a href="http://mapbox.com">Mapbox</a>'
      }).addTo(map);

  var slider = L.timelineSliderControl({
    formatOutput: function(date){
      return moment(date).format("YYYY");
    }
  });
  map.addControl(slider);

  var pointTimeline = L.timeline(points);
  pointTimeline.addTo(map);
  slider.addTimelines(pointTimeline);
});
    </script>

  </head>
  <body>
    <div id="map"></div>
  </body>
</html>

The problem right now is combining these two things:
Loading a GeoJSON file and showing it with the Timeline.

So far the code looks like this:

<!DOCTYPE html>
<html>
  <head>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
    <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>

    <script src="http://prehistoricmap.com/thanh_lab/Leaflet.timeline/dist/leaflet.timeline.min.js"></script>
    <link rel="stylesheet" href="http://prehistoricmap.com/thanh_lab/Leaflet.timeline/dist/leaflet.timeline.min.css"/>
    <script src="http://prehistoricmap.com/thanh_lab/leaflet.ajax.min.js"></script>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">

    <script>
var map;

var points= new L.GeoJSON.AJAX("http://prehistoricmap.com/thanh_lab/clean4.geojson");


$(document).ready(function () {
 
  map = L.map('map').setView([0, 0], 2);

  L.tileLayer('https://{s}.tiles.mapbox.com/v3/ebrelsford.ho06j5h0/{z}/{x}/{y}.png', {
      maxZoom: 18,
      attribution: 'Map data &copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery &copy; <a href="http://mapbox.com">Mapbox</a>'
      }).addTo(map);

  var slider = L.timelineSliderControl({
    formatOutput: function(date){
      return moment(date).format("YYYY");
    }
  });
  map.addControl(slider);

  var pointTimeline = L.timeline(points);
  pointTimeline.addTo(map);
  slider.addTimelines(pointTimeline);
});
    </script>

  </head>
  <body>
    <div id="map"></div>
  </body>
</html>

This shows a map but no data. The Timeline is shown, but does not work.
We have tried to take all the code from the GeoJSON and copy paste it into the exactly as it is in the file, and that works.
There must be a problem with the link between the GeoJSON file and making it load into the Timeline.

We hope somebody can help.

map.removeLayer( ..timeline.. ) generates error

When I add the timeline layer to the L.LayerControl and then try to uncheck/check the layer to hide. I get an error. This also happens in another place in my code where I want to destroy the layer and load a new layer.

I really need to be able to load/unload the L.timeliner, since users will be trying out different GeoJSON data in sequence, and need to refresh the layer (as well as hide it).

             if (typeof timeLayer != 'undefined') {
                 console.log('remove the timeline layer');
                 layerControl.removeLayer(timeLayer);
                 theMap.removeLayer(timeLayer);
             }

At first I was really surprised at the chrome debugger which was showing me the error occurred in coffeescript. [I only copied the /dist folder to my project]. But now I see that timeline.js has the coffeescript at the bottom. Unfortunately, I do not speak coffeescript so I do not know what is the problem.

Uncaught TypeError: this.timeSliderControl.removeFrom is not a function
L.Timeline.L.GeoJSON.extend.onRemove @ leaflet.timeline.coffee:185
L.Map.include.removeLayer @ leaflet-src.js:2569
L.Control.Layers.L.Control.extend._onInputClick @ leaflet-src.js:9110

The error is coming from the statement "@timeSliderControl.removeFrom map"

  onRemove: (map) ->
    L.GeoJSON.prototype.onRemove.call this, map
    @timeSliderControl.removeFrom map

  getDisplayed: -> @ranges.lookup @time

Drag not working on mobile

On mobile chrome, android and ios, dragging the slider is not working. Touching on the bar will set the slider correctly though. Also, thank you very much for the plugin.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.