Skip to content

Instantly share code, notes, and snippets.

@briantjacobs
Forked from grossbart/README.md
Last active September 21, 2015 16:16
Show Gist options
  • Save briantjacobs/01b4adfdfbbb3491f0b5 to your computer and use it in GitHub Desktop.
Save briantjacobs/01b4adfdfbbb3491f0b5 to your computer and use it in GitHub Desktop.
Kinetoscope

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 crop and 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>Kinetoscope</title>
<meta charset="utf-8">
<script src="http://d3js.org/d3.v3.min.js"></script>
<style type="text/css">
.viewer {
border: 5px solid #6d95ad;
cursor: ew-resize;
margin: 60px auto 0 auto;
opacity: 0;
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
.on('mousemove', onMove)
.on('mouseleave', onRelease)
.on('touchstart', function(){ d3.event.preventDefault() })
.on('touchmove', onMove)
.on('touchend', onRelease)
.style({
width: pct(100),
height: px(frameWidth)
})
.transition().duration(1000)
.style('opacity', 1)
.transition()
.style({
'border-radius': px(frameWidth),
width: px(frameWidth)
})
}
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 pct(val){ return val + '%'; }
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