JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://d3js.org/d3.v4.min.js"></script>
<div>
</div>
CSS
text {
fill: white;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
/* tell the SVG path to be a thin blue line without any area fill */
path.line {
stroke: #00AEEF;
stroke-width: 4;
fill: none;
&.bad {
stroke: #EE227B;
}
}
.overlay {
fill: none;
pointer-events: all;
}
path.domain {
stroke: none;
}
.tick {
line {
stroke: none;
}
}
.area {
fill: url(#area-gradient);
stroke-width: 0;
&.bad {
fill: url(#bad-area-gradient);
}
}
circle {
fill: #D8D8D8;
stroke: #000;
stroke-width: 1;
}
.chart-value-inspector {
border: solid 1px #d8d8d8;
}
JavaScript
function drawEndPoint(svg, point) {
svg.append('circle')
.attr('class', 'endpoint')
.attr('cx', point.x)
.attr('cy', point.y)
.attr('r', '5');
}
function computeArea(xScale, yScale, bottom, yVariable) {
return d3.area()
.x(d => xScale(d.x))
.y0(bottom)
.y1(d => yScale(d[yVariable]))
}
function drawArea(svg, data, computedArea, className = '') {
return svg.append('path')
.datum(data)
.attr('class', 'area ' + className)
.attr('d', computedArea);
}
function computeLine(xScale, yScale, yVariable) {
return d3.line()
.x(d => xScale(d.x))
.y(d => yScale(d[yVariable]))
}
function drawLine(svg, data, computedLine, className) {
return svg.append('path')
.datum(data)
.attr('class', className)
.attr('d', computedLine);
}
function drawXAxisHelper(svg, xScale, xExtent, height, tickFormat) {
let xAxisLabel = svg.append('g')
.attr('transform', 'translate(0,' + height + ')')
.call(d3.axisBottom(xScale)
.tickValues(xExtent)
.tickFormat(d => tickFormat(d)));
// Align all text to the end
xAxisLabel.selectAll('text')
.style('text-anchor', 'end');
// Align the first text element to the start
xAxisLabel.select('text')
.style('text-anchor', 'start');
}
function drawXAxisWithAge(svg, xScale, xExtent, height, baseAge) {
drawXAxisHelper(svg, xScale, xExtent, height, d => {
let year = new Date().getFullYear();
return `${year + d - 1} - (Age ${baseAge + d - 1})`;
});
}
function drawXAxis(svg, xScale, xExtent, height) {
drawXAxisHelper(svg, xScale, xExtent, height, d => d);
}
function drawVerticalGradient(svg, id, bottomColor, topColor) {
return svg.append('linearGradient')
.attr('id', id)
.attr('x1', '100%')
.attr('y1', '100%')
.attr('x2', '100%')
.attr('y2', '0%')
.attr('spreadMethod', 'pad')
.selectAll('stop')
.data([{
offset: '0%',
color: bottomColor
}, {
offset: '100%',
color: topColor
}])
...