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 + ")")
...