Scrolling will interpolate between two paths
Last active
August 29, 2015 14:27
-
-
Save dannyko/45b56550308f89849101 to your computer and use it in GitHub Desktop.
svg-path-scroll-demo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<style> | |
body { | |
min-width: 640px; | |
height: 100% ; | |
padding: 0; | |
border: 0; | |
margin: 0; | |
overflow-y: scroll; | |
} | |
div { | |
border:0; | |
padding:0; | |
display: block; | |
} | |
.svgDiv { | |
position: fixed ; | |
left: 0; | |
top: 0; | |
width: 100% ; | |
height: 100% ; | |
} | |
</style> | |
</head> | |
<body> | |
<script> | |
/* | |
* setup the SVG visualization: | |
*/ | |
var svgns = "http://www.w3.org/2000/svg" ; | |
var svgContainer = document.createElement('div') ; // this is the div that contains all of the content divs | |
svgContainer.setAttribute('class', 'svgDiv') ; // set the ID of this div so that the CSS rules will apply | |
var svg = document.createElementNS(svgns, 'svg') ; | |
svg.setAttribute('width', '100%') ; | |
svg.setAttribute('height', '100%') ; | |
svg.setAttribute('viewBox', '0 0 1 1') ; | |
var p = "M 0.1,0.1 L 0.1,0.2 L 0.2,0.2 L 0.2,0.1 0.1,0.1" ; // a square | |
var q = "M 0.1,0 L 0.1,0.4 L 0.3,0.4 L 0.3,0 0.1,0" ; // a rectangle | |
var path = document.createElementNS(svgns, 'path') ; | |
path.setAttribute('fill', 'none') ; | |
path.setAttribute('stroke', 'black') ; | |
path.setAttribute('stroke-width', '.01px') ; | |
path.setAttribute('d', p) ; // initialize path data | |
svg.appendChild(path) ; | |
svgContainer.appendChild(svg) ; | |
document.body.appendChild(svgContainer) ; // add the div to the page via the DOM | |
/* | |
* update the interactive visualization on scroll: | |
*/ | |
document.body.addEventListener( | |
'wheel', | |
wheel_callback, | |
false | |
) ; | |
var precision = 0.001 ; | |
var tween = path_tween(path, q, precision) ; | |
var Nstep = 101 ; | |
var kstep = 0 ; | |
function wheel_response(delta) { | |
kstep += delta ; | |
kstep = Math.max(kstep, 0) ; | |
kstep = Math.min(kstep, Nstep) ; | |
var t = kstep / Nstep ; | |
path.setAttribute('d', tween(t)) ; | |
// console.log('delta', delta, 't', t) ; | |
} ; | |
function wheel_callback(event) { | |
var delta = 0 ; | |
if (!event) event = window.event ; | |
if (event.wheelDelta) { | |
delta = event.wheelDelta / 120 ; | |
} else if (event.detail) { | |
delta = -event.detail / 3 ; | |
} | |
if (delta) | |
wheel_response(delta) ; | |
if (event.preventDefault) | |
event.preventDefault() ; | |
event.returnValue = false ; | |
} ; | |
/* | |
* helper functions: | |
*/ | |
function path_tween(path, q, precision) { | |
var p = path.cloneNode(), | |
n0 = path.getTotalLength(), | |
n1 = (p.setAttribute("d", q), p).getTotalLength() ; | |
// Uniform sampling of distance based on specified precision. | |
var distances = [0], | |
i = 0, | |
dt = precision / Math.max(n0, n1) ; | |
while ( (i += dt) < 1 ) | |
distances.push(i) ; | |
distances.push(1) ; | |
// Compute point-interpolators at each distance. | |
var points = distances.map( | |
function(t) { | |
var p0 = path.getPointAtLength(t * n0), | |
p1 = p.getPointAtLength(t * n1) ; | |
return interpolate([p0.x, p0.y], [p1.x, p1.y]) ; | |
} | |
) ; | |
return function(t) { | |
return t < 1 ? | |
"M" + points.map( | |
function(p) { return p(t) ; } | |
).join("L") | |
: q ; | |
} ; | |
} ; | |
function interpolate(a, b) { | |
var xinterp, yinterp ; | |
return function(t) { | |
xinterp = a[0] * (1 - t) + b[0] * t ; | |
yinterp = a[1] * (1 - t) + b[1] * t ; | |
return [xinterp, yinterp] ; | |
} | |
} ; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment