Skip to content

Instantly share code, notes, and snippets.

@vlandham
Forked from grossbart/README.md
Created January 31, 2014 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vlandham/8743890 to your computer and use it in GitHub Desktop.
Save vlandham/8743890 to your computer and use it in GitHub Desktop.

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

<!DOCTYPE html>
<head>
<title>Scrubbing</title>
<meta charset="utf-8">
<script src="http://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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment