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 | |
| }}) | |