An example of using Torque, CartoDB’s time lapse tool

For a recent project we were provided with a GIS shapefile of developments (primarily houses) in a suburban neighborhood in Ithaca, NY. We created static maps to show change through time with color coded dots for different time windows but we thought that the dataset was a perfect opportunity to show off CartoDB’s time series tool called Torque. For details on Torque you can visit CartoDB’s website or the Torque GitHub page.

Creating a Torque visualization

Creating a time-lapse visualization with Torque is surprisingly easy, particularly if you’re willing to accept the defaults and don’t need to customize the infowindow and slider. If your data is small, you can test it out using CartoDB’s free account and signing up is quick. Here are the steps for creating a visualization:

1. Upload your data: CartoDB has done a nice job with this, you can select a local file, drag and drop or even use Dropbox. Your data should have a numeric field representing time. In our case this was year.

upload

2. Create a visualization by clicking on your layer and then clicking on the ‘Visualization’ button in the top right corner.

visualize

3. Give the visualization a name and save

save_viz

4. Click on ‘Map View’ on your new visualization and in the table of contents on the right, under ‘Wizards’ choose ‘Torque’ and choose your time field where it says ‘column’

torque

If you’re happy with your visualization it can be shared at this stage. Simply click on the ‘Share’ button in the top right of the visualization and copy the URL and paste in to an e-mail to collaborators.

Customize the display using the CartoDB API

If you want to make further tweaks to your visualization, there is a very good post for the different settings by Azavea here. We also borrowed heavily (stole?) in this example from Javi Santana’s code on GitHub.

One setting in particular that we think CartoDB should add is the ability to change the slider units. As it stands, the default slider does not display actual data (in our case, year) but time steps (1,2,3…). In order to do this we are not able to simply use the URL or iFrame options for sharing the visualization, we had to make the changes using the CartoDB API and adding custom code which, again, was stolen from CartoDB’s Javi Santana.

In the custom code we start by adding a div to store the year information:

<div id="torque-time"></div>

Then we create the initialization function to add the layers and create the map:

function initialize() {
      var map = new google.maps.Map(document.getElementById('map'), {
          center: new google.maps.LatLng(42.425,-76.42),
          zoom: 12,
          mapTypeId:google.maps.MapTypeId.TERRAIN,
          mapTypeControl:false,
          minZoom:1,
          scaleControl: false,
          streetViewControl: false,
          overviewMapControl: false,
      });

      var map_style = {};
      map_style.google_maps_customization_style = [
          {
              stylers:[
                  { invert_lightness:true },
                  { weight:1 },
                  { saturation:-100 },
                  { lightness:-40 }
              ]
          },
          {
              elementType:"labels",
              stylers:[
                  { visibility:"simplified" }
              ]
          }
      ];


      // define the torque layer style using cartocss
      var CARTOCSS = [
          'Map {',
          '-torque-time-attribute: "date";',
          '-torque-aggregation-function: "count(cartodb_id)";',
          '-torque-frame-count: 512;',
          '-torque-animation-duration: 30;',
          '-torque-resolution: 1',
		  '-torque-data-aggregation:cumulative;',
          '}',
		  '#buildings_temp{',
  		  'comp-op: lighter;',
  		  'marker-opacity: 1;',
  		  'marker-line-color: #850200;',
  		  'marker-line-width: 1;',
  		  'marker-line-opacity: 1;',
 		  'marker-type: ellipse;',
  		  'marker-width: 4;',
  		  'marker-fill: #D6301D;',
		  '}',
		  '#buildings_temp[frame-offset=1] {',
 		  'marker-width:6;',
		  'marker-opacity:0.5;',
		  '}'
      ].join('\n');


      var torqueLayer = new torque.GMapsTorqueLayer({
        user       : 'XX',
        table      : 'XX',
        cartocss: CARTOCSS,
        map: map
      });

      torqueLayer.setMap(map);
      init_slider(torqueLayer);
      torqueLayer.play();
    }

And then create the function that puts the year in the torque-time div:

function init_slider(torqueLayer) {
        var torqueTime = $('#torque-time');
        $("#torque-slider").slider({
            min: 0,
            max: torqueLayer.options.steps,
            value: 0,
            step: 1,
            slide: function(event, ui){
              var step = ui.value;
              torqueLayer.setStep(step);
            }
        });

        // each time time changes, move the slider
        torqueLayer.on('change:time', function(changes) {
          $("#torque-slider" ).slider({ value: changes.step });
		  
          var month_year = changes.time.toString().substr(4).split(' ');

		  //$('#torque-time').text(month_year[0] + " - " + month_year[2]);
		  $('#torque-time').text(month_year[2]);
		 
          console.log(torqueLayer.getTime());
        });

        // play-pause toggle
        $("#torque-pause").click(function(){
          torqueLayer.toggle();
          $(this).toggleClass('playing');
        });
      };

And we execute the code when the window is done loading:

window.onload = initialize;

And here is what we created:

2 responses

  1. Zev,
    the customization that you did in the second part (“Customize the display using the CartoDB API”), is it something that can be done using CartoDB interface (CartoCSS Editor)? Or do you need to host the map to make the amendments?

    • Good question. I depends which piece of customization you’re talking about but mostly you would need to use the API by hosting it yourself. It has been more than a year since I wrote this post, though, and perhaps there are now additional tweaks available through the CartoDB interface.

Leave a Reply

Your email address will not be published. Required fields are marked *