Skip to content

Instantly share code, notes, and snippets.

@bricof
Last active May 1, 2017 12:02
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 bricof/3ce0a03e5eb4a8591f852e815b5c1e86 to your computer and use it in GitHub Desktop.
Save bricof/3ce0a03e5eb4a8591f852e815b5c1e86 to your computer and use it in GitHub Desktop.
Unfurling UI Animation

This unfurling UI is used in the human computation section of the Stitch Fix Algorithms Tour. The svg drawing was made by Liz Cruz.

The script takes the drawn paths as starting points, and maps between their given x,y values to different x,y values as a function of time. Note that to make the animation look okay, it is best to avoid long distances between points in your path definitions - in the given svg paths, you will notice long sequences of Lx,y elements that all sit on the same straight line, which in normal static conditions would be best repaced with a single Lx,y element.

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<svg width="960" height="500">
<g id="ui" transform="translate(270,-175)">
<path fill="#fff" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M459.9,594.6 L455,594.6 L450,594.6 L445,594.6 L440,594.6 L435,594.6 L430,594.6 L425,594.6 L420,594.6 L415,594.6 L410,594.6 L405,594.6 L400,594.6 L395,594.6 L390,594.6 L385,594.6 L380,594.6 L375,594.6 L370,594.6 L365,594.6 L360,594.6 L355,594.6 L350,594.6 L345,594.6 L340,594.6 L335,594.6 L330,594.6 L325,594.6 L320,594.6 L315,594.6 L310,594.6 L305,594.6 L300,594.6 L295,594.6 L290,594.6 L285,594.6 L280,594.6 L275,594.6 L270,594.6 L265,594.6 L260,594.6 L255,594.6 L250,594.6 L245,594.6 L240,594.6 L235,594.6 L230,594.6 L225,594.6 L220,594.6 L215,594.6 L210,594.6 L205,594.6 L200,594.6 L195,594.6 L190,594.6 L185,594.6 L180,594.6 L175,594.6 L170,594.6 L165,594.6 L160,594.6 L155,594.6 L150,594.6 L145,594.6 L140,594.6 L135,594.6 L130,594.6 L125,594.6 L120,594.6 L115,594.6 L110,594.6 L105,594.6 L100,594.6 L95,594.6 L90,594.6 L85,594.6 L80,594.6 L75,594.6 L70,594.6 L65,594.6 L60,594.6 L55,594.6 L54.4,594.6 C53,594.6 51.8,593.5 51.8,592 L51.8,322.6 C51.8,321.2 52.9,320 54.4,320 L55,320 L60,320 L65,320 L70,320 L75,320 L80,320 L85,320 L90,320 L95,320 L100,320 L105,320 L110,320 L115,320 L120,320 L125,320 L130,320 L135,320 L140,320 L145,320 L150,320 L155,320 L160,320 L165,320 L170,320 L175,320 L180,320 L185,320 L190,320 L195,320 L200,320 L205,320 L210,320 L215,320 L220,320 L225,320 L230,320 L235,320 L240,320 L245,320 L250,320 L255,320 L260,320 L265,320 L270,320 L275,320 L280,320 L285,320 L290,320 L295,320 L300,320 L305,320 L310,320 L315,320 L320,320 L325,320 L330,320 L335,320 L340,320 L345,320 L350,320 L355,320 L360,320 L365,320 L370,320 L375,320 L380,320 L385,320 L390,320 L395,320 L400,320 L405,320 L410,320 L415,320 L420,320 L425,320 L430,320 L435,320 L440,320 L445,320 L450,320 L455,320 L459.9,320 C461.3,320 462.5,321.1 462.5,322.6 L462.5,592 C462.4,593.4 461.3,594.6 459.9,594.6 z"></path>
<path d="M157.1,350.8 L66.6,350.8 C65.6,350.8 64.8,349.9 64.8,348.9 S65.6,347 66.6,347 L157.1,347 C158.1,347 158.9,347.9 158.9,348.9 S158.1,350.8 157.1,350.8 z"></path>
<path d="M150.4,358.6 L66.6,358.6 C65.6,358.6 64.8,357.7 64.8,356.7 S65.6,354.8 66.6,354.8 L150.5,354.8 C151.5,354.8 152.3,355.7 152.3,356.7 S151.4,358.6 150.4,358.6 z"></path>
<path d="M157.1,366.4 L66.6,366.4 C65.6,366.4 64.8,365.5 64.8,364.5 S65.6,362.6 66.6,362.6 L157.1,362.6 C158.1,362.6 158.9,363.5 158.9,364.5 S158.1,366.4 157.1,366.4 z"></path>
<path d="M150.4,374.2 L66.6,374.2 C65.6,374.2 64.8,373.3 64.8,372.3 S65.6,370.4 66.6,370.4 L150.5,370.4 C151.5,370.4 152.3,371.3 152.3,372.3 S151.4,374.2 150.4,374.2 z"></path>
<path d="M249.6,415.2 L199,415.2 C198.4,415.2 198,414.3 198,413.3 S198.5,411.4 199,411.4 L249.6,411.4 C250.2,411.4 250.6,412.3 250.6,413.3 S250.2,415.2 249.6,415.2 z"></path>
<path d="M312.4,415.2 L261.8,415.2 C261.2,415.2 260.8,414.3 260.8,413.3 S261.3,411.4 261.8,411.4 L312.4,411.4 C313,411.4 313.4,412.3 313.4,413.3 S313,415.2 312.4,415.2 z"></path>
<path d="M375.1,415.2 L324.5,415.2 C323.9,415.2 323.5,414.3 323.5,413.3 S324,411.4 324.5,411.4 L375.1,411.4 C375.7,411.4 376.1,412.3 376.1,413.3 S375.7,415.2 375.1,415.2 z"></path>
<path d="M437.9,415.2 L387.3,415.2 C386.7,415.2 386.3,414.3 386.3,413.3 S386.8,411.4 387.3,411.4 L437.9,411.4 C438.5,411.4 438.9,412.3 438.9,413.3 S438.5,415.2 437.9,415.2 z"></path>
<path fill="#AA7CAA" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M286.1,393.7 C292.3,393.7 298.6,391.5 298.6,391.5 C298.6,387.4 296.7,378.8 296.7,378.8 C295.7,374.8 295.4,370.7 296.5,368 C297.5,365.5 297.4,363.2 297.3,361.9 C297.2,361.4 297,360.9 296.8,360.5 C295,357.9 295.5,348.8 295.5,348.8 L292.6,348.8 C292.6,348.8 294,360.7 286.2,360.4 L286.2,360.4 C278.4,360.7 279.8,348.8 279.8,348.8 L276.9,348.8 C276.9,348.8 277.5,357.9 275.6,360.5 C275.3,360.9 275.1,361.4 275.1,361.9 C275,363.2 274.9,365.5 275.9,368 C277,370.7 276.7,374.8 275.7,378.8 C275.7,378.8 273.8,387.4 273.8,391.5 C273.6,391.5 280,393.7 286.1,393.7 L286.1,393.7 z"></path>
<path fill="#F3A54A" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M368.4,370.2 C367.6,367 365.5,357.9 364.9,356.1 C364.3,354.1 362.5,351.8 360,351 L354.7,349 C354.7,349 354.5,358 349.3,360.5 C346.7,359.2 345.4,356.4 344.7,353.8 C344,351.2 344,349 344,349 L338.7,351 C337.5,351.4 336.4,352.2 335.6,353.1 C334.8,354 334.2,355.1 333.9,356.1 C333.4,357.9 331.2,367 330.4,370.2 C330.2,370.9 330.3,371.7 330.6,372.3 L336.5,386.4 C336.5,386.4 337,386.6 337.7,386.7 C337.3,388.5 337,390.3 337,391.6 C337,391.6 339.6,393.6 349.4,393.6 C359.1,393.6 361.8,391.6 361.8,391.6 C361.8,390.3 361.5,388.6 361.1,386.7 C361.8,386.6 362.3,386.4 362.3,386.4 L368.2,372.3 C368.5,371.6 368.5,370.9 368.4,370.2 z M336.4,371.6 C336.3,371.4 336.3,371.2 336.4,371 L339.2,362.4 C340.2,365.1 340.8,374.6 339.8,378.6 C339.8,378.6 339.7,378.8 339.6,379.3 L336.4,371.6 z M362.4,371.6 L359.3,379.4 C359.1,378.9 359.1,378.7 359.1,378.7 C358.1,374.8 358.7,365.2 359.7,362.5 L362.5,371.1 C362.4,371.2 362.4,371.4 362.4,371.6 z"></path>
<path fill="#CCDE66" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M420.8,361.2 C423.3,362.9 425.5,379.2 425.5,379.2 S422.7,380.6 419.5,380.6 C416.2,380.6 415.6,380.7 414.3,381.3 L412.2,375.9 L410.1,381.3 C408.8,380.7 408.2,380.6 404.9,380.6 C401.6,380.6 398.9,379.2 398.9,379.2 S401.1,362.9 403.6,361.2 C403.8,361.2 411.4,365 420.8,361.2 z"></path>
<path fill="#CCDE66" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M224.7,349.1 C221.8,349.1 218.6,348.7 217.3,348.3 L217.3,348.3 L217.3,348.3 L217.3,348.3 C217.2,348.5 217.2,348.7 217.1,349 C216.9,349.5 216.8,349.9 216.6,350.4 C216,352.1 215.6,353.5 215.3,355.3 C215.3,355.5 215.2,355.7 215.2,356 C214.8,358.9 215.3,361.6 215.8,364.5 C216.3,367.4 216.4,370.4 216.6,373.4 C216.9,377.7 216.8,382 217,386.4 L217,393.9 C217,393.9 219.2,394.4 220.3,394.4 C220.3,394.4 222.6,394.3 223.3,394 C223.3,388.8 223.3,383.5 223.3,378.3 C223.3,375.9 223.4,373.5 223.4,371.1 C223.4,368.3 223.5,365.3 223.8,362.6 L223.8,362.6 C223.8,362.6 223.9,361.9 223.9,361.4 C224,360.9 224.3,360.5 224.8,360.5 S225.6,360.9 225.7,361.4 C225.8,361.9 225.8,362.6 225.8,362.6 L225.8,362.6 C226.1,365.3 226.2,368.4 226.2,371.1 C226.2,373.5 226.3,375.9 226.3,378.3 C226.4,383.5 226.3,388.8 226.3,394 C226.9,394.4 229.3,394.4 229.3,394.4 C230.3,394.4 232.6,393.9 232.6,393.9 L232.6,386.4 C232.8,382.1 232.7,377.7 233,373.4 C233.2,370.4 233.4,367.5 233.8,364.5 C234.3,361.6 234.8,359 234.4,356 C234.4,355.8 234.3,355.6 234.3,355.3 C234,353.5 233.5,352.1 233,350.4 C232.9,350 232.7,349.5 232.5,349 C232.4,348.8 232.4,348.6 232.3,348.3 L232.3,348.3 L232.3,348.3 L232.3,348.3 C230.8,348.7 227.6,349.1 224.7,349.1"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M174,320.1 L174,594.6"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M153.9,403.5 L69.8,403.5 C67.8,403.5 66.1,401.5 66.1,398.9 L66.1,391.1 C66.1,388.6 67.7,386.5 69.8,386.5 L154,386.5 C156,386.5 157.7,388.5 157.7,391.1 L157.7,398.9 C157.6,401.4 156,403.5 153.9,403.5 z"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M140,386.6 L140,403.5"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M198,342 L251.3,342 L251.3,400.5 L198,400.5 z"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M259.5,342 L312.8,342 L312.8,400.5 L259.5,400.5 z"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M322.8,342 L376.1,342 L376.1,400.5 L322.8,400.5 z"></path>
<path fill="none" stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="M385.6,342 L438.9,342 L438.9,400.5 L385.6,400.5 z"></path>
</g>
</svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var paths_d = []
d3.selectAll("#ui > path")._groups[0].forEach(function(path_el){
paths_d.push(path_el.attributes.d.value)
})
function map_point(pt, t){
var entry_point = [525, 380]
var entry_ramp_dx = 100
var speed = 0.5
var scale = 0.8
var x2 = 10 + scale * Math.min((entry_point[0] / scale) + entry_ramp_dx,
Math.max(pt[0],
pt[0] + (entry_point[0] / scale) - (t * speed)))
var y2 = scale * pt[1] + 50
if (x2 > 425) {
y2 = entry_point[1] + Math.sin(Math.PI * 0.5 * (-1) * ((x2-625)/200)) * (y2 - entry_point[1])
}
return [x2, y2]
}
function map_path(original_path_d, map, t){
var ds = original_path_d.split(" ")
var ds2 = []
ds.forEach(function(p){
if (p == "z") {
ds2.push(p)
} else {
var leading = ""
if (!p[0].match(/[0-9\-]/)) {
leading = p[0]
p = p.substring(1)
}
var pt1 = [ +p.split(",")[0], +p.split(",")[1] ]
var pt2 = map(pt1, t)
ds2.push(leading + pt2[0] + "," + pt2[1])
}
})
return ds2.join(" ")
}
function show_ui() {
var paths = d3.selectAll("#ui > path").data(paths_d)
var timer = d3.timer(function(t){
if (t > 2000) { timer.stop() }
paths
.attr("d", function(d){ return map_path(d, map_point, t) })
})
}
function hide_ui() {
var paths = d3.selectAll("#ui > path").data(paths_d)
var timer = d3.timer(function(t){
if (t > 2000) { timer.stop() }
paths
.attr("d", function(d){ return map_path(d, map_point, 1500 - t) })
})
}
function unfurlfurl() {
show_ui()
d3.timeout(hide_ui, 2000)
}
unfurlfurl()
d3.interval(unfurlfurl, 5000)
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment