python -m SimpleHTTPServer 8080
sass --watch style.scss:style.css
Last active
January 2, 2016 10:59
-
-
Save elidupuis/8294043 to your computer and use it in GitHub Desktop.
The Circles of Life
This file contains 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 lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>How your perception of time changes as you age</title> | |
<link href='http://fonts.googleapis.com/css?family=Source+Sans+Pro:300,600,700,900|Sacramento' rel='stylesheet' type='text/css'> | |
<link rel="stylesheet" href="style.css"> | |
</head> | |
<body> | |
<div class="l-wrap"> | |
<div class="l-side"> | |
<p class="text"> | |
<span class="text-when hilite">When</span> | |
<span class="text-ur hilite">you are</span> | |
<input class="fill-hilite" type="number" id="currentAge" value="30" min="1" max="150" required> | |
<span class="text-years">years old</span> | |
<span class="text-fancy"><span class="stars">every</span></span> | |
<input type="number" id="referenceAge" value="1" min="1" max="150"> | |
<select id="referenceRatio"> ↓ | |
<option value="365">days</option> | |
<option value="52">weeks</option> | |
<option value="12">months</option> | |
<option value="1" selected>years</option> | |
</select> | |
<span class="text-represent">represents</span> | |
<span class="text-result hilite" id="relativeTime"></span> | |
<span class="text-fancy"><span class="slashes">of your</span></span> | |
<span class="text-life">life</span> | |
</p> | |
</div> | |
<div class="l-main"> | |
<div id="vis"></div> | |
</div> | |
</div> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<script src="vis.js"></script> | |
</body> | |
</html> |
This file contains 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
$hilite: #8cdc0d; | |
$font: 'Source Sans Pro', helvetica, sans-serif; | |
$font-alt: 'Sacramento', cursive; | |
body { | |
font-family: $font; | |
padding: 0; | |
margin: 0; | |
min-height: 500px; | |
} | |
form { | |
position: relative; | |
z-index: 2; | |
} | |
.l-wrap { | |
width: 860px; | |
margin: auto; | |
position: relative; | |
} | |
.l-side { | |
width: 170px; | |
margin: 50px 0 0; | |
} | |
.l-main { | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
right: 0; | |
left: 230px; | |
} | |
.hilite { | |
color: $hilite; | |
} | |
.fill-hilite { | |
background: $hilite; | |
} | |
/* ========================================================================== | |
Text | |
========================================================================== */ | |
.text { | |
font-size: 38px; | |
text-transform: uppercase; | |
position: relative; | |
font-weight: 300; | |
} | |
.text-when { | |
font-size: 50px; | |
font-weight: 600; | |
} | |
.text-ur { | |
font-size: 21px; | |
font-weight: 600; | |
position: absolute; | |
width: 50px; | |
line-height: 0.9; | |
top: 0.65em; | |
right: -0.15em; | |
text-align: right; | |
} | |
.text-years { | |
font-size: 38px; | |
font-weight: 300; | |
} | |
.text-represent { | |
font-size: 32px; | |
} | |
.text-result { | |
font-size: 62px; | |
font-weight: 700; | |
text-align: center; | |
display: block; | |
margin-top: -0.25em; | |
> span { | |
font-size: 30px; | |
vertical-align: super; | |
} | |
} | |
.text-fancy { | |
font-family: $font-alt; | |
font-weight: 400; | |
text-transform: lowercase; | |
font-size: 34px; | |
text-align: center; | |
display: block; | |
width: 100%; | |
margin: -0.35em 0 0; | |
} | |
.text-life { | |
font-size: 96px; | |
font-weight: 900; | |
letter-spacing: -4px; | |
display: block; | |
margin-top: -0.25em; | |
} | |
.stars { | |
position: relative; | |
&:before, | |
&:after { | |
content: url(http://f.cl.ly/items/3n340c381j2d2D0x3W1r/stars.png); | |
position: absolute; | |
top: 0; | |
} | |
&:before { | |
left: 110%; | |
} | |
&:after { | |
right: 110%; | |
} | |
} | |
.slashes { | |
position: relative; | |
&:before, | |
&:after { | |
content: url(http://f.cl.ly/items/0B3f1Y0V2w0n3f0F120m/slashes.png); | |
position: absolute; | |
top: 0; | |
} | |
&:before { | |
left: 110%; | |
} | |
&:after { | |
right: 95%; | |
} | |
} | |
/* | |
inputs, selects | |
========================================================================== */ | |
input { | |
background: #000; | |
color: #fff; | |
display: block; | |
width: 100%; | |
text-align: center; | |
border: 0; | |
font-size: 70px; | |
} | |
select { | |
background: #000; | |
color: #fff; | |
width: 100%; | |
border-radius: 0; | |
padding: 0.25em 1em; | |
font-size: 25px; | |
font-family: $font-alt; | |
/* http://uplifted.net/programming/change-default-select-dropdown-style-just-css/ */ | |
border: 0 !important; | |
-webkit-appearance: none; | |
-mox-appearance: none; | |
} | |
/* ========================================================================== | |
Vis | |
========================================================================== */ | |
#vis { | |
position: absolute; | |
top: 0; | |
bottom: 0; | |
right: 0; | |
left: 0; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: $hilite; | |
shape-rendering: crispEdges;; | |
} | |
.tick text { | |
font-size: 12px; | |
fill: $hilite; | |
} | |
.outer { | |
fill: black; | |
} | |
.inner { | |
fill: $hilite; | |
} | |
line { | |
stroke: $hilite; | |
stroke-width: 1px; | |
} |
This file contains 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
var doit = (function(){ | |
var d = document; | |
var currentAge = d.getElementById('currentAge'); | |
var referenceAge = d.getElementById('referenceAge'); | |
var referenceRatio = d.getElementById('referenceRatio'); | |
var relativeTime = d.getElementById('relativeTime'); | |
var output = d.getElementById('output') | |
// d3 varibales | |
var margin = {top: 0, right: 30, bottom: 20, left: 30} | |
var svg, x, xAxis, radius, width, height, outerCircle, innerCircle, refLine | |
function calculate () { | |
var age = +currentAge.value; | |
var reference = +referenceAge.value; | |
var conversion = 1/(+referenceRatio.value); | |
var ratio, percentage | |
// make sure reference age is equal or less than actual age | |
if (reference > age) { | |
reference = age; | |
referenceAge.value = age; | |
} | |
// calulate the proportion of current age | |
ratio = (reference * conversion) / age; | |
percentage = ratio * 100; | |
// convert to percentage and display | |
relativeTime.innerHTML = displayPercentage(percentage) | |
// update visualization | |
buildVis(age, (reference * conversion)) | |
} | |
// format percentage decimal places | |
function displayPercentage (p) { | |
if (p < 1) { | |
return p.toFixed(3) + '<span>%</span>' | |
} | |
return p.toFixed(1) + '<span>%</span>' | |
} | |
// attach event listeners | |
[currentAge, referenceAge, referenceRatio].forEach(function(el) { | |
el.addEventListener('change', handleChange) | |
el.addEventListener('keyup', handleChange) | |
}) | |
function handleChange (e) { | |
e.preventDefault() | |
calculate() | |
} | |
// first run vis setup | |
initVis(+currentAge.value) | |
// kick it off for the first time | |
calculate() | |
//////////////////////////////////////////////////////////////////// | |
// d3... | |
//////////////////////////////////////////////////////////////////// | |
function getSize () { | |
// var el = d.getElementById('vis') | |
// var w = el.offsetWidth || 600 | |
// var h = el.offsetHeight || 600 | |
// return d3.min([w, h]) | |
return 660 | |
} | |
// set up the D3 elements and inital state. | |
function initVis (max) { | |
width = getSize() - margin.left - margin.right; | |
height = getSize() - margin.top - margin.bottom; | |
radius = d3.scale.sqrt() | |
.domain([0, max]) | |
.range([0, width/2]); | |
svg = d3.select("#vis").append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
xAxis = d3.svg.axis() | |
.scale(radius) | |
.orient("bottom"); | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(" + width/2 + "," + height + ")") | |
.call(xAxis); | |
outerCircle = svg.append('circle') | |
.attr('class', "circle outer") | |
.attr('cx', width/2) | |
.attr('cy', height/2) | |
.attr('r', width/2) | |
innerCircle = svg.append('circle') | |
.attr('class', "circle inner") | |
.attr('cx', width/2) | |
.attr('cy', height/2) | |
svg.append('line') | |
.attr('class', 'line') | |
.attr('x1', width/2) | |
.attr('y1', height/2) | |
.attr('x2', width/2) | |
.attr('y2', height) | |
refLine = svg.append('line') | |
.attr('class', 'line') | |
.attr('y1', height/2) | |
.attr('y2', height) | |
} | |
// update the visualization | |
function buildVis (max, relative) { | |
width = getSize() - margin.left - margin.right; | |
height = getSize() - margin.top - margin.bottom; | |
radius.domain([0, max]) | |
.range([0, width/2]); | |
svg | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
svg.select(".x.axis") | |
.transition() | |
.call(xAxis); | |
innerCircle | |
.transition() | |
.attr('r', radius(relative)) | |
refLine | |
.transition() | |
.attr('x1', radius(relative) + (width/2)-0.5) | |
.attr('x2', radius(relative) + (width/2)-0.5) | |
} | |
}) | |
document.addEventListener("DOMContentLoaded", function(event) { | |
doit() | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment