block by gka 52653eea329b7953b29b35f72ce43bc0

poll jitter bar

Full Screen

Built with blockbuilder.org

index.html

<!DOCTYPE html>
<head>
  <meta charset="utf-8">
  <script src="https://rawgit.com/gka/d3-jetpack/master/build/d3v4+jetpack.js"></script>
  <style>
    div { margin:10px }
    body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
    rect { fill: gray; }
    text { fill: white; font-weight:bold; }
  </style>
</head>

<body>
  <div>poll results (sep by comma): <input class="results" value="51,44" /></div>
  <div>margin of error: <input class="error" value="5.0" /></div>
	
  <script>
   
    var p5 = P5();
    
    var w = 400;
    
    // Feel free to change or delete any of the code you see in this editor!
    var svg = d3.select("body").append("svg")
      .attr("width", 960)
      .attr("height", 500)
    	.append('g').translate([30,30]);
    
    var bars, rect, lbl, results, error, 
        undecided, offsets, max, t;
    
    changed();
    
    d3.selectAll('input')
      	.on('keyup', changed)
    		.on('change', changed);
    
   	function changed() {
      svg.html('');
      
      results = d3.select('.results')
          .prop('value')
          .split(',')
          .map(Number);
      
      error = +d3.select('.error').prop('value');
      undecided = 100 - d3.sum(results);
      offsets = results.map(Math.random);
      max = d3.max(results) + undecided + error;
      
      console.log(results, undecided);
    
      bars = svg.appendMany(results, 'g.bar')
        .translate(function(d,i) { return [0,i*50]; });

      rect = bars.append('rect')
        .at({height:30, width: 10});

      lbl = bars.append('text').translate([5,20]);
      t = 0;
    }
    
    
    
    d3.interval(function() {
      var jit = p5.noise(t);
      
      var jitters = results.map(function(d,i) {
        return p5.noise(t + offsets[i]);
      });
      var sum_jit = d3.sum(jitters);
      var results_jit = results.map(function(r,i) {
        return r + (jitters[i]/sum_jit) * (undecided + 2*error);
      });
      var sum_res = 100/d3.sum(results_jit);
      
      rect.attr('width', function(d,i) {
        return (results_jit[i]*sum_res)/max * w;
      });
      lbl.text(function(d,i) {
        return (results_jit[i]*sum_res).toFixed(1)+'%';
      })
      t += 0.07;
    }, 1000/30);
    
 
    function P5() {
    
        var PERLIN_YWRAPB = 4;
        var PERLIN_YWRAP = 1<<PERLIN_YWRAPB;
        var PERLIN_ZWRAPB = 8;
        var PERLIN_ZWRAP = 1<<PERLIN_ZWRAPB;
        var PERLIN_SIZE = 4095;

        var perlin_octaves = 4; // default to medium smooth
        var perlin_amp_falloff = 0.5; // 50% reduction/octave

        var scaled_cosine = function(i) {
          return 0.5*(1.0-Math.cos(i*Math.PI));
        };

        var perlin; // will be initialized lazily by noise() or noiseSeed()

        return {
            noise: noise
        };

        function noise(x,y,z) {
            y = y || 0;
            z = z || 0;

            if (perlin == null) {
                perlin = new Array(PERLIN_SIZE + 1);
                for (var i = 0; i < PERLIN_SIZE + 1; i++) {
                    perlin[i] = Math.random();
                }
            }

            if (x<0) { x=-x; }
            if (y<0) { y=-y; }
            if (z<0) { z=-z; }

            var xi=Math.floor(x), yi=Math.floor(y), zi=Math.floor(z);
            var xf = x - xi;
            var yf = y - yi;
            var zf = z - zi;
            var rxf, ryf;

            var r=0;
            var ampl=0.5;

            var n1,n2,n3;

            for (var o=0; o<perlin_octaves; o++) {
                var of=xi+(yi<<PERLIN_YWRAPB)+(zi<<PERLIN_ZWRAPB);

                rxf = scaled_cosine(xf);
                ryf = scaled_cosine(yf);

                n1  = perlin[of&PERLIN_SIZE];
                n1 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n1);
                n2  = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
                n2 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n2);
                n1 += ryf*(n2-n1);

                of += PERLIN_ZWRAP;
                n2  = perlin[of&PERLIN_SIZE];
                n2 += rxf*(perlin[(of+1)&PERLIN_SIZE]-n2);
                n3  = perlin[(of+PERLIN_YWRAP)&PERLIN_SIZE];
                n3 += rxf*(perlin[(of+PERLIN_YWRAP+1)&PERLIN_SIZE]-n3);
                n2 += ryf*(n3-n2);

                n1 += scaled_cosine(zf)*(n2-n1);

                r += n1*ampl;
                ampl *= perlin_amp_falloff;
                xi<<=1;
                xf*=2;
                yi<<=1;
                yf*=2;
                zi<<=1;
                zf*=2;

                if (xf>=1.0) { xi++; xf--; }
                if (yf>=1.0) { yi++; yf--; }
                if (zf>=1.0) { zi++; zf--; }
            }
            return r;
        }
		}
  </script>
</body>