p5/D3 Cookbook

Combining the power of D3.js with the simplicity of p5.js

      function setup() {
  
  var width = 700,
      height = 300,
      margin = 30;
  
  createCanvas(width + margin*2, height + margin*2);
  
  push();
  translate(margin,margin);  
  
  
  //y axis
  var D3yscale = d3.scale.linear()
    .domain([0, 10])
    .range([height,0]);
  
  var D3yaxis = d3.svg.axis()
    .scale(D3yscale)
    .orient('left')
  
  var p5yaxis = D3p5axis(D3yaxis);
  
  p5yaxis.drawTicks(function(txt) {
    stroke('#ddd');
    line(0,0,width,0);
    noStroke();
    fill('black');
    textAlign(RIGHT);
    text(txt, -5, 5);
  });
  
  p5yaxis.drawConnectingLine(function(startX, endX) {
    //no line connecting
  });
  
    //x axis
  var D3xscale = d3.scale.ordinal()
    .domain(['planes','trains','automobiles', 'ferries', 'subways', 'taxis', 'ubers', 'lyft'])
    .rangeRoundBands([0,width], .1);
  
  var D3xaxis = d3.svg.axis()
    .scale(D3xscale)

  var p5axis = D3p5axis(D3xaxis, 0, height);
  
  p5axis.drawTicks(function(txt) {
    fill('black');
    noStroke();
    textAlign(CENTER);
    text(txt, 0, 23);
    stroke('black');
    line(0,3,0,10);
   
  });
  
  p5axis.drawConnectingLine(function(startX, endX) {
    stroke('black');
    strokeWeight(2);
    line(startX, 0, endX, 0);
  });
  
  
  var data = [1,2,3,4,5,4.5,5,9.5];
  
  for(var i = 0; i < data.length; i++) {
    fill('blue');
    var xOffset = D3xscale.range()[i];
    var barWidth = D3xscale.rangeBand();
    var barHeight = D3yscale(data[i]);
    var maxHeight = D3yscale(0);
    push();
    translate(xOffset, 0);
    rect(0, barHeight, barWidth, maxHeight-barHeight);
    pop();
  }
  
  pop();
  
  
  //Add a title
  fill('#000');
  noStroke();
  textSize(15);
  text("Drawing D3 axes using p5 canvas methods", 30, 20);
 
}


//Function for converting D3 axis to p5 drawing methods
p5.prototype.D3p5axis = function(d3Axis, x, y) {
  x = x || 0;
  y = y || 0;
  var D3scaleObj = d3Axis.scale();  
  var customDOMaxis = d3.select('body').append('custom').style('display', 'none').call(d3Axis);
  var ticks = customDOMaxis.selectAll('g');
  
  var returnFunction = function() {}
  
  returnFunction.drawTicks = function(drawFunction) {
    push();
    translate(x,y);
    ticks.each(function() {
      var translateObj = d3.transform(d3.select(this).attr('transform'));
      var translateX = translateObj.translate[0];
      var translateY = translateObj.translate[1];
      push();
      translate(translateX, translateY);
      var txt = d3.select(this).select('text').text();
      drawFunction(txt);
      pop();
    });
    pop();
  }
  
  returnFunction.drawConnectingLine = function(drawFunction) {
    push();
    translate(x,y);
    drawFunction(D3scaleObj.range()[0],D3scaleObj.range()[1]);
    pop();
  }
  
  return returnFunction;
}