block by vlandham 8743890

8743890

Full Screen

A short code excerpt from this visualization I created for the longform article “Iouri Podladtchikov – You only fly once” by the Neue Zürcher Zeitung.

It’s a very simple way to create an interactive animation based on video material. Hover over the image to go through the animation.

I used Final Cut Pro to export the frames of a short video sequence, which I then stitched together into a single film strip using ImageMagick: convert folder-of-stills/* +append filmstrip.jpg

index.html

<!DOCTYPE html>
<head>
  <title>Scrubbing</title>
  <meta charset="utf-8">
  <script src="//d3js.org/d3.v3.min.js"></script>
  <style type="text/css">
  .viewer {
    border: 5px solid #6d95ad;
    border-radius: 110px;
    cursor: ew-resize;
    margin: 60px auto 0 auto;
    overflow: hidden;
  }
  </style>
</head>
<body>
<script>
var frameWidth = 0,
    numberOfFrames = 0,
    posToFrame = d3.scale.linear().clamp(true);

var viewer = d3.select('body').append('div')
    .attr('class', 'viewer');

var frames = viewer.append('img')
    .attr('src', 'filmstrip.jpg')
    .on('load', init);

function init() {
  frameWidth = this.offsetHeight;
  numberOfFrames = this.offsetWidth / this.offsetHeight;
  posToFrame
    .interpolate(interpolateFrame)
    .domain([frameWidth, 0])
    .range([0, ((numberOfFrames - 1) * -frameWidth)]);

  viewer
    .style({
      width: px(frameWidth),
      height: px(frameWidth)
    })
    .on('mousemove', onMove)
    .on('touchmove', onMove)
    .on('mouseleave', onRelease)
    .on('touchend', onRelease)
}

function onMove(){ frameAtPos(d3.mouse(this)[0]) }
function onRelease(){ frameAtPos(frameWidth) }

function frameAtPos(pos) {
  frames.style('margin-left', posToFrame(pos) + 'px');
}

function interpolateFrame(a, b) {
  return function(t) {
    return Math.floor(((b - a) * t)/frameWidth) * frameWidth
  }
}

function px(val){
  return val + 'px';
}
</script>