block by emeeks 5022696

Slightly Random Colors

Full Screen

I think it may be more legible for information visualization to utilize a rougher specification for color and other element aspects. In this implementation, perturbations of color and line thickness provide a less uniform set of squares, but they are still nearly the same color. Perturbations of color, size, and line can all provide not only a nuanced aesthetic, but perhaps also convey a certain uncertainty in the data visualization. Using rgb specification, you imply a sort of precision similar to decimal precision in spatial coordinates, and by wiring your visualization to produce a slightly rougher color spectrum on output, you might correct for that. While line jitter has been a feature of drawing packages for some time, I haven’t seen procedural application of this kind of perturbation to traditional data visualization.

I’m going to add some perturbation of paths following the same concept. I’ll also put a few buttons in for user interaction.

index.html

<!DOCTYPE html>
<html xmlns="//www.w3.org/1999/xhtml">
<meta charset="utf-8">
  <head>
    <title>Color Perturbation for Information Visualization</title>
  </head>
<style>

#colorviz {
  width: 960px;
  height: 960px;
}

</style>
<script src="//d3js.org/d3.v3.min.js"></script>

<body>
<div><input type="color" onchange="changeColor(this.value)" name="colorselection">
  <form>
    Variation <input id="variationSlider" type="range" onchange="changeColor(currentColor)" min ="1" max="50" step ="1"  value="15" /> 
  <input type="text" id="variationInput" value="15" />
  </form>
</div>
<div id="colorviz">
</div>
</body>

<script>

currentColor = "#40F065";
var width = 960,
    height = 960;

var svg = d3.select("#colorviz").append("svg")
    .attr("width", width)
    .attr("height", height);
someData = [];
    
for (i=0;i<506;i++) {
  someData.push(i);
}

svg.selectAll('rect')
.data(someData)
.enter()
.append('rect')
.attr("height",20)
.attr("width",20)
.attr("class","base")
.attr('x',function(d,i) {return i%22 * 20})
.attr('y',function(d,i) {return i%23 * 20})
.style("fill",function() {return lessSlightlyRandomColor(40,240,65,15)})
.style("stroke", function() {return lessSlightlyRandomColor(155,155,155,15)})
.style("stroke-width", function() {return slightlyRandomLineWidth(1,.95)})

svg
.append('rect')
.attr("height",80)
.attr("width",80)
.attr('x',450)
.attr('y',20)
.attr("class","not")
.style("fill", "rgb(40,240,65)")
.style("stroke", "rgb(155,155,155)")
.style("stroke-width", .45)

scaleRamp = d3.scale.linear().domain([0,9,19]).range(["#FF0000","#00FF00","#0000FF"]).clamp(true);
var someOtherData = [];
for (i=0;i<20;i++) {
  someOtherData.push(i);
}

    

    svg.selectAll('rect.ramp')
    .data(someOtherData)
    .enter()
    .append("rect")
    .attr("class","ramp")
    .attr("height",20)
    .attr("width",20)
    .attr("y", 470)
    .attr("x", function(d,i){ return i * 20})
    .style("fill", function(d,i) { var rgbColor = fromHex(scaleRamp(i)); return lessSlightlyRandomColor(rgbColor[0],rgbColor[1],rgbColor[2],15)})
    .style("cursor", "pointer")
    .on("click", function(d) {changeColor(d3.select(this).style("fill"))})
    

function changeColor(colorPicked) {
  currentColor = colorPicked;
  var rgbColor = fromHex(colorPicked);
  
  var newVariation = document.getElementById('variationSlider').value;
  
  document.getElementById('variationInput').value = newVariation;


svg.select('rect.not')
.style("fill", colorPicked)

svg.selectAll('rect.base')
.style("fill",function() {return lessSlightlyRandomColor(rgbColor[0],rgbColor[1],rgbColor[2],newVariation)})
.style("stroke-width", function() {return slightlyRandomLineWidth(1,.95)})

svg.selectAll('rect.ramp')
.style("fill", function(d,i) { var rgbColor = fromHex(scaleRamp(i)); return lessSlightlyRandomColor(rgbColor[0],rgbColor[1],rgbColor[2],newVariation)})
  
}

function fromHex(hexInput) {
r = hexToR(hexInput);
g = hexToG(hexInput);
b = hexToB(hexInput);

function hexToR(h) {return parseInt((cutHex(h)).substring(0,2),16)}
function hexToG(h) {return parseInt((cutHex(h)).substring(2,4),16)}
function hexToB(h) {return parseInt((cutHex(h)).substring(4,6),16)}
function cutHex(h) {return (h.charAt(0)=="#") ? h.substring(1,7):h}
return [r,g,b];
}
    
    function slightlyRandomColor(r,g,b,range) {
      r = r + (Math.floor(Math.random() * range) - Math.floor(range / 2));
      g = g + (Math.floor(Math.random() * range) - Math.floor(range / 2));
      b = b + (Math.floor(Math.random() * range) - Math.floor(range / 2));
      return "rgb("+r+","+g+","+b+")"
    }

    function lessSlightlyRandomColor(r,g,b,range) {
    var scaleRamp = d3.scale.linear().domain([256,0]).range([.5,2]).clamp(true);
    var rRange = (range * scaleRamp(r));
    var gRange = (range * scaleRamp(g));
    var bRange = (range * scaleRamp(b));
    

      r = r + (Math.floor(Math.random() * rRange) - Math.floor(rRange / 2));
      g = g + (Math.floor(Math.random() * gRange) - Math.floor(gRange / 2));
      b = b + (Math.floor(Math.random() * bRange) - Math.floor(bRange / 2));
      return "rgb("+r+","+g+","+b+")"
    }

    
    function slightlyRandomLineWidth(width,range) {
      return width + ((Math.random() * range) - range/2);
    }

    

</script>
</html>