JSFiddle - React, Tailwind, and code Playground

by Rishabh Sharma

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>

JavaScript

var data = [
 { id: "A", value: 80 },
 { id: "B", value: 160 },
 { id: "C", value: 50 },
 { id: "D", value: 30 },
 { id: "E", value: -120 },
 { id: "F", value: -20 }
]

// For the N data points above, segments will be the resulting N + x segments
var segments;

// The x-value at which to break up a datum into one or more segments
var wrapLength;

var slider = d3.select("body").append("input")
  .attr({
    type: "range",
    value: 100,
    min: 50,
    max: 200,
    step: 1
  })
  .on('input', wrapAndRender)

var checkbox = d3.select("body")
	.append('label')
  .html('<span>Zig zag?</span>')
  .insert("input", 'span')
	.attr({
  	type: "checkbox",
    checked: true
   })
  .on('change', wrapAndRender)

var colorScale = d3.scale.category10()

var svg = d3.select("body").append("svg")
  .attr('width', window.innerWidth)
  .attr('height', window.innerHeight - 50);
var bars = svg.append('g')
  .attr({
    class: 'bars',
    transform: 'translate(10, 30)'
  });
var pies = svg.append('g')
  .attr({
    class: 'pies',
    transform: 'translate(130, 250)'
  });
var legend = svg.append('g')
  .attr({
    class: 'legend',
    transform: 'translate(30, 450)'
  });

wrapAndRender()

function wrapAndRender() {
  // The x-value at which to break up a datum into multiple segments
  wrapLength = Number(slider.property('value'));
  var zigzag = checkbox.property('checked');
  
  // Turn N data points into N + x segments, as dictated by wrapLength. Do this separately
  // for positive and negative values. They'll be merged further down, after we apply
  // a specific transformation to just the negatives
  var positiveSegments = wrap(data.filter(function(d) { return d.value > 0; }), wrapLength);
  var negativeSegments = wrap(data.filter(function(d) { return d.value < 0; }), wrapLength);
  
  // Flip and offset-by-one the y-value of every negative segment. I.e. 0 becomes -1, 1 becomes -2
  negativeSegments.forEach(function(segment) { segment.y = -(segment.y + 1); });
  
  // Flip...