block by rveciana 6a50336f5fffee99f29e1881ebee5e97

Map scroller associated with video position

Full Screen

Play the video once loaded to see the example.

I took the idea from this tweet.

I created the path with the help of Geojson.io, and it’s not exact. The idea was showing the possibility of syncing the video with the path.

The video is a timelapse (I don’t dare driving this fast) taken at the paradise valley close to Agadir, Morocco. Go there if you have the opportunity!

The code should be improved. I think that some times don’t work if play is pressed beffore the video ends loading.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<html>
<style>
video {
  vertical-align: top;
}
</style>
<body>
  <video width="320" height="240" controls>
   <source src="valee.mp4" type="video/mp4">
 Your browser does not support the video tag.
 </video>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="//d3js.org/d3.geo.tile.v0.min.js"></script>
<script>

var width = 450,
    height = 500;
var projection = d3.geo.mercator()
    .center([-9.52, 30.5809])
    .scale(1000000);

var path = d3.geo.path()
    .projection(projection);

var tile = d3.geo.tile()
    .scale(projection.scale() * 2 * Math.PI)
    .translate(projection([0, 0]))
    .zoomDelta((window.devicePixelRatio || 1) - .5);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

  var tiles = tile();

  var defs = svg.append("defs");

  svg.append("g")
    .selectAll("image")
      .data(tiles)
    .enter().append("image")
      .attr("xlink:href", function(d) {
        return "//b.tile.openstreetmap.org/" + d[2] + "/" + d[0] + "/" + d[1] + ".png";
       })
      .attr("width", Math.round(tiles.scale) + 1)
      .attr("height", Math.round(tiles.scale) + 1)
      .attr("x", function(d) { return Math.round((d[0] + tiles.translate[0]) * tiles.scale); })
      .attr("y", function(d) { return Math.round((d[1] + tiles.translate[1]) * tiles.scale); });
d3.json("path.json", function(error, route) {
  var pathLength;
  var routeLine = svg.append("path")
    .attr("d",path(route))
    .attr("stroke","#f44")
    .attr("stroke-width","4px")
    .attr("fill","none")
    .style('stroke-dasharray', function(d) {
      pathLength = d3.select(this).node().getTotalLength();
      return pathLength + 'px, ' + pathLength + 'px';
    })
    .style('stroke-dashoffset', function(d) {
      return d3.select(this).node().getTotalLength() + 'px';
     });

     var video = d3.select("video")
     .on("play", function(){
       var currentTime = this.currentTime;
       var duration = this.duration;

       routeLine
       .style('stroke-dashoffset', function(d) {
         return pathLength*(1-(currentTime/duration))+'px';
       });

       routeLine
        .transition()
        .duration(1000*(duration - currentTime))
        .ease("linear")
        .style('stroke-dashoffset', '0px');
     })
     .on("pause", function(){
       routeLine
        .transition();
     })
     .on("seeked", function(){
       var currentTime = this.currentTime;
       var duration = this.duration;
       routeLine
       .style('stroke-dashoffset', function(d) {
         return pathLength*(1-(currentTime/duration))+'px';
       });
     });
});
</script>


</body>
</html>

path.json

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "properties": {},
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            -9.532442092895506,
            30.58705352749691
          ],
          [
            -9.53287124633789,
            30.586443949981696
          ],
          [
            -9.53390121459961,
            30.58550186809996
          ],
          [
            -9.534158706665039,
            30.58511394936984
          ],
          [
            -9.533751010894775,
            30.583783930510254
          ],
          [
            -9.533751010894775,
            30.583285168733482
          ],
          [
            -9.534029960632324,
            30.582527784832426
          ],
          [
            -9.535961151123047,
            30.581419407482862
          ],
          [
            -9.536540508270264,
            30.581068418680566
          ],
          [
            -9.53664779663086,
            30.580680482210255
          ],
          [
            -9.53611135482788,
            30.579461243198555
          ],
          [
            -9.535660743713379,
            30.578777723712577
          ],
          [
            -9.534780979156494,
            30.578278936181885
          ],
          [
            -9.534609317779541,
            30.577724724805247
          ],
          [
            -9.53611135482788,
            30.575784960042622
          ],
          [
            -9.537484645843506,
            30.5752676828861
          ],
          [
            -9.537763595581055,
            30.57449176197788
          ],
          [
            -9.53832149505615,
            30.574214645863282
          ],
          [
            -9.538364410400389,
            30.57349414025959
          ],
          [
            -9.538471698760986,
            30.572699730440863
          ]
        ]
      }
    }
  ]
}