Last active
December 17, 2015 19:59
-
-
Save michalskop/5664300 to your computer and use it in GitHub Desktop.
Kroměříž 2012
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
[{"name":"Arno\u0161t \u0160krabal","d1":[[2012.25,2.3395],[2012.75,2.047]],"d2":[[2012.25,-1.5937],[2012.75,0.2378]],"color":[[2012.25,"#008000"],[2012.75,"#008000"]]},{"name":"Blanka \u0160im\u016fnkov\u00e1","d1":[[2012.25,-1.3891],[2012.75,-0.7452]],"d2":[[2012.25,0.9902],[2012.75,-0.5172]],"color":[[2012.25,"#023484"],[2012.75,"#023484"]]},{"name":"Daniela Hebnarov\u00e1","d1":[[2012.25,-1.3082],[2012.75,-1]],"d2":[[2012.25,0.7204],[2012.75,0.2608]],"color":[[2012.25,"#023484"],[2012.75,"#023484"]]},{"name":"Esma Opravilov\u00e1","d1":[[2012.25,-0.8974],[2012.75,1.81]],"d2":[[2012.25,-0.0216],[2012.75,1.5568]],"color":[[2012.25,"#E01C07"],[2012.75,"#E01C07"]]},{"name":"Jan \u017d\u00e1rsk\u00fd","d1":[[2012.25,-0.9831],[2012.75,-0.4314]],"d2":[[2012.25,1.3063],[2012.75,0.7685]],"color":[[2012.25,"#BBBBBB"],[2012.75,"#BBBBBB"]]},{"name":"Jarmila \u010c\u00edhalov\u00e1","d1":[[2012.25,-1.3891],[2012.75,-1.055]],"d2":[[2012.25,0.9902],[2012.75,0.0362]],"color":[[2012.25,"#BBBBBB"],[2012.75,"#BBBBBB"]]},{"name":"Jaroslav Adam\u00edk","d1":[[2012.25,-1.3149],[2012.75,-1.1437]],"d2":[[2012.25,1.0376],[2012.75,-0.5975]],"color":[[2012.25,"#E01C07"],[2012.75,"#E01C07"]]},{"name":"Jaroslav Nov\u00e1k","d1":[[2012.25,-0.5861],[2012.75,0.0998]],"d2":[[2012.25,1.1129],[2012.75,-0.297]],"color":[[2012.25,"#673B6C"],[2012.75,"#673B6C"]]},{"name":"Jitka Dvo\u0159\u00e1kov\u00e1","d1":[[2012.25,1.3624],[2012.75,0.9329]],"d2":[[2012.25,-1.6426],[2012.75,-0.2109]],"color":[[2012.25,"#023484"],[2012.75,"#023484"]]},{"name":"Karel Chv\u00e1tal","d1":[[2012.25,0.7252],[2012.75,-0.7691]],"d2":[[2012.25,-1.3653],[2012.75,-1.3806]],"color":[[2012.25,"#023484"],[2012.75,"#023484"]]},{"name":"Karel Hol\u00edk","d1":[[2012.25,-1.312],[2012.75,-1.212]],"d2":[[2012.25,0.7188],[2012.75,-0.3821]],"color":[[2012.25,"#F18811"],[2012.75,"#F18811"]]},{"name":"Karel Sm\u00ed\u0161ek","d1":[[2012.25,1.4612],[2012.75,1.7838]],"d2":[[2012.25,-0.1761],[2012.75,1.9188]],"color":[[2012.25,"#FFFF00"],[2012.75,"#FFFF00"]]},{"name":"Lea P\u00edskovsk\u00e1","d1":[[2012.25,2.2795],[2012.75,1.9099]],"d2":[[2012.25,-0.8859],[2012.75,1.8937]],"color":[[2012.25,"#4444FF"],[2012.75,"#4444FF"]]},{"name":"Lenka Mergenthalov\u00e1","d1":[[2012.25,-1.515],[2012.75,-0.9166]],"d2":[[2012.25,1.0081],[2012.75,-0.4005]],"color":[[2012.25,"#673B6C"],[2012.75,"#673B6C"]]},{"name":"Marek \u0160indler","d1":[[2012.25,-1.3082],[2012.75,-1.0081]],"d2":[[2012.25,0.7204],[2012.75,0.2697]],"color":[[2012.25,"#F18811"],[2012.75,"#F18811"]]},{"name":"Miloslava Noskov\u00e1","d1":[[2012.25,0.8102],[2012.75,-0.9345]],"d2":[[2012.25,-1.2402],[2012.75,-1.2369]],"color":[[2012.25,"#F18811"],[2012.75,"#F18811"]]},{"name":"Milo\u0161 Mal\u00fd","d1":[[2012.25,-1.3005],[2012.75,-1.0735]],"d2":[[2012.25,0.749],[2012.75,-0.3096]],"color":[[2012.25,"#F18811"],[2012.75,"#F18811"]]},{"name":"Olga Sehnalov\u00e1","d1":[[2012.25,1.4554],[2012.75,1.8262]],"d2":[[2012.25,-1.4809],[2012.75,0.2193]],"color":[[2012.25,"#F18811"],[2012.75,"#F18811"]]},{"name":"Ond\u0159ej Debef","d1":[[2012.25,1.4768],[2012.75,1.5239]],"d2":[[2012.25,-0.667],[2012.75,0.7991]],"color":[[2012.25,"#FFFF00"],[2012.75,"#FFFF00"]]},{"name":"Pavel Moty\u010dka","d1":[[2012.25,2.0955],[2012.75,2.3033]],"d2":[[2012.25,-1.0729],[2012.75,1.0272]],"color":[[2012.25,"#FFFF00"],[2012.75,"#FFFF00"]]},{"name":"Richard Kreml","d1":[[2012.25,2.2736],[2012.75,1.7469]],"d2":[[2012.25,-1.5219],[2012.75,-0.7606]],"color":[[2012.25,"#008000"],[2012.75,"#008000"]]},{"name":"Vladim\u00edr Ken\u0161a","d1":[[2012.25,-1.0722],[2012.75,-1.1796]],"d2":[[2012.25,0.6921],[2012.75,-0.4713]],"color":[[2012.25,"#E01C07"],[2012.75,"#E01C07"]]},{"name":"Vladim\u00edr K\u0159eme\u010dek","d1":[[2012.25,-1.1457],[2012.75,-0.978]],"d2":[[2012.25,0.6688],[2012.75,-0.6676]],"color":[[2012.25,"#E01C07"],[2012.75,"#E01C07"]]},{"name":"V\u011bra Knapkov\u00e1","d1":[[2012.25,-1.3891],[2012.75,-0.7601]],"d2":[[2012.25,0.9902],[2012.75,-0.5348]],"color":[[2012.25,"#023484"],[2012.75,"#023484"]]},{"name":"V\u011bra Nov\u00e1kov\u00e1","d1":[[2012.25,1.734],[2012.75,0.3097]],"d2":[[2012.25,-1.6756],[2012.75,-1.3395]],"color":[[2012.25,"#F18811"],[2012.75,"#F18811"]]},{"name":"Zde\u0148ka Dokoupilov\u00e1","d1":[[2012.25,2.249],[2012.75,2.3364]],"d2":[[2012.25,-0.7497],[2012.75,0.9451]],"color":[[2012.25,"#008000"],[2012.75,"#008000"]]},{"name":"\u0160\u00e1rka Ka\u0161p\u00e1rkov\u00e1","d1":[[2012.25,-1.515],[2012.75,-0.5048]],"d2":[[2012.25,1.0081],[2012.75,0.4888]],"color":[[2012.25,"#BBBBBB"],[2012.75,"#BBBBBB"]]}] |
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
.libPaths("/home/michal/R/x86_64-pc-linux-gnu-library/3.0") | |
#install.packages("reshape2") | |
library("reshape2") | |
#install.packages("sqldf") | |
library("sqldf") | |
path = "/home/michal/project/mpv_motion/www/analyses/" | |
dataname = "cz_kromeriz_2012" | |
analysisname = "cz_kromeriz_2012_1h" | |
#lower limit to eliminate from calculations | |
lo_limit = .1 | |
#lower limit to eliminate from projections | |
lo_limitT = lo_limit | |
#raw data in 3 columns (values in [-1,1]) | |
Graw = read.table(paste(path,dataname,"/",dataname,".csv",sep=""), header=FALSE, sep=",") | |
#data divisions x persons | |
G = acast(Graw,V2~V1,value.var='V3') | |
#scaled divisions x persons (mean=0 and sd=1 for each division) | |
H=t(scale(t(G),scale=TRUE)) | |
#weights | |
#weights 1, based on number of persons in division | |
w1 = apply(abs(G)==1,1,sum,na.rm=TRUE)/max(apply(abs(G)==1,1,sum,na.rm=TRUE)) | |
w1[is.na(w1)] = 0 | |
#weights 2, "100:100" vs. "195:5" | |
w2 = 1 - abs(apply(G==1,1,sum,na.rm=TRUE) - apply(G==-1,1,sum,na.rm=TRUE))/apply(!is.na(G),1,sum) | |
w2[is.na(w2)] = 0 | |
#analytics | |
#plot(w1) | |
#plot(w2) | |
#plot(w1*w2) | |
#weighted scaled divisions x persons | |
Hw = H * w1 * w2 | |
#index of missing data | |
#index of missing data divisions x persons | |
HI = H | |
HI[!is.na(H)]=1 | |
HI[is.na(H)] = 0 | |
#weighted scaled with NA->0 division x persons | |
Hw0 = Hw | |
Hw0[is.na(Hw)]=0 | |
#eliminate persons with too few votes (weighted) | |
#weights for non missing data division x persons | |
HIw = HI*w1*w2 | |
#sum of weights of divisions for each persons | |
tmp = apply(HIw,2,sum) | |
pw = tmp/max(tmp) | |
#index of persons in calculation | |
pI = pw > lo_limit | |
#weighted scaled with NA->0 and cutted persons with too few votes division x persons | |
Hw0c = Hw0[,pI] | |
#index of missing data cutted persons with too few votes divisions x persons | |
HIc = HI[,pI] | |
#"covariance" matrix adjusted according to missing data | |
Hcov=t(Hw0c)%*%Hw0c * 1/(t(HIc)%*%HIc) * (dim(Hw0c)[1]) | |
#Hcov=t(Hw0)%*%Hw0 * 1/(t(HI)%*%HI-1) * (dim(H)[1]-1) | |
#substitution of missing data in "covariance" matrix | |
Hcov0 = Hcov | |
Hcov0[is.na(Hcov)] = 0 #********* | |
#eigendecomposition | |
He=eigen(Hcov0) | |
# V (rotation values of persons) | |
V = He$vectors | |
#projected divisions into dimensions | |
Hy=Hw0c%*%V | |
#analytics | |
#plot(Hy[,1],Hy[,2]) | |
#plot(sqrt(He$values[1:10])) | |
#sigma matrix | |
sigma = diag(sqrt(He$values)) | |
sigma[is.na(sigma)] = 0 | |
#projection of persons into dimensions | |
Hproj = t(sigma%*%t(V)) | |
#analytics | |
#plot(Hproj[,1],Hproj[,2]) | |
#second projection | |
#Hproj2 = t(t(U) %*% Hw0c) | |
#without missing values should be equal | |
#plot(Hproj[,1],Hproj[,1]) | |
#plot(Hproj[,2],Hproj[,2]) | |
#sigma^-1 matrix | |
sigma_1 = diag(sqrt(1/He$values)) | |
sigma_1[is.na(sigma_1)] = 0 | |
# U (rotation values of divisions) | |
U = Hw0c%*%V%*%sigma_1 | |
#U%*%sigma%*%t(V) != Hw0c ;because of adjusting of "covariance" matrix | |
# NEW MP (or partial) | |
#New persons / partial (like a projection of divisions from a smaller time interval into all divisions) | |
analdb = dbConnect(SQLite(), dbname=paste(path,dataname,"/",analysisname,"/",analysisname,".sqlite3",sep="")) | |
datadb = dbConnect(SQLite(), dbname=paste(path,dataname,"/",dataname,".sqlite3",sep="")) | |
rotation = strsplit(dbGetQuery(analdb,"SELECT orientation FROM analysis_info")[1,1],",")[[1]] | |
rot_mp_rank = which(dimnames(Hcov)[[1]] == rotation[1]) | |
for (j in 2:length(rotation)) { | |
if (Hproj[rot_mp_rank,j-1] * as.double(rotation[j]) < 0) { | |
U[,j-1] = -1*U[,j-1] | |
} | |
} | |
aU = abs(U) | |
mp_names = dbGetQuery(datadb,"SELECT name FROM mp ORDER BY CAST(code as INTEGER)") | |
attr(G,'dimnames')[2][[1]] = mp_names$name | |
#attr(Hw0c,'dimnames')[2][[1]] = mp_names$name[pI] | |
interval_names = dbGetQuery(analdb,"SELECT distinct(interval_name) FROM analysis_division_in_interval ORDER BY interval_name") | |
for (i in 1:dim(interval_names)[1]) { | |
TIf = dbGetQuery(analdb,paste("SELECT division_code, CASE interval_name='",interval_names[i,],"' WHEN 1 THEN 'TRUE' ELSE 'FALSE' END as in_interval FROM analysis_division_in_interval ORDER BY division_code",sep="")) | |
TIf$in_interval = as.logical(TIf$in_interval) | |
max_division_code = TIf$division_code[max(which(as.logical(TIf$in_interval)))] | |
min_division_code = TIf$division_code[min(which(as.logical(TIf$in_interval)))] | |
TI = TIf$in_interval | |
GTc = G[,pI] | |
GTc[!TI,] = NA | |
HTc = (GTc - attr(H,"scaled:center"))/attr(H,"scaled:scale") | |
HTIc = HTc | |
HTIc[!is.na(HTIc)] = 1 | |
HTIc[is.na(HTIc)] = 0 | |
HTw0c = HTc * w1 * w2 | |
HTw0c[is.na(HTw0c)] = 0 | |
#weights for non missing data division x persons | |
HTIcw = HTIc*w1*w2 | |
#sum of weights of divisions for each persons | |
tmp = apply(HTIcw,2,sum) | |
pTw = tmp/max(tmp) | |
#index of persons in calculation | |
pTI = pTw > lo_limitT | |
#weighted scaled with NA->0 and cutted persons with too few votes division x persons | |
HTw0cc = HTw0c[,pTI] | |
#index of missing data cutted persons with too few votes divisions x persons | |
HTIcc = HTIc[,pTI] | |
dweights = t(t(aU)%*%HTIcc / apply(aU,2,sum)) #person x division | |
dweights[is.na(dweights)] = 0 | |
HTw0ccproj = t(HTw0cc)%*%U / dweights | |
parties = as.matrix(dbGetQuery(datadb,paste('SELECT COALESCE(NULLIF(tmax.code,""),tmin.code) as code, COALESCE(NULLIF(tmax.color,""),tmin.color) as color FROM (SELECT mvf.mp_code, g.code, g.color FROM mp_vote_full as mvf LEFT JOIN "group" as g ON mvf.group_code=g.code WHERE division_code="',max_division_code,'") as tmax LEFT JOIN (SELECT mvf.mp_code, g.code, g.color FROM mp_vote_full as mvf LEFT JOIN "group" as g ON mvf.group_code=g.code WHERE division_code="',min_division_code,'") as tmin ON tmax.mp_code=tmin.mp_code ORDER BY CAST(tmax.mp_code as INTEGER)',sep=""))) | |
partiescc = (parties[pI,])[pTI,] | |
output = format(HTw0ccproj[,1:2],scientific=FALSE,digits=3) | |
write.csv(format(cbind(output,partiescc),digits=3),file=paste(path,dataname,"/",analysisname,"/",interval_names[i,],"_result.csv",sep="")) | |
#************************* | |
} |
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"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<title>Kroměříž 2012</title> | |
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.css" /> | |
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script> | |
<script src="http://code.jquery.com/mobile/1.3.1/jquery.mobile-1.3.1.min.js"></script> | |
<style> | |
#chart { | |
margin-left: -40px; | |
height: 506px; | |
} | |
text { | |
font: 10px sans-serif; | |
} | |
.dot { | |
stroke: #000; | |
opacity: .5; | |
stroke-opacity: .75; | |
} | |
.axis path, .axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.label { | |
fill: #777; | |
} | |
.year.label { | |
font: 500 100px "Helvetica Neue"; | |
fill: #ddd; | |
} | |
.year.label.active { | |
fill: #aaa; | |
} | |
.overlay { | |
fill: none; | |
pointer-events: all; | |
cursor: ew-resize; | |
} | |
</style> | |
</head> | |
<body> | |
<div data-role="page" class="type-home"> | |
<div data-role="content"> | |
<header> | |
<aside>May 28, 2013</aside> | |
<a href="../" rel="author">Michal Škop</a> | |
</header> | |
<h1>Kroměříž 2012</h1> | |
<form> | |
<label for="slider">Slider:</label> | |
<input name="slider" id="slider" min="2012.25" max="2012.75" value="2012.25" step=".01" type="range" /> | |
</form> | |
<p> | |
<a href="#" id="play" data-role="button" data-inline="true" data-icon="refresh"><span id="playText">Play ></span></a> | |
</p> | |
<p id="chart"><svg><defs id="gradients"></defs></svg></p> | |
<!-- <p id="slide">XXX</p> --> | |
<p>Method: weighted PCA; Time intervals: 6 months (projection of 6-month blocks into all data)</p> | |
<p>Data thanks to <a href="http://blog.aktualne.centrum.cz/blogy/vojtech-navratil.php">V. Navrátil</a></p> | |
<p>Using <a href="https://github.com/michalskop/mpv_motion">Models of parliamentary voting in motion</a></p> | |
<script src="http://d3js.org/d3.v2.js?2.8.1"></script> | |
<script> | |
// Various accessors that specify the four dimensions of data to visualize. | |
function x(d) { return d.d1; } | |
function y(d) { return d.d2; } | |
function z(d) { return d.d3; } | |
function radius(d) { return 1; } | |
function color(d) { return d.color; } | |
//function color(d) { return d.group; } | |
function key(d) { return d.name; } | |
function display(d) {return d.display;} | |
// Chart dimensions. | |
var margin = {top: 19.5, right: 19.5, bottom: 19.5, left: 39.5}, | |
width = 600 - margin.right, | |
height = 400 - margin.top - margin.bottom; | |
// Various scales. These domains make assumptions of data, naturally. | |
var xScale = d3.scale.linear().domain([-3, 3]).range([0, width]), | |
yScale = d3.scale.linear().domain([-2.5, 2.5]).range([height, 0]), | |
radiusScale = d3.scale.sqrt().domain([0, 1]).range([0, 10]); | |
//colorScale = d3.scale.category10(); | |
var colorScale = d3.scale.category20c(); | |
// The x & y axes. | |
var xAxis = d3.svg.axis().orient("bottom").scale(xScale).ticks(12, d3.format(",d")), | |
yAxis = d3.svg.axis().scale(yScale).orient("left"); | |
// Create the SVG container and set the origin. | |
var svg = d3.select("#chart svg") //d3.select("#chart").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 + ")"); | |
// Add the x-axis. | |
svg.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height + ")") | |
.call(xAxis); | |
// Add the y-axis. | |
svg.append("g") | |
.attr("class", "y axis") | |
.call(yAxis); | |
// Add an x-axis label. | |
svg.append("text") | |
.attr("class", "x label") | |
.attr("text-anchor", "end") | |
.attr("x", width) | |
.attr("y", height - 6) | |
.text("Dimension 1"); | |
// Add a y-axis label. | |
svg.append("text") | |
.attr("class", "y label") | |
.attr("text-anchor", "end") | |
.attr("y", 6) | |
.attr("dy", ".75em") | |
.attr("transform", "rotate(-90)") | |
.text("Dimension 2"); | |
// Add the year label; the value is set on transition. | |
var label = svg.append("text") | |
.attr("class", "year label") | |
.attr("text-anchor", "end") | |
.attr("y", height - 24) | |
.attr("x", width) | |
.text("2012/1"); | |
// Load the data. | |
d3.json("cz_kromeriz_2012_1h.json", function(nations) { | |
// A bisector since many nation's data is sparsely-defined. | |
var bisect = d3.bisector(function(d) { return d[0]; }); | |
// Add a dot per nation. Initialize the data at 1800, and set the colors. | |
var dot = svg.append("g") | |
.attr("class", "dots") | |
.selectAll(".dot") | |
.data(interpolateData(2012.25)) | |
.enter().append("circle") | |
.attr("class", "dot") | |
//.style("fill", function(d) { return d.group; }) | |
//.style("fill", function (d) { return gradient(colorScale(color(d))) }) | |
.call(position) | |
.sort(order) | |
.on("mouseover", animateFirstStep) | |
.on("mouseout", animateSecondStep) | |
.on("mousedown", animateFirstStep); | |
// Add a title. | |
dot.append("title") | |
.text(function(d) { return d.name}); | |
var i=0; | |
var playing = false; | |
$("#play").click(function() { | |
if(playing === false) { | |
startPlaying(); | |
} else { | |
stopPlaying(); | |
} | |
}); | |
function startPlaying() { | |
playing = true; | |
$("#playText").html("Stop ||"); | |
$('#slider').slider('disable'); | |
// Start a transition that interpolates the data based on year. | |
svg.transition() | |
.duration(30000) | |
.ease("linear") | |
.tween("year", function() {return tweenYear($('#slider').val()) }) | |
.each("end", stopPlaying); | |
} | |
function stopPlaying() { | |
playing = false; | |
$("#playText").html("Play >"); | |
svg.transition().duration(0); | |
$('#slider').slider('enable'); | |
} | |
// Positions the dots based on data. | |
function position(dot) { | |
dot .attr("cx", function(d) { return xScale(x(d)); }) | |
.attr("cy", function(d) { return yScale(y(d)); }) | |
.attr("r", function(d) { return radiusScale(radius(d)) }) | |
//.style("fill", function(d) { return color(d); }); | |
.style("fill", function (d) { return gradient(color(d)) }) | |
//.attr("style", function (d) { return "display:" + display(d)+";";}); | |
.attr("display", function (d) { return display(d);}); | |
//alert(dot.data); | |
} | |
// Defines a sort order so that the smallest dots are drawn on top. | |
function order(a, b) { | |
return radius(b) - radius(a); | |
} | |
// Tweens the entire chart by first tweening the year, and then the data. | |
// For the interpolated data, the dots and label are redrawn. | |
function tweenYear(start) { | |
var year = d3.interpolateNumber(2012.25,2012.75); | |
return function(t) { displayYear(year(t)); }; | |
} | |
// Updates the display to show the specified year. | |
function displayYear(year) { | |
dot.data(interpolateData(year), key).call(position).sort(order); | |
month = Math.ceil((year - Math.floor(year))*12); | |
label.text(Math.floor(year) + '/' + month); | |
i++; | |
if ((i%25) == 0) { | |
$("#slider").val(year); | |
$('#slider').slider('refresh'); | |
} | |
} | |
// Interpolates the dataset for the given (fractional) year. | |
function interpolateData(year) { | |
return nations.map(function(d) { | |
return { | |
name: d.name, | |
//group: d.group, | |
d1: interpolateValues(d.d1, year), | |
d2: interpolateValues(d.d2, year), | |
//d3: interpolateValues(d.d3, year), | |
color: findColor(d.color, year), | |
display: isDisplayed(d.d1, year) | |
//category: d.group | |
//lifeExpectancy: interpolateValues(d.lifeExpectancy, year) | |
}; | |
}); | |
} | |
// Finds (and possibly interpolates) the value for the specified year. | |
function interpolateValues(values, year) { | |
var i = bisect.left(values, year, 0, values.length - 1), | |
a = values[i]; | |
if (i > 0) { | |
var b = values[i - 1], | |
t = (year - a[0]) / (b[0] - a[0]); | |
return a[1] * (1 - t) + b[1] * t; | |
} | |
return a[1]; | |
} | |
function findColor(values, year) { | |
var i = bisect.left(values, year, 0, values.length - 1); | |
return values[i][1]; | |
} | |
function isDisplayed(values, year) { | |
if ( (year < values[0][0]) || (year > values[values.length - 1][0])) | |
return 'none'; | |
else | |
return 'inherit'; | |
} | |
function animateFirstStep(d){ | |
d3.select(this) | |
.transition() | |
.delay(0) | |
.duration(1000) | |
.attr("r", 10*2) | |
//.attr("cx", 300*d.x+150+50) | |
;//.each("end", animateSecondStep); | |
} | |
function animateSecondStep(d){ | |
d3.select(this) | |
.transition() | |
.duration(1000) | |
.attr("r", 10); | |
//.attr("cx", 300*d.x+150); | |
} | |
//slider | |
//see http://michalskop.tumblr.com/post/37352195911/strange-behaviour-of-jquery-change | |
$('#slider').ready(function() { | |
$('#slider').change(function(){ | |
displayYear($(this).val()); | |
}); | |
}); | |
//color gradients | |
//http://dexvis.wordpress.com/2012/12/25/motion-charts-revisited/ | |
function shadeColor(color, percent) { | |
var R = parseInt(color.substring(1,3),16) | |
var G = parseInt(color.substring(3,5),16) | |
var B = parseInt(color.substring(5,7),16); | |
R = parseInt(R * (100 + percent) / 100); | |
G = parseInt(G * (100 + percent) / 100); | |
B = parseInt(B * (100 + percent) / 100); | |
R = (R<255)?R:255; | |
G = (G<255)?G:255; | |
B = (B<255)?B:255; | |
var RR = ((R.toString(16).length==1)?"0"+R.toString(16):R.toString(16)); | |
var GG = ((G.toString(16).length==1)?"0"+G.toString(16):G.toString(16)); | |
var BB = ((B.toString(16).length==1)?"0"+B.toString(16):B.toString(16)); | |
return "#"+RR+GG+BB; | |
} | |
function gradient(baseColor) | |
{ | |
var gradientId = "gradient" + baseColor.substring(1) | |
console.log("COLOR: " + gradientId); | |
//var lightColor = shadeColor(baseColor, -10) | |
var darkColor = shadeColor(baseColor, -20) | |
var grad = d3.select("#gradients").selectAll("#" + gradientId) | |
.data([ gradientId ]) | |
.enter() | |
.append("radialGradient") | |
.attr("id", gradientId) | |
.attr("gradientUnits", "objectBoundingBox") | |
.attr("fx", "30%") | |
.attr("fy", "30%") | |
grad.append("stop") | |
.attr("offset", "0%") | |
.attr("style", "stop-color:#FFFFFF") | |
// Middle | |
grad.append("stop") | |
.attr("offset", "40%") | |
.attr("style", "stop-color:" + baseColor) | |
// Outer Edges | |
grad.append("stop") | |
.attr("offset", "100%") | |
.attr("style", "stop-color:" + darkColor) | |
console.log("url(#" + gradientId + ")") | |
return "url(#" + gradientId + ")"; | |
} | |
}); | |
</script> | |
<script> | |
</script> | |
</div> <!-- /content --> | |
</div><!-- /page --> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment