Last active
April 10, 2017 21:33
-
-
Save sara-maria/efae537119b896181c5fa8e3d4db508e to your computer and use it in GitHub Desktop.
CVCM
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
index | date | event_header | event_details | arrowheight | direction | category | align | |
---|---|---|---|---|---|---|---|---|
0 | 8/16/80 | Born | Goirle The Netherlands | 50 | down | life | left | |
1 | 1/7/98 | Graduation Secondary School | Koning Willem II college - Gymnasium | 75 | down | education | left | |
2 | 9/1/99 | Study physics | Universiteit Utrecht | 30 | down | education | left | |
3 | 7/1/02 | Bachelor Research | MRI and X-ray angiography | 100 | down | education | left | |
4 | 6/1/04 | Minor | Fundamentals of Business and Economics. Internship at Bain & Company | 30 | up | professional | right | |
5 | 6/1/05 | Master Research | MRI blood flow measurements using Arterial Spin Labeling | 35 | down | education | left | |
6 | 12/1/05 | Start PhD Research | MR Thermometry for guidance of thermal therapy | 35 | up | education | left | |
7 | 11/4/10 | PhD Defense | 30 | down | education | center | ||
8 | 4/1/11 | Postdoctoral research | Characterizing trabecular bone using MRI diffusion techniques | 40 | up | professional | left | |
9 | 6/1/14 | Value Based Health Care work | International Consortium for Health Outcomes Measurement - ICHOM | 40 | down | professional | left | |
10 | 9/1/16 | Data science & <br> Data vis | Data Science specialization @ Coursera. HTML CSS D3.js @ Udacity | 40 | up | education | left | |
11 | 11/1/19 | Entering a Mixed Reality | Learning Mixed Reality skills | 40 | down | education | left | |
12 | 11/7/21 | Creating other Realities | Creating Mixed Reality environments for creative, educational & therapeutic purposes | 55 | up | professional | left | |
13 | 3/6/26 | Nutrition | Studying the impact of nutrition and microbiome on physical and mental health | 30 | up | education | left | |
14 | 9/1/29 | Connecting knowledge | Using data visualization to raise cross-discipline and cross-cultural awareness of the connectedness of beings and ideas | 45 | down | professional | right | |
15 | 8/16/41 | Pet | Finally getting a guinea pig | 40 | down | life | left | |
16 | 6/20/54 | Dies | In my sleep <br> during a pneumonia | 40 | down | life | right |
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> | |
<head> | |
<meta charset="utf-8"> | |
<link href="https://fonts.googleapis.com/css?family=Lato:300,400" rel="stylesheet"> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<style> | |
/* | |
*{ | |
border: 1px solid orange !important; | |
} | |
*/ | |
/* | |
To fix/add: | |
- hardcoded foh in yc array (because ems --> pix) | |
- lineheight in foreign object | |
- font scaling less dramatic | |
- css separated | |
- add details on hover? | |
- make it visible on phones | |
LAYOUT FEEDBACK: | |
- instead of arrows pointing to events, maybe a thin line (Robby suggestion) | |
- arrange categories better | |
*/ | |
body{ | |
font-family: 'Lato', sans-serif; | |
font-size:100%; /* flexible baseline - commonly 16px. Then, as example, 1.25em will result in 20px */ | |
font-weight: 300; | |
margin:0; | |
height: 100vh; /*30em; /*500px;*/ | |
width: 100vw; /*full width of screen*/ /*width:1500px;*/ | |
overflow-y: hidden; | |
} | |
#wrapper { | |
width:100vw; | |
height:100vh; | |
display:block; | |
} | |
#CVheader { | |
height: 10%; /*6em; /*90px;*/ | |
width: 100%; | |
/* background-color:"red";*/ | |
/* padding-top: .2em; 4px;*/ | |
/* overflow:auto;*/ | |
} | |
#headerleft { | |
width:9em; /*300px;*/ | |
height:1.3em;/*40px;*/ | |
float:left; | |
position:absolute; | |
color:"black"; | |
background-color:#e0e0d9; | |
text-align: center; | |
border-radius: 2em; /*25px;*/ | |
} | |
#headerright { | |
width:10em; /*320px;*/ | |
height:1.3em;/*40px;*/ | |
float:right; | |
text-align: center; | |
position:absolute; | |
right: 0; | |
color:#716c6c; | |
/* border: 3px solid white;*/ | |
background-color:#444; | |
border-radius: 2em; /*25px;*/ | |
} | |
/* #headerright:hover { | |
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both; | |
transform: translate3d(0, 0, 0); | |
backface-visibility: hidden; | |
perspective: 1000px; | |
} | |
*/ | |
.hoverclass { | |
animation: shake 0.7s cubic-bezier(.36,.07,.19,.97) both; | |
transform: translate3d(0, 0, 0); | |
backface-visibility: hidden; | |
/* perspective: 1px;*/ | |
} | |
@keyframes shake { | |
10%, 90% { | |
transform: translate3d(-2px, 1px, 0); | |
} | |
20%, 80% { | |
transform: translate3d(2px, -1px, 0); | |
} | |
30%, 50%, 70% { | |
transform: translate3d(-4px, 3px, 0); | |
} | |
40%, 60% { | |
transform: translate3d(4px, 2px, 0); | |
} | |
} | |
#content { | |
height:85%; | |
/* min-height: 80%;*/ | |
} | |
#lifeline { | |
width:100vw; /* ensures it stretches the full width of the page */ | |
height:90%; | |
} | |
.category_buttons { | |
height: 2em; /*height of whole section*/ | |
display: -webkit-flex; | |
display: flex; | |
-webkit-align-items: top; | |
align-items: top; | |
-webkit-justify-content: center; | |
justify-content: center; | |
} | |
div.category_buttons div { | |
width: 8em; | |
height:1.1em; | |
line-height: 1.1em; /*needed for vertical align*/ | |
vertical-align: middle; | |
text-align: center; | |
background-color: white; | |
padding: .3em; | |
margin-left: 1em; | |
margin-right: 1em; | |
border-radius: 2em; | |
border:1px solid #9d9999; | |
color:#444; | |
font-weight: 100 | |
} | |
div.category_buttons > div:first-of-type { /*select first button "all", to be diff color*/ | |
background-color: rgb(247, 230, 210); | |
} | |
#footer { | |
text-align: center; | |
font-size: .7em; | |
width:100vw; | |
height:5%; /*2.5em;*/ | |
line-height: 2.5sem; | |
vertical-align: bottom; | |
bottom:0; | |
} | |
#rotatediv { | |
display:flex; | |
background-color:#6d6c6c; | |
display: block; | |
height: 100%; | |
width: 100%; | |
font-size: 4em; | |
color: "white"; | |
/* float:center;*/ | |
text-align: center; | |
position:fixed; | |
color:rgb(247, 230, 210); | |
vertical-align:middle; | |
} | |
h2 { | |
margin-left: 1em; /*15px;*/ | |
margin-right: 1em; /*15px;*/ | |
margin-bottom: 1em; /*15px;*/ | |
font-size: 2em; | |
} | |
h3{ | |
margin-left: 1em;/*15px;*/ | |
margin-top: 0em; | |
font-weight: 100; | |
font-size: 1em; | |
} | |
h2CV { | |
margin-bottom: .06em; | |
font-size: 1em; /*12px;*/ | |
line-height: .6em; | |
font-weight: 400; | |
color: "black"; | |
} | |
h3CV { | |
margin-top: 0em; | |
font-weight: 100; | |
font-size: .8em; /*10px;*/ | |
/* line-height: 10em;*/ | |
color: "black"; | |
} | |
a { | |
color:#494949; | |
text-decoration:none; | |
} | |
a:hover { | |
font-weight: 400; | |
} | |
.lefty {text-align: left !important;} | |
.centry {text-align: center !important;} | |
.righty {text-align: right !important;} | |
.lifelinetext{ | |
display:none; | |
} | |
/* # info was needed for mouse position testing*/ | |
/* | |
#info { | |
position: absolute; | |
bottom: 10px; | |
right: 10px; | |
background-color: black; | |
color: white; | |
padding: 25px 50px; | |
} | |
*/ | |
/*-------CATCH ROTATED SMART PHONES AND SCREENS -----------*/ | |
/* for non rotated screens: do not show rotation message */ | |
#rotatediv {display: none;} | |
/* only when orientation is in portrait mode: */ | |
@media screen and (orientation:portrait) { | |
#content {display: none;} | |
#rotatediv {display: flex;} | |
} | |
/*-------CATCH for iPHONES where body width = "vh" gives problems... -----------*/ | |
/** iPad with landscape orientation. */ | |
@media all and (device-width: 768px) and (device-height: 1024px) and (orientation:landscape){ | |
body { | |
/* width:2*1024px; always times 2--> visualization is twice width!*/ | |
} | |
} | |
/** iPhone 5 */ /*@media screen and (device-aspect-ratio: 40/71) {*/ | |
@media screen and (device-height: 568px) and (device-width: 320px) and (-webkit-min-device-pixel-ratio: 2){ | |
body { | |
/* width:2*568px; always times 2--> visualization is twice width!*/ | |
} | |
} | |
</style> | |
<script> | |
// MAIN DRAW CVCM FUNCTION! | |
function draw(data){ | |
var environment = "CV"; // to ensure colorcodings match the CV or CM page | |
//Width and height of CV visualization | |
var w = 2*window.screen.availWidth; //because the visualization is spread over two lengths of the window! | |
var h = 1/2*window.screen.availHeight; | |
var margin = {top: 0, right: 0, bottom: 0, left:0}; | |
width = w - margin.left - margin.right; | |
height = h - margin.top - margin.bottom; | |
// window.width = w - margin.left - margin.right; | |
// window.height = h - margin.top - margin.bottom; | |
//Sizing variables for lifeline visualization | |
var arrowlinewidth = 5; | |
var arrowlineheight = 60; | |
var arrowheadbasewidth = 15; | |
var arrowheadlength = 15; | |
var arrowtextdistance = 5; | |
var lifelineheight = ".7em"; | |
var relypos = 4/9; // where life line will be drawn on y axes | |
var lifelinemarginL = 40; // margin space at start of life line | |
var lifelinemarginR = 100; // margin space at end of life line | |
// Find full domains of input data | |
var lifeline_extent = d3.extent(data,function(d){ | |
return d['age']; | |
}); | |
var arrowheight_extent = d3.extent(data,function(d){ | |
return d['arrowheight']; | |
}); | |
//Setting scales | |
var xScale = d3.scale.linear() | |
.domain(lifeline_extent) | |
.range([lifelinemarginL, width-lifelinemarginR]); | |
var yScale = d3.scale.linear() | |
.domain(arrowheight_extent) | |
.range([0, height]); | |
//xScale(#years) --> # pixels on time axes | |
//xScale.invert(#pixels) --> #years | |
//xScale.invert(lifelinemargin) --> 0 years (born) | |
//xScale.invert(0) --> -1.3670886075 years (margin on left side, in years) | |
//Create SVG element that holds the CV | |
var svg = d3.select("body").select("#content") | |
.append("svg") | |
.attr("id","lifeline") | |
.attr("width", .5*width) | |
.attr("height", height) | |
.attr("viewBox", "0 0 "+.52*width+" "+height+"") | |
//Create one large horizontal life-line | |
var lifeline = svg.append("rect") | |
.attr("x", 0) | |
.attr("y", relypos*height) | |
.attr("width", width) //line across full length of div! | |
.attr("height", lifelineheight) | |
.attr("fill", "#716c6c"); | |
// CREATE ARROW GROUPS at AGE LOCATIONS | |
var lifearrows = svg.append("g") | |
.attr("id","lifearrows"); | |
var arrows = lifearrows.selectAll("g") | |
.data(data) //when I add: function(d){return d.age;},arrows at same age go missing | |
.enter() | |
.append("g") | |
.attr("transform", function(d) { return "translate(" + xScale(d.age) + ",0)" ;} ) | |
.attr("class","arrow") | |
.attr("id", function(d, i) { return ("arrow" + d.index); }) | |
arrows.append("rect") | |
.attr("width", arrowlinewidth) | |
.attr("height", arrowlineheight) | |
.attr("x", 0) | |
.attr("y", relypos*height) | |
.attr("height", function(d) { return d.arrowheight; }) | |
.attr("fill", "#716c6c") | |
arrows.append("path") | |
.attr('d', function(d) { | |
var x = - .5*arrowheadbasewidth + .5*arrowlinewidth; | |
var y = relypos*height + d.arrowheight; // starting coord. of triangle | |
var lr = arrowheadbasewidth, ld = arrowheadlength, ll = -.5*arrowheadbasewidth; | |
return 'M ' + x +' '+ y + ' l ' + lr + ' 0 l ' + ll + ' ' + ld + ' z'; | |
}) | |
.attr("stroke", "#716c6c") | |
.attr("stroke-width", 2) | |
.attr("fill", "#716c6c") | |
// interaction with arrows: | |
function arrowclick(d3Element){ | |
console.log("you clicked an arrow") | |
lt = d3.selectAll(".lifelinetext") | |
var curelement = +d3Element.__data__.index; | |
}; | |
function arrowmouseover(d3Element){ | |
// d3Element.style.cursor = "pointer"; | |
lt = lifelinetextgroup.selectAll(".lifelinetext") | |
var curelement = +d3Element.__data__.index; | |
console.log(curelement) | |
lt[0][curelement].style.display="flex" | |
}; | |
function arrowmouseout(d3Element){ | |
// d3Element.style.cursor = "default"; | |
lt = lifelinetextgroup.selectAll(".lifelinetext") | |
var curelement = +d3Element.__data__.index; | |
console.log(curelement) | |
lt[0][curelement].style.display="none" | |
}; | |
arrows.on("mouseover", function(d) { arrowmouseover(this); }) | |
.on("mouseout", function(d) { arrowmouseout(this); }) | |
.on("click", function() { arrowclick(this); }) | |
// ROTATE ARROWS WHERE INDICATED | |
for(var i=0; i<data.length ; i++){ | |
if(data[i].direction === "up"){ // NEW: use data on arrow direction: if data.direction == up, flip arrow; | |
var selection = d3.select("#arrow" + data[i].index +""); | |
selection.attr("transform", function(d) { return "rotate(-180,0,"+ relypos*height + ") translate(-"+xScale(data[i].age)+",0)";} ) | |
} | |
}; | |
// Create text labels for all events using FOREIGNOBJECT | |
var textgroup = svg.append("g") | |
.attr("id","textgroup"); | |
// Calculate forgeign object box sizes: | |
var foh = "10em"; // ems - foreign object height can be large, it is the outside box only | |
var fow = 210; // pixels - foreign object width can be large, it is the outside box only | |
var bleedoverleft = 1; // years - x-position of text boxes in years, left of the actual event | |
var fotwmax = 2.8; // years - maximum width of foreign object text label boxes | |
var fotwmin = fotwmax-.2; // years - minimum width of foreign object text label boxes | |
// 1. calculate space between the current event's year and the prior and after event | |
//xScale.invert(#pixels) --> zero point is margin: "prior to born" in #years | |
var dyears = [Math.abs(xScale.invert(0))]; | |
for(var i=1; i < data.length; i++){ | |
var obj = data[i].age - data[i-1].age; | |
dyears.push(obj); | |
} | |
//xScale.invert(#pix) -> #years after the very last lifeline event | |
dyears[dyears.length] = xScale.invert(width)-data[data.length-1].age; | |
// 2. determine x and y-coordinate current event text box in YEARS | |
var xc = [], yc = []; | |
for(var i=0; i < dyears.length-1; i++){ | |
// if there is >bleedoverleft years on the left side of the event: | |
if(dyears[i] > bleedoverleft){ | |
var xct = data[i].age - bleedoverleft; //fixed amount to the left of arrow | |
var yct = relypos*height + data[i].arrowheight + arrowheadlength + arrowtextdistance; | |
} | |
// if there is 1 < X < bleedover years on the left side of the event: | |
if(dyears[i] <= bleedoverleft & dyears[i] > 0){ // >0 because first entry has negatiev years | |
var xct = data[i].age - dyears[i]; | |
var yct = relypos*height + data[i].arrowheight + arrowheadlength + arrowtextdistance; | |
} | |
xc.push(xct); | |
yc.push(yct); | |
} | |
// Adjust x coodinate list manually: | |
// change first x coordinate | |
xc[0]=-.7*bleedoverleft; | |
// add a last element of xc and yc vector to ensure math goes well: indicates the end of the timeline: | |
xc[xc.length]=xScale.invert(width)-.9; | |
yc[yc.length]=yScale.invert(relypos*height); | |
// 3. foreign object text box width (fotw) --> determine width & position for current event text box in YEARS | |
var fotw = []; | |
for(var i=0; i<dyears.length-1; i++){ | |
var obj = (xc[i+1] - xc[i]); | |
fotw.push(obj); | |
} | |
// manually adjust width of label positions: | |
fotw[fotw.length-2] = fotw[fotw.length-2]-11; // width of one before last one | |
fotw[fotw.length-1] = fotw[fotw.length-1]-2; // width of last one (death) | |
xc[xc.length-1]=[fotw.length-1]-1.8;//+xScale.invert(0); | |
// debugger; | |
fotw[4]=2.4; // one too small one | |
fotw[5]=2.6; // one too small one | |
xc[4]=xc[4]-1.8;//+xScale.invert(0); | |
// for all fotw > max value, clip to max vaule | |
for(var i=0; i<=fotw.length-1; i++){ | |
if(fotw[i]>fotwmax){fotw[i]=fotwmax} | |
}; | |
// 4. Apply these calculated measures for all TEXT boxes | |
textgroup.selectAll('foreignObject') | |
.data(data) //, function(d) { return d.event_header, d.event_details, d.direction; }) | |
.enter() | |
.append('foreignObject') | |
.attr("id", function(d,i) { return ("textbox" + d.index); }) | |
.attr("x", function(d,i) { | |
if(d.align === "left"){return xScale(xc[i]); } | |
if(d.align === "center"){return xScale(xc[i]); } | |
if(d.align === "right"){return xScale(xc[i]-.8); } // shift these blocks bit to the left | |
}) | |
.attr("y", function(d,i) { | |
// debugger; | |
if(d.direction === "up"){return relypos*height - data[i].arrowheight - arrowheadlength - 125; } | |
if(d.direction === "down"){return yc[i]; } | |
}) | |
.attr('width', function(d,i) {return xScale(fotw[i]) }) | |
.attr('height', foh) | |
.attr("class", function(d) { | |
if(d.align === "left"){return "lefty";} | |
if(d.align === "center"){return "centry";} | |
if(d.align === "right"){return "righty";} | |
}) | |
.html(function(d,i) { return '<div style="width:' + xScale(fotw[i]) + 'px;"><h2CV>' + d.event_header + '</h2CV></div><div style="width:' + xScale(fotw[i]) + 'px;"><h3CV style="line-height:20%;">' + d.event_details + '</h3CV></div>'} ) | |
//debugger; | |
d3.selectAll("foreignObject") | |
.on("mouseover", function(d) { textmouseover(this); }) | |
.on("mouseout", function(d) { textmouseout(this); }) | |
function textmouseover(d3Element){ | |
var curelement = +d3Element.__data__.index; | |
console.log(curelement) | |
q = document.getElementsByClassName("lifelinetext") | |
q[curelement].style.display="flex" | |
}; | |
function textmouseout(d3Element){ | |
var curelement = +d3Element.__data__.index; | |
console.log(curelement) | |
q = document.getElementsByClassName("lifelinetext") | |
q[curelement].style.display="none" | |
}; | |
// put date labels inside timeline: | |
var lifelinetextgroup = svg.append("g") | |
.attr("id","lifelinetextgroup"); | |
var month = new Array(); | |
month[0] = "January"; | |
month[1] = "February"; | |
month[2] = "March"; | |
month[3] = "April"; | |
month[4] = "May"; | |
month[5] = "June"; | |
month[6] = "July"; | |
month[7] = "August"; | |
month[8] = "September"; | |
month[9] = "October"; | |
month[10] = "November"; | |
month[11] = "December"; | |
lifelinetextgroup.selectAll("text") | |
.data(data) //, function(d) { return d.date}) <-- causes skip of data again | |
.enter() | |
.append("text") | |
.attr("class", "lifelinetext") | |
.attr("id", function(d,i) {return "lt"+i+""}) | |
.text(function(d,i) { | |
if(d.date.getDate() == "1") {return d3.time.format(""+month[d.date.getMonth()]+" "+d.date.getDate()+"st "+d.date.getFullYear()+"");} | |
if(d.date.getDate() == "2") {return d3.time.format(""+month[d.date.getMonth()]+" "+d.date.getDate()+"nd "+d.date.getFullYear()+"");} | |
if(d.date.getDate() == "3") {return d3.time.format(""+month[d.date.getMonth()]+" "+d.date.getDate()+"rd "+d.date.getFullYear()+"");} | |
else {return d3.time.format(""+month[d.date.getMonth()]+" "+d.date.getDate()+"th "+d.date.getFullYear()+"");} | |
}) | |
.attr("text-anchor", "middle") | |
.attr("x", function(d,i) {return xScale(d.age); }) | |
.attr("y", function(d,i) {return (relypos*height + 8); }) | |
.attr("font-family", "Garamond") | |
// .attr("font-size", "9px") | |
.attr("font-size", ".6em") | |
.attr("fill", "white"); | |
// create INTERACTIVE CATEGORY buttons! | |
function key_func(d){ | |
return d.index; | |
}; | |
function update(cat,duration) { // cat is button category name | |
console.log("updating") | |
// GROUP data by category: | |
var grouped = d3.nest() //grouping. In this case: group data by category | |
.key(function(d){ | |
return d['category']; | |
}) | |
.entries(data); //passes data through nest pipeline | |
debugger; | |
if(cat.slice(0,4) === "all") { | |
console.log("show all events") | |
var data_to_enter = data; | |
}else{ | |
// filter data for giving category: filter() | |
var filtered = grouped.filter(function(d) { | |
if(d.key.slice(0,4) === cat.slice(0,4)) { | |
return d.key;} | |
}); | |
var data_to_enter = filtered[0].values; | |
}; | |
// UPDATE arrow style based on button press | |
var arrows = d3.select("#lifearrows").selectAll("g") | |
.data(data_to_enter,key_func) // key func needed to get the correct index of the arrow | |
// change style of arrow that are not highlighted: the .exit group | |
arrows.exit().transition() | |
.duration(duration) | |
.style("opacity", .1); | |
// update all other arrows: | |
arrows.transition().duration(duration) | |
.style("opacity", 1) | |
// UPDATE text style based on button press | |
function fo_styling_exit(d){ | |
if(environment == "CM") { // we are in CM mode | |
return "#a7a7a7"; | |
} else { | |
return "#ebebeb";} | |
}; | |
function fo_styling_enter(d){ | |
if(environment == "CM") { // we are in CM mode | |
return "#f4f0f0"; | |
} else { | |
return "black";} | |
}; | |
var fos = d3.selectAll("foreignObject") | |
.data(data_to_enter,key_func) // key func needed to get the correct index of the arrow | |
// change style of arrow that are not highlighted: the .exit group | |
fos.exit().transition() | |
.duration(duration) | |
.attr("fill",fo_styling_exit) | |
.attr("color",fo_styling_exit) | |
// update all other arrows: | |
fos.transition().duration(duration) | |
.attr("fill",fo_styling_enter) | |
.attr("color",fo_styling_enter) | |
}; // end of update function | |
var categories = ["all","life events","education","professional"]; | |
var buttons = d3.select("#content") | |
.append("div") | |
.attr("class","category_buttons") | |
.selectAll("div") | |
.data(categories) | |
.enter() | |
.append("div") | |
.text(function(d){return d;}); | |
buttons.on("click",function(d){ | |
// first select all the buttons: | |
d3.select(".category_buttons") | |
.selectAll("div") | |
.transition().duration(500) | |
.style("background-color", "white") | |
d3.select(this) //selects current element (which is button) | |
.transition().duration(500) | |
.style("background-color", "rgb(247, 230, 210)") | |
update(d,500); | |
cg = d; | |
return cg; | |
}); | |
buttons.on("mouseover", function(d) {d3.select(this).style("cursor", "pointer")} ) | |
.on("mouseout", function(d) {d3.select(this).style("cursor", "default")} ) | |
// <!-- call functions here that interact with the curriculum --> | |
// Functions that moves (and recolors) the whole lifeline depending on header click or mouse position --> | |
var ease = "sin"; //"poly"//"linear" // "cubic", " | |
var transitiondurationCVCM =2000; // is transition speed of the *moving* | |
function changeElementColorCM(d3Element){ | |
var curelement = d3.select("body"); | |
var colour = d3.rgb(curelement.attr("style")); | |
d3Element | |
.style("background", colour) | |
.transition().delay(500).duration(1500).ease(ease) // transition speed of background re-coloring | |
.style("background", "grey") | |
d3.select("body").select("#content").select("svg") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("viewBox", ""+.5*width+" 0 "+ .5*width+" "+height+"") | |
d3.select("body").select("#content").select("svg").select("rect") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("color","white") | |
.attr("fill","white") | |
d3.selectAll("rect") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("color","white") | |
.attr("fill", "white") | |
d3.selectAll("path") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("stroke", "white") | |
.attr("fill", "white") | |
d3.selectAll("foreignObject") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("fill","white") | |
.attr("color","white") | |
d3.selectAll("text") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.style("fill","gray") | |
d3.select("body").select("#wrapper").select("#CVheader").select("#headerright") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.style("color","white"); | |
d3.select("body").select("#wrapper").select("#CVheader").select("#headerleft") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.style("color","#a5a1a1"); | |
environment = "CM"; | |
console.log(environment) | |
if (typeof cg !== 'undefined') { | |
update(cg,2000) | |
console.log(cg) | |
} | |
} // end of changeElementColorCM | |
function changeElementColorCV(d3Element){ | |
var curelement = d3.select("body"); | |
var colour = d3.rgb(curelement.attr("style")); | |
d3Element | |
.style("background", colour) | |
.transition().delay(500).duration(1500).ease(ease) // transition speed of background re-coloring | |
.style("background", "white") | |
d3.select("body").select("#content").select("svg") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("viewBox", "0 0 "+.52*width+" "+height+"") | |
d3.select("body").select("#content").select("svg").select("rect") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("color","#716c6c") | |
.attr("fill","#716c6c") | |
d3.selectAll("rect") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("color","#716c6c") | |
.attr("fill", "#716c6c") | |
d3.selectAll("path") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("stroke", "#716c6c") | |
.attr("fill", "#716c6c") | |
d3.selectAll("foreignObject") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.attr("fill","#716c6c") | |
.attr("color","#716c6c") | |
d3.selectAll("text") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.style("fill","white") | |
d3.select("body").select("#wrapper").select("#CVheader").select("#headerright") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.style("color","#716c6c"); | |
d3.select("body").select("#wrapper").select("#CVheader").select("#headerleft") | |
.transition().duration(transitiondurationCVCM).ease(ease) | |
.style("color","black"); | |
environment = "CV"; | |
console.log(environment) | |
if (typeof cg !== 'undefined') { | |
update(cg,2200) | |
console.log(cg) | |
} | |
} // end of changeElementColorCV | |
// Function that will give the position of cursor | |
// and cause interactions with page at certain mouse positions: | |
function GetcursorPos(p){ | |
// PageX and PageY are position values | |
// info.innerHTML = 'Position X : ' + p.pageX; | |
var maxX = screen.width; | |
var posX = p.pageX/maxX; | |
// Get current screen (CV or CM), through background color: | |
var curelement = d3.select("body"); | |
var colour = d3.rgb(curelement.attr("style")); | |
if(colour.r == 255) { // white, CV environment | |
if(posX > .85) { | |
changeElementColorCM(d3.select("body")); | |
} | |
if(posX <= .85) { | |
changeElementColorCV(d3.select("body")); | |
} | |
} | |
if(colour.r == 128) { // dark, CM environment | |
if(posX < .15) { | |
changeElementColorCV(d3.select("body")); | |
} | |
if(posX >= .15) { | |
changeElementColorCM(d3.select("body")); | |
} | |
} | |
} //End getcursorpos | |
addEventListener('mousemove', GetcursorPos, false); | |
// Set up button functionality of two header texts (CV and CM) | |
var headerr = d3.select("#headerright"); | |
headerr.on({ | |
"mouseover": function(d) { | |
d3.select(this).style("cursor", "pointer") | |
}, | |
"mouseout": function(d) { | |
d3.select(this).style("cursor", "default") | |
} | |
}); | |
var headerl = d3.select("#headerleft") | |
headerl.on({ | |
"mouseover": function(d) { | |
d3.select(this).style("cursor", "pointer") | |
}, | |
"mouseout": function(d) { | |
d3.select(this).style("cursor", "default") | |
} | |
}); | |
//Here, the action after clicking the CV and CM button is defined: | |
headerr.on("click", function() { | |
console.log("you clicked the CM header") | |
var curelement = d3.select("body"); | |
var colour = d3.rgb(curelement.attr("style")); | |
if(colour.r == 255) { | |
changeElementColorCM(d3.select("body")); | |
} | |
}); | |
headerl.on("click", function() { | |
console.log("you clicked the CV header") | |
var curelement = d3.select("body"); | |
var colour = d3.rgb(curelement.attr("style")); | |
if(colour.r == 128) { | |
changeElementColorCV(d3.select("body")); | |
} | |
}); | |
}; // end draw function | |
</script> | |
</head> | |
<body style="style.background= rgb(255, 255, 255);"> | |
<!-- <div id='info'></div>--> | |
<div id="rotatediv"><p><br>Rotate device (or widen browser window) for better view</p></div> | |
<!-- // Wrapper around full visualization --> | |
<div id="wrapper"> | |
<!-- // Header with CV and CM buttons --> | |
<div id="CVheader" style="style.background= rgb(0, 0, 255);"> | |
<h2 id="headerleft">Curriculum Vitae</h2> | |
<h2 id="headerright" >Curriculum Mortem</h2> | |
</div> | |
<!-- // Life line with arrows and text --> | |
<div id="content"> | |
<script type="text/javascript"> | |
// Reading data from CSV | |
formatdate = d3.time.format("%m/%d/%y") | |
function formatage(inputdate){ | |
var birthdate = 1980 + 1/12*8; | |
var age = inputdate.getFullYear() + 1/12*(inputdate.getMonth()+1) - birthdate ; | |
return age; | |
} | |
d3.csv("CVCMdata.csv",function(d){ | |
// transform the data here into needed variables | |
d['date'] = formatdate.parse(d['date']); // to extract data format | |
d['age'] = formatage(d['date']); | |
d['arrowheight']=+d["arrowheight"]; // to make it from strings into numbers | |
return d; | |
},draw); | |
</script> | |
</div> <!-- #end of content --> | |
<!-- // Footer with data details and credits --> | |
<div id="footer"> | |
Source: Data on past events collected throughout the years, future predictions made using <a href="http://fatefulday.eu" target="_blank">fatefulday.eu </a> | <a href="https://sara-maria.github.io/" target="_blank">Sara Maria 2016</a> | |
</div> | |
</div> <!-- #end of wrapper --> | |
<script> | |
// Javascript media query event handler to window size change | |
if (matchMedia) { | |
var mq = window.matchMedia("(min-width: 680px)"); | |
mq.addListener(WidthChange); | |
WidthChange(mq); | |
var mqr = window.matchMedia("(orientation: portrait)"); | |
mqr.addListener(RotationChange); | |
RotationChange(mqr); | |
}; | |
// Javascript function for header button changes on window resize | |
function WidthChange(mq) { | |
if (mq.matches) { | |
// window width is at least 660px | |
var hr = document.getElementById("headerright"); | |
hr.textContent = 'Curriculum Mortem' | |
hr.style.width = "10em"; | |
var hl = document.getElementById("headerleft"); | |
hl.textContent = 'Curriculum Vitae'; | |
hl.style.width = "9em"; | |
} else { | |
// window width is less than 660px | |
var hr = document.getElementById("headerright"); | |
hr.textContent = 'CM'; | |
hr.style.width = "3.6em"; | |
var hl = document.getElementById("headerleft"); | |
hl.textContent = 'CV'; | |
hl.style.width = "3.6em"; | |
} | |
}; | |
// CATCH ROTATED SMART PHONES AND SCREENS // | |
function RotationChange(mqr) { | |
// If there are matches, we're in portrait | |
if(mqr.matches) { | |
// Portrait orientation | |
console.log("rotated to portrait"); | |
// document.getElementById("lifeline").style.background="rgb(0,0,255)" | |
} else { | |
// Landscape orientation | |
console.log("rotated back to landscape"); | |
// console.log(document.body.style.width); | |
// debugger; | |
// var w = 2*window.screen.availWidth; | |
// var h = window.screen.availHeight; | |
// | |
//// document.body.style.width = "20*560px"; | |
// document.getElementById("lifeline").style.background="rgb(0,255,0)"; //green | |
//// document.getElementById("lifeline").style.width=w | |
// document.body.style.width = w; | |
} | |
}; | |
</script> | |
</body> | |
</html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment