|
window.initColumns = function(id, metrics, measures){ |
|
var c = d3.conventions({ |
|
sel: d3.select(id).html('').st({width: 775, margin: '0px auto', left: 27}), |
|
margin: {left: 260, top: 40}, |
|
height: 600, |
|
}) |
|
|
|
var sets = d3.range(numRows).map(i => { |
|
var shapes = columnShapes[i] |
|
shapes = _.sortBy(shapes, d => d.shape) |
|
shapes = _.sortBy(shapes, d => d.size) |
|
shapes = _.sortBy(shapes, d => d.color) |
|
shapes = _.sortBy(shapes, d => d.color == 'green' ? 0 : 1) |
|
|
|
|
|
shapes.nG = d3.sum(shapes, d => d.color == 'green') |
|
shapes.nB = d3.sum(shapes, d => d.color == 'blue') |
|
shapes.nO = d3.sum(shapes, d => d.color == 'orange') |
|
shapes.nR = d3.sum(shapes, d => d.color == 'red') |
|
|
|
shapes.forEach((d, i) => { |
|
d.i = i |
|
d.sizeVal = d.sizeVal < 1 ? .6 : 1 |
|
}) |
|
shapes.i = i |
|
return shapes |
|
}) |
|
|
|
var colW = 200 |
|
var colWpad = 50 |
|
var colH = 20 |
|
var colHpad = 10 |
|
var offsetW = -20 |
|
|
|
var colSel = c.svg.appendMany('g', measures) |
|
.translate((d, i) => [.5 + i*(colW + colWpad) + offsetW, .5]) |
|
|
|
colSel.append('text').text(d => d.ranking_display_text) |
|
.at({y: -20, textAnchor: 'middle', x: colW/2, fontWeight: 600, }) |
|
|
|
var rowSel = colSel.appendMany('g.row', sets) |
|
.translate(d => d.i*(colH + colHpad), 1) |
|
|
|
var colMean = colSel.filter((d, i) => i === 0) |
|
var colMin = colSel.filter((d, i) => i === 1) |
|
var scoreLabelsMean = colMean.selectAll('.row').append('text') |
|
.at({x: -5, y: 15, textAnchor: 'end'}) |
|
.st({fontSize: '13px', opacity: .7}) |
|
var scoreLabelsMin = colMin.selectAll('.row').append('text') |
|
.at({x: 222, y: 15, textAnchor: 'end'}) |
|
.st({fontSize: '13px', opacity: .7}) |
|
|
|
colSel.each(function(d, i){ |
|
d.rowSel = d3.select(this).selectAll('.row') |
|
|
|
c.svg.append('marker') |
|
.attr('id', 'arrow') |
|
.attr('viewBox', '-10 -10 20 20') |
|
.attr('markerWidth', 20) |
|
.attr('markerHeight', 20) |
|
.attr('orient', 'auto') |
|
.append('path') |
|
.attr('d', 'M-6.75,-6.75 L 0,0 L -6.75,6.75') |
|
.at({fill: '#000'}) |
|
|
|
|
|
if (i){ |
|
var pathstr = ['M', 160, -25, 'C', 215, -25, 215, -25, 215, -5].join(' ') |
|
} else{ |
|
var pathstr = ['M', 35, -25, 'C', -20, -25, -20, -25, -20, -5].join(' ') |
|
} |
|
d3.select(this).append('path') |
|
.at({stroke: '#000', fill: 'none', d: pathstr, markerEnd: 'url(#arrow)', strokeWidth: .6}) |
|
}) |
|
|
|
|
|
var s = colH |
|
var p = 2 |
|
|
|
var l0Sel = c.svg.appendMany('path.set', sets).classed('set1', true) |
|
.translate(d => [colW + offsetW, s/2 + .5]) |
|
|
|
drawRow(rowSel) |
|
function drawRow(rowSel){ |
|
rowSel.append('rect.set.no-stroke') |
|
.at({x: -p, y: -p, width: colW + p*2, height: colH + p*2, fill: '#fff'}).classed('set1', true) |
|
|
|
rowSel.appendMany('g', d => d) |
|
.translate(d => [d.i*s + s/2, s/2]) |
|
.each(function(d){ |
|
|
|
var sOffset = 12 |
|
var classNames = [d.shape, d.size, d.color, 'rank-item'].join(' ') |
|
var shapeSel = d3.select(this).append('rect') |
|
.at({ |
|
x: -s/2, |
|
y: -s/2 + (d.size == 'small' ? sOffset/2 : 0) - .5, |
|
width: s - .5, |
|
height: s - (d.size == 'small' ? sOffset : 0), |
|
fill: d.fill, |
|
class: classNames |
|
}) |
|
|
|
if (d.shape == 'triangle'){ |
|
var shapeSel = d3.select(this).append('circle') |
|
.at({r: 2, fill: '#fff', stroke: '#000', strokeWidth: .5, class: classNames}) |
|
} |
|
}) |
|
|
|
} |
|
|
|
var setSel = c.svg.selectAll('.set1') |
|
.on('mouseover', selectSet) |
|
|
|
sets.selected = sets[0] |
|
function selectSet(set){ |
|
sets.selected = set |
|
sets.forEach(d => d.selected = d == set) |
|
setSel |
|
.classed('selected', d => d.selected) |
|
.filter(d => d.selected) |
|
.lower() |
|
|
|
rowSel.classed('selected', d => d.selected) |
|
|
|
sliders.render() |
|
} |
|
|
|
|
|
var sliders = makeSliders(metrics, sets, c, selectSet, drawRow, () => { |
|
sets.forEach(shapes => { |
|
shapes.score = metrics.map(m => { |
|
var v = d3.sum(shapes, (d, i) => shapes[i][m.field] == m.key) |
|
return Math.abs(m.target - v/shapes.length) |
|
}) |
|
}) |
|
|
|
measures.forEach(m => { |
|
sets.forEach(shapes => { |
|
shapes[m.str] = m.fn(shapes.score) |
|
}) |
|
_.sortBy(sets, d => d[m.str] + d.i/10000000) |
|
.forEach((d, i) => d['i' + m.str] = i) |
|
|
|
m.rowSel.translate(d => d['i' + m.str]*(colH + colHpad), 1) |
|
}) |
|
|
|
var p = 0 |
|
l0Sel.at({d: d => [ |
|
'M', p, d['iUtilitarian']*(colH + colHpad), |
|
'L', colWpad - p, d['iEgalitarian']*(colH + colHpad), |
|
].join(' ')}) |
|
|
|
|
|
scoreLabelsMean.text(d => { |
|
return d3.format('.2f')(d['Utilitarian']) |
|
}) |
|
scoreLabelsMin.text(d => { |
|
return measures[1].ppFn(d['score']).replace('%', '') |
|
}) |
|
}) |
|
|
|
sliders.render() |
|
selectSet(_.sortBy(sets, d => d.iEgalitarian)[0]) |
|
} |
|
window.initColumns('#columns-height', metrics1, measures) |
|
window.initColumns('#columns-height-disagree', metrics2, measures2) |
|
|
|
|
|
d3.select('#columns-height-disagree').selectAll('.rank-item').at({opacity: .3}) |
|
d3.select('#columns-height-disagree').selectAll('.green').at({opacity: 1}) |
|
|
|
|
|
d3.select('#columns-height-disagree').selectAll('.slider').at({opacity: d => { |
|
return d.key !== 'green' ? 0.35: 1 |
|
}}) |
|
|
|
|