Skip to content

Instantly share code, notes, and snippets.

@abernier
Last active October 7, 2015 08:38
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 abernier/3136589 to your computer and use it in GitHub Desktop.
Save abernier/3136589 to your computer and use it in GitHub Desktop.
flipbook
#
# datas
#
drawing = false
flips = ({
progress: 1
target: -1
} for [1..10])
mouse =
x: null
y: null
#
# Book dimensions
#
BOOK_MARGIN = .05
PAGE_MARGIN = .1
factor = .5
BOOK_OUTERWIDTH = factor * $(window).width()
BOOK_OUTERHEIGHT = factor * $(window).height()
BOOK_WIDTH = BOOK_OUTERWIDTH * (1 - BOOK_MARGIN)
BOOK_HEIGHT = BOOK_OUTERHEIGHT * (1 - BOOK_MARGIN)
SPINE_WIDTH = factor * 50
PAGE_THICKNESS = SPINE_WIDTH / (flips.length - 1)
PAGE_WIDTH = (BOOK_WIDTH/2 - SPINE_WIDTH) * (1 - PAGE_MARGIN) + SPINE_WIDTH/2
PAGE_HEIGHT = BOOK_HEIGHT * (1 - 2*PAGE_MARGIN)
PAGE_Y = (BOOK_HEIGHT - PAGE_HEIGHT) / 2
#
# Create the SVG
#
svg = d3.select("body").append("svg:svg")
.attr("width", BOOK_OUTERWIDTH)
.attr("height", BOOK_OUTERHEIGHT)
#
# Draw the book outline
#
svg.append('svg:rect')
.attr('class', 'book')
.attr('x', (BOOK_OUTERWIDTH - BOOK_WIDTH) / 2)
.attr('y', (BOOK_OUTERHEIGHT - BOOK_HEIGHT) / 2)
.attr('width', BOOK_WIDTH)
.attr('height', BOOK_HEIGHT)
#
# Spine
#
svg.append('svg:rect')
.attr('class', 'spine')
.attr('x', BOOK_OUTERWIDTH / 2 - SPINE_WIDTH / 2)
.attr('y', (BOOK_OUTERHEIGHT - BOOK_HEIGHT) / 2)
.attr('width', SPINE_WIDTH)
.attr('height', BOOK_HEIGHT)
#
# Make a new coordinates system
#
svg = svg.append("svg:g")
.attr("transform", "translate(#{BOOK_OUTERWIDTH / 2}, #{(BOOK_OUTERHEIGHT - PAGE_HEIGHT) / 2})")
#
# Draw the pages outlines
#
svg.append('svg:rect')
.attr('class', 'page left')
.attr('x', -PAGE_WIDTH)
.attr('y', 0)
.attr('width', PAGE_WIDTH)
.attr('height', PAGE_HEIGHT)
svg.append('svg:rect')
.attr('class', 'page right')
.attr('x', 0)
.attr('y', 0)
.attr('width', PAGE_WIDTH)
.attr('height', PAGE_HEIGHT)
#
# mouse behaviors
#
svg.on('mousemove', (d, i) ->
e = d3.event
mouse.x = e.pageX - $(@).offset().left - PAGE_WIDTH
mouse.y = e.pageY - $(@).offset().top
)
###svg.on('mousedown', (d, i) ->
if (Math.abs(mouse.x) < PAGE_WIDTH)
flip.target = mouse.x / PAGE_WIDTH for flip in flips
draw()
)###
#
# Draw the flips
#
draw = ->
fold = svg.selectAll(".fold")
.data(flips)
#
# New folds
#
fold.enter()
.append("svg:path")
.attr('class', 'fold')
.on('click', (d, i) ->
flips[k].target = -1 for k in [Math.max(i-1, 0)..0]
flips[k].target = 1 for k in [i..flips.length-1]
draw()
)
.each(swipe)
#
# Existing folds
#
fold
.each(swipe)
#
# Deleted folds
#
fold.exit()
.remove()
swipe = (d, i) ->
d3.select(@)
# .attr('d', (d) -> shape(d.progress))
.transition()
.ease('cubic-in-out')
.delay(d.target < d.progress and i * 100 / flips.length or (flips.length - i) * 100 / flips.length)
.duration(750)
.attrTween("d", shapeTween)
#
# Compute the path for the fold (progress ∈ [-1, 1])
#
shape = (d, i) ->
i = flips.indexOf(d)
n = flips.length
strength = 1 - Math.abs(d.progress)
foldWidth = (PAGE_WIDTH * 0.5) * (1 - d.progress)
foldX = PAGE_WIDTH * d.progress + foldWidth - SPINE_WIDTH / 2 + i * PAGE_THICKNESS
verticalOutdent = (BOOK_OUTERHEIGHT - PAGE_HEIGHT) / 4 * .66 * strength
"M #{foldX} 0 L #{foldX} #{PAGE_HEIGHT} Q #{foldX} #{PAGE_HEIGHT + verticalOutdent * 2}, #{foldX - foldWidth} #{PAGE_HEIGHT + verticalOutdent} L #{foldX - foldWidth} #{-verticalOutdent} Q #{foldX} #{-verticalOutdent * 2}, #{foldX} 0"
#
# Tween the shape
#
shapeTween = (d, i) ->
#
# Encapsulate an interpolation function into a closure
#
# from datum's progress to target
#
interpolate = d3.interpolate(d.progress, d.target)
(t) ->
# Make progress :)
newProgress = interpolate(t)
# Update datum's progress value
d.progress = newProgress
# draw the shape
shape(d, i)
draw()
$('input').change((event) ->
flip.target = event.target.value / 100 for flip in flips
draw()
)
window.flips = flips
window.draw = draw
html,
body {height:100%;}
html {display:table; width:100%;}
body {display:table-cell; margin:0; overflow:hidden; text-align:center; vertical-align:middle;}
svg {display:inline-block; stroke: black; background-color:infoBackground;}
rect,
path {stroke: black; fill:white;}
rect {stroke-dasharray:10,3;}
path {cursor:pointer;}
path:hover {stroke:red}
input {display:block; margin:0 auto; width:33%;}
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<title></title>
<link rel="stylesheet" href="album.css">
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="http://d3js.org/d3.v2.min.js"></script>
<script src="http://jashkenas.github.com/coffee-script/extras/coffee-script.js"></script>
<script type="text/coffeescript" src="album.coffee"></script>
</head>
<body>
<!--<p><input type="range" min="-100" max="100" step="1" value="-1"></p>-->
</body>
</html>
@biovisualize
Copy link

Could you please fix the broken link to d3.js, using http://d3js.org/d3.v2.min.js ?

@abernier
Copy link
Author

abernier commented Feb 4, 2013

@biovisualize done, thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment