Skip to content

Instantly share code, notes, and snippets.

@gka
Created June 21, 2017 12:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gka/52653eea329b7953b29b35f72ce43bc0 to your computer and use it in GitHub Desktop.
Save gka/52653eea329b7953b29b35f72ce43bc0 to your computer and use it in GitHub Desktop.
poll jitter bar
license: mit
<!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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment