| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- import * as d3 from 'd3';
- import { repr } from '../utilities/formatter';
- // d3js module for module04: poll generator
- export default () => {
- // defaults
- const options = {
- width: 475,
- height: 500,
- radius: 10,
- data: [],
- pollindex: 0,
- setData: () => {} // eslint-disable-line no-empty-function
- };
- // start
- const poll = selection => {
- const svg = selection.select('svg');
- const scores = options.data.map(distribution => distribution.score);
- const xScale = d3.scaleLinear().domain([ 0, 100 ]).range([ 0, options.width ]);
- const bisect = d3.bisector(d => d.cumul).left;
- // reset everything
- const reset = () => {
- svg.select('.counter').text('');
- svg.selectAll('rect.diff, rect.election').transition().duration(1000).attr('width', 0);
- svg.selectAll('text.difftext, text.result').text('');
- svg.selectAll('rect.poll').transition().duration(1000).attr('width', 0);
- svg.selectAll('text.polltext').text('');
- svg.selectAll('circle').transition()
- .duration(2000)
- .attr('cy', () => (options.height * Math.random()))
- .attr('cx', () => (options.width * Math.random()))
- .attr('fill-opacity', 0.2);
- };
- // generate new poll
- const generatepoll = pollind => {
- if (options.pollindex === 0) reset();
- let xIndex;
- let yind;
- // determine correct position
- if (pollind < options.numberOfCols) {
- xIndex = pollind;
- yind = 0;
- } else {
- xIndex = pollind - options.numberOfCols;
- yind = 1;
- }
- const polldata = [ 0, 0, 0, 0, 0 ];
- let pollperc = [ 0, 0, 0, 0, 0 ];
- let pollcounter = 0;
- // add them one by one
- const anim = setInterval(() => {
- animatepoll(1000); // eslint-disable-line no-use-before-define
- }, 1);
- // show poll results
- const animatepoll = pollsize => {
- if (pollcounter === pollsize) {
- clearInterval(anim);
- if (options.pollindex === 4) {
- options.setData({ continue: true });
- }
- }
- pollcounter += 1;
- // draw random sample ('index' corresponds to class index in 'data.json')
- const index = bisect(options.data, Math.random() * 100);
- // add to polldata
- polldata[index] += 1;
- // calculate difference with result
- pollperc = polldata.map(score => (Math.round(score / pollcounter * 1000) / 10));
- pollperc.forEach((element, i) => {
- pollperc[i] = Math.round((pollperc[i] - scores[i]) * 100) / 100;
- });
- const distance = (options.width - options.xoffset * 2) / (options.numberOfCols - 1);
- const xBase = options.xoffset + xIndex * distance;
- // increase rectangle width
- svg.selectAll(`rect.diff${xIndex}${yind}`)
- .data(pollperc)
- .attr('width', d => (xScale(Math.abs(d))))
- .attr('x', d => (d < 0 ? xBase - Math.abs(xScale(d)) : xBase));
- // add text, format it
- svg.selectAll(`.difftext${xIndex}${yind}`)
- .data(pollperc)
- .attr('x', d => (d > 0 ? xBase + xScale(d) + 7 : xBase + xScale(d) - 6))
- .attr('text-anchor', d => (d > 0 ? 'start' : 'end'))
- .text(d => repr(d))
- .attr('fill-opacity', pollcounter > 100 ? 1 : 0);
- };
- };
- // start next poll
- generatepoll(options.pollindex);
- };
- // "setter"
- poll.options = input => {
- Object.assign(options, input);
- return poll;
- };
- return poll;
- };
|