Spaces:
Running
Running
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)//.reverse() | |
.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) | |
// Only highlight green items in the second ranking chart. | |
d3.select('#columns-height-disagree').selectAll('.rank-item').at({opacity: .3}) | |
d3.select('#columns-height-disagree').selectAll('.green').at({opacity: 1}) | |
// Only highlight the green slider in the second ranking chart. | |
d3.select('#columns-height-disagree').selectAll('.slider').at({opacity: d => { | |
return d.key !== 'green' ? 0.35: 1 | |
}}) | |