JSFiddle - React, Tailwind, and code Playground

by yoni sidi

HTML

<script src="//d3js.org/d3.v3.min.js"></script>
<form>
  <label for="interpolate">Interpolate:</label>
  <select id="interpolate"></select><br>
</form>

CSS

body {
  font: 13px sans-serif;
  position: relative;
  width: 960px;
  height: 500px;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

form {
  position: absolute;
  top: 10px;
  left: 20px;
}

rect {
  fill: none;
  pointer-events: all;
}

circle,
.line {
  fill: none;
  stroke: steelblue;
  stroke-width: 1.5px;
}

circle {
  fill: #fff;
  fill-opacity: .2;
  cursor: move;
}

.selected {
  fill: #ff7f0e;
  stroke: #ff7f0e;
}

.tooltip {
  position: absolute;
  width: 200px;
  height: 28px;
  pointer-events: none;
}

JavaScript

var 
    width = 960,
    height = 500;


var points = d3.range(1, 5).map(function(i) {
  return [i * width / 5, 50 + Math.random() * (height - 100)];
});

// setup x 
var xValue = function(d) { return d[0];}, // data -> value
    xScale = d3.scale.linear().range([0, width]),
    xMap = function(d) { return xScale(xValue(d));}, // data -> display
    xAxis = d3.svg.axis().scale(xScale).orient("bottom");

// setup y
var yValue = function(d) { return d[1];}, // data -> value
    yScale = d3.scale.linear().range([height, 0]), // value -> display
    yMap = function(d) { return yScale(yValue(d));}, // data -> display
    yAxis = d3.svg.axis().scale(yScale).orient("left");


var dragged = null,
    selected = points[0];

var line = d3.svg.line();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("tabindex", 1);

svg.append("rect")
    .attr("width", width)
    .attr("height", height)
    .on("mousedown", mousedown);

svg.append("path")
    .datum(points)
    .attr("class", "line")
    .call(redraw);

d3.select(window)
    .on("mousemove", mousemove)
    .on("mouseup", mouseup)
    .on("keydown", keydown);

d3.select("#interpolate")
    .on("change", change)
  .selectAll("option")
    .data([
      "linear",
      "step-before",
      "step-after",
      "basis",
      "basis-open",
      "basis-closed",
      "cardinal",
      "cardinal-open",
      "cardinal-closed",
      "monotone"
    ])
  .enter().append("option")
    .attr("value", function(d) { return d; })
    .text(function(d) { return d; });

svg.node().focus();

function redraw() {
  svg.select("path").attr("d", line);

// don't want dots overlapping axis, so add in buffer to data domain
  xScale.domain([d3.min(points, xValue)-1, d3.max(points, xValue)+1]);
  yScale.domain([d3.min(points, yValue)-1, d3.max(points, yValue)+1]);

// x-axis
  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
     ...