TODO: redo just using d3.interpolateZoom, duh.
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<link rel="stylesheet" type="text/css" href="main.css"/>
<body>
<div class="container">
<img src="photo.jpg">
</div>
</body>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js" charset="utf-8"></script>
<script src="//cdn.rawgit.com/gka/d3-jetpack/master/d3-jetpack.js" charset="utf-8"></script>
<script src="main.js" charset="utf-8"></script>
</html>
html, body {
margin: 0;
padding: 0;
height: 5000px;
}
.container {
position: fixed;
}
.container img {
position: absolute;
}
var container = d3.select('.container')
.style('width', innerWidth + 'px')
.style('height', innerHeight + 'px')
.node();
var image = document.querySelector("img");
var start = {
zoom: [.7, .7],
center: [.5, .5]
}
var end = {
zoom: [4, 4],
center: [.33, .33]
}
var zoomerTween = zoomerTweener(start, end);
var scrollScale = d3.scale.linear()
.domain([0,1000])
.clamp(true);
window.addEventListener('scroll', handleScroll);
handleScroll();
function handleScroll() {
var t = scrollScale(scrollY);
var coords = zoomerTween(t);
d3.select(image)
.style('left', coords.x + 'px')
.style('top', coords.y + 'px')
.style('width', coords.width + 'px')
.style('height', coords.height + 'px');
}
function zoomerTweener(start, end) {
var zoomLerp = lerp(start.zoom, end.zoom);
var centerLerp = lerp(start.center, end.center);
return function(t) {
var zoom = zoomLerp(t*t);
var center = centerLerp(t);
return zoomer(zoom, center);
}
}
function zoomer(zoom, center) {
var x = d3.scale.linear()
.domain([center[0] * image.naturalWidth, center[0] * image.naturalWidth + 1])
.range([container.offsetWidth/2, container.offsetWidth/2 + zoom[0]])
var y = d3.scale.linear()
.domain([center[1] * image.naturalHeight, center[1] * image.naturalHeight + 1])
.range([container.offsetHeight/2, container.offsetHeight/2 + zoom[1]]);
return {
x: x(0),
y: y(0),
width: image.naturalWidth * zoom[0],
height: image.naturalHeight * zoom[1]
}
}
function lerp(array0,array1) {
var scales = d3.range(array0.length).map(function(n) {
return d3.scale.linear()
.range([array0[n], array1[n]]);
});
return function(t) {
return scales.map(function(d,i) {
return d(t);
})
}
}
// https://gist.github.com/Rich-Harris/5894545
// UM NOT CURRENTLY BEING USED LOL but would be nice to ditch d3
var linearScale = function ( domain, range ) {
var d0 = domain[0], r0 = range[0], multiplier = ( range[1] - r0 ) / ( domain[1] - d0 );
// special case
if ( r0 === range[1] ) {
return function () {
return r0;
};
}
return function ( num ) {
return r0 + ( multiplier * ( num - d0 ) );
};
};