Skip to content

Instantly share code, notes, and snippets.

@said-and-done
Last active April 17, 2019 11:14
Show Gist options
  • Save said-and-done/06257a56b1e29d6719fe002b85db2977 to your computer and use it in GitHub Desktop.
Save said-and-done/06257a56b1e29d6719fe002b85db2977 to your computer and use it in GitHub Desktop.
vandring
license: mit
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel='stylesheet' href='https://phobos.local/interactive/vaelgervandring-v3/dist/custom.min.css'/>
<script src="https://phobos.local/interactive/vaelgervandring/data/flow.min.js"></script>
<script src="https://phobos.local/common/lib/d3.v3.5.12.min.js"></script>
<div class="t2vaelgervandring-v3 t2toolbox loading">
<div class="chart">
</div>
</div>
<style>
.t2vaelgervandring-v3 svg text{
stroke:none;
font-size: 150%;
}
path:hover{
stroke-opacity: .5;
}
.elections{
transform: rotate(-90deg) translate(-60px, 0);
transform-origin: 175px 125px;
}
text.font-black{
transform: rotate(90deg);
transform-origin: 0px 0px;
}
</style>
<script>
'use strict';
var config = {
yearLabels:['Valget 2015', '2018'],
sortBalanced: false, /*false: share values are sorted, biggest first. true: biggest value is at the center */
colorSlices: true, /* color each incoming slice after party color*/
shape: 'circle', /* options: rect, circle*/
metadata:{
'A': { 'name': 'Socialdemokraterne', 'abbrev': 'Soc.dem', 'color': '#d1163e' },
'B': { 'name': 'Radikale Venstre', 'abbrev': 'Radikale', 'color': '#9044a9', _color: '#712f87' },
'C': { 'name': 'Det Konservative Folkeparti', 'abbrev': 'Kons.', 'color': '#4aa127' },
'D': { 'name': 'Nye Borgerlige', 'abbrev': 'Nye Borg.', 'color': '#01505d' },
'E': { 'name': 'Klaus Riskær Pedersen', 'abbrev': 'Riskær', 'color': '#5C77A3' },
'F': { 'name': 'Socialistisk Folkeparti', 'abbrev': 'SF', 'color': '#f50896' },
'I': { 'name': 'Liberal Alliance', 'abbrev': 'Lib. All.', 'color': '#47bed4' },
'K': { 'name': 'Kristendemokraterne', 'abbrev': 'Kr. dem.', 'color': '#fe8300' },
'O': { 'name': 'Dansk Folkeparti', 'abbrev': 'DF', 'color': '#f4b912' },
'V': { 'name': 'Venstre', 'abbrev': 'Venstre', 'color': '#065bb2' },
'Ø': { 'name': 'Enhedslisten', 'abbrev': 'Enhedsl.', 'color': '#f82d00' },
'Å': { 'name': 'Alternativet', 'abbrev': 'Alternativet', 'color': '#78c31e' }
},
svg: {
width: 530,
height: 300,
margin: {
top: 50,
right: 20,
bottom: 0,
left: 20
},
box: {
width: 40,
height: 30,
//height: 50 * (3/4), /* 4:3 ratio */
spacing: 0, /* horiz spacing between boxes*/
valuePadding: 20, /* between % value and the box*/
radius: 21
},
transition: {
duration: 1300,
delay: 100
},
path: {
in : {
delay: 0,
transition: 2200,
easing: 'cubic-out'
},
out: {
delay: 25,
transition: 1000,
easing: 'cubic-out' //exp
}
}
}
};
var sort = function (list) {
list.sort(function(a, b) {
return b.value - a.value
});
if (!config.sortBalanced) {
return list
}
var left = [],
right = [],
middle = list.shift(),
indx = 0, v;
while (v = list.shift()) {
if (indx++ % 2) {
right.push(v);
} else {
left.push(v);
}
}
return left.reverse().concat(middle).concat(right);
};
var drawParty = function (data, container) {
var parties = container
.selectAll('g').data(data)
.enter()
.append('g')
.attr('transform', function (d, i) {
return 'translate(' + d.x + ', ' + d.y + ')';
});
var dots = parties.append('circle')
.attr('cx', 0)
.attr('cy', 0)
.attr('r', config.svg.box.radius)
.style('fill', function(d) {
return d.meta.color
});
var labels = parties.append('text')
// .attr('y', config.svg.box.radius)
// .attr('x', config.svg.box.radius)
// .attr('dx', '0')
.attr('dy', 8)
.attr('class', 'font-black')
.attr('text-anchor', 'middle')
.text(function(d) {
return d.name
return d.meta.abbrev
})
};
var drawParties = function (container, data, links) {
var diagonal = d3.svg.diagonal()
//.projection(function(d) { return [d.x, d.y]; });
var link = container.selectAll('.link')
.data(links)
.enter().append('path')
.attr('d', diagonal)
.attr('class', 'link')
.attr('stroke-width', function (d) {
console.log(d.target.value,strokeScale(d.target.value))
return strokeScale(d.target.value) + 'px';
})
.style('stroke', function (d) {
return d.target.meta.color;
})
drawParty(data, container);
};
d3.select('.chart svg').remove();
var wrapper = d3.select('.t2vaelgervandring-v3');
var svg = wrapper.select('.chart').append('svg');
//======================
var currentParty = 'C';
//======================
var data = APPDATA.flow[currentParty];
var strokeScale = d3.scale.linear()
.domain([0, 1])
.range([0, 2*config.svg.box.radius]);
var xScale = function (d, i) {
return i * (config.svg.box.radius * 2 + config.svg.box.spacing) + config.svg.box.radius
};
var init = function () {
var g = svg.append('g').attr('class', 'elections')
g.attr('transform', 'rotate()')
var containers = g.selectAll('g.last, g.current')
.data(['last', 'current'])
.enter()
.append('g')
//.attr('transform', Flow.Node.parentTransform)
.attr('class', function(d) {return d;});
var target = {
x: 266,
y: 208
};
var glinks = [];
var llinks = [];
var gnodes = sort(data.gain.filter(function (item) {
return item.value;
return item.value && item.name !== currentParty
}));
var lnodes = sort(data.loss.filter(function (item) {
return item.value && item.name !== currentParty
return item.value;
}));
//var xOffset = (Math.max(gnodes.length, lnodes.length)/2)-0.5;
var xOffset = (gnodes.length/2)-0.5;
target.x = xScale([], xOffset);
gnodes.forEach(function (d, i) {
var accum = gnodes.slice(0, i).map(function(k) {
return k.value
})
.reduce(function(prev, curr) {
return +prev + +curr
}, 0);
var h = strokeScale(accum);
var h2 = strokeScale(d.value);
var offset = h2 / 2 + h;
d.x = xScale(d, i);
d.y = config.svg.box.radius;
d.meta = config.metadata[d.name];
var a = {
y:d.y + config.svg.box.radius,
x:d.x,
value: d.value,
meta: d.meta
};
var b = {
y:target.y - config.svg.box.radius *.5,
x:target.x + offset - config.svg.box.radius
//x:target.x - offset
};
glinks.push({source: b, target: a});
});
lnodes.forEach(function (d, i) {
var accum = lnodes.slice(0, i).map(function(k) {
return k.value
})
.reduce(function(prev, curr) {
return +prev + +curr
}, 0);
var h = strokeScale(accum);
var h2 = strokeScale(d.value);
var offset = h2 / 2 + h;
d.x = xScale(d, i);
d.y = 2*target.y - (config.svg.box.radius *1);
d.meta = config.metadata[d.name];
var a = {
y:d.y - config.svg.box.radius,
x:d.x,
value: d.value,
meta: d.meta
};
var b = {
y:target.y + config.svg.box.radius - 2,
x:target.x + offset
};
llinks.push({source: b, target: a});
});
drawParties(d3.select('g.last'), gnodes, glinks);
drawParties(d3.select('g.current'), lnodes, llinks);
var p = g.append('g').attr('class', 'party');
var d = {name: currentParty, x: target.x, y: target.y, meta: config.metadata[currentParty]}
drawParty([d], p);
};
init.apply();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment