Skip to content

Instantly share code, notes, and snippets.

@newsummit
Last active May 18, 2019 13:32
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save newsummit/b52a9b22d4b2b0486a8e40ae07419e97 to your computer and use it in GitHub Desktop.
Save newsummit/b52a9b22d4b2b0486a8e40ae07419e97 to your computer and use it in GitHub Desktop.
Simple graph with filled area in v4
license: mit

This is a simple graph demonstrating the addition of a filled area in conjunction with a line graph. This was written using d3.js v4 and is a follow on to the simple graph example here.

This graph is part of the code samples for the update to the book D3 Tips and Tricks to version 4 of d3.js.

forked from d3noob's block: Simple graph with filled area in v4

date close
1-May-12 58.13
30-Apr-12 53.98
27-Apr-12 67.00
26-Apr-12 89.70
25-Apr-12 99.00
24-Apr-12 130.28
23-Apr-12 166.70
20-Apr-12 234.98
19-Apr-12 345.44
18-Apr-12 443.34
17-Apr-12 543.70
16-Apr-12 580.13
13-Apr-12 605.23
12-Apr-12 622.77
11-Apr-12 626.20
10-Apr-12 628.44
9-Apr-12 636.23
5-Apr-12 633.68
4-Apr-12 624.31
3-Apr-12 629.32
2-Apr-12 618.63
30-Mar-12 599.55
29-Mar-12 609.86
28-Mar-12 617.62
27-Mar-12 614.48
26-Mar-12 606.98
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
.area {
fill: lightsteelblue;
}
.sla__line {
stroke: #F74C7D;
stroke-width: 2;
stroke-dasharray: 6 3;
}
.sla__label {
fill: white;
}
.issue__line {
stroke: steelblue;
stroke-width: 20;
opacity: .5;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// set the dimensions and margins of the graph
const margin = {top: 20, right: 20, bottom: 30, left: 80};
const width = 960 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
const arr = [];
// parse the date / time
const dateFormat = "%B %d, %Y";
const parseTime = d3.timeParse(dateFormat);
const formatTime = d3.timeFormat(dateFormat);
const randNum = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
// Set up random data
const numDays = 45;
const graphData = Array(numDays)
.fill()
.map((_, index) => {
const newD = new Date();
newD.setDate(newD.getDate() - index);
return {
date: parseTime(formatTime(newD)),
value: randNum(5, 15)
}
});
const fillArr = (num) => {
if (arr.includes(num)) {
fillArr(randNum(num - 1, 20));
} else {
arr.push(num);
return num;
}
};
for (let i=0; i < 11; i++) {
fillArr(randNum(1, 20));
}
const lineData = Array(10)
.fill()
.map((_, index) => graphData[arr[index]]);
// set the ranges
const x = d3.scaleTime().range([0, width]);
const y = d3.scaleLinear().range([height, 0]);
// define the area
const area = d3.area()
.x(d => x(d.date))
.y0(height)
.y1(d => y(d.value))
.curve(d3.curveMonotoneX);
// define the line
const valueline = d3.line()
.x(d => x(d.date))
.y(d => y(d.value))
.curve(d3.curveMonotoneX);
// append the svg obgect to the body of the page
const svg = d3.select("body")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// scale the range of the data
x.domain(d3.extent(graphData, d => d.date));
y.domain([0, d3.max(graphData, d => d.value + 5)]);
// add the X Axis
svg.append("g")
.attr("class", "x-axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the Y Axis
svg.append("g")
.attr("class", "y-axis")
.call(d3.axisLeft(y));
// Add grid
svg.selectAll('.y-axis .tick line')
.attr('stroke', '#E3E3E3')
.attr('stroke-width', 1)
.attr('x1', 0)
.attr('x2', width);
svg.selectAll('.x-axis .tick line')
.attr('stroke', '#E3E3E3')
.attr('stroke-width', 1)
.attr('y1', 0)
.attr('y2', -height)
// add the area
svg.append("path")
.data([graphData])
.attr("class", "area")
.attr("d", area);
// add the valueline path.
svg.append("path")
.data([graphData])
.attr("class", "line")
.attr("d", valueline);
// Draw HZ line
addLine(svg);
// Draw Vert lines
addVertLines(svg);
function addVertLines(svg) {
const vertLine = svg.selectAll('.issue')
.data(lineData)
.enter()
.append('g')
.attr('transform', d => `translate(${x(d.date)}, 0)`);
vertLine.append('line')
.attr('y1', 0)
.attr('y2', height)
.attr('class', 'issue__line');
}
function addVertLine(pos) {
svg.append("line")
.attr("x1", x(today)) //<<== change your code here
.attr("y1", 0)
.attr("x2", x(today)) //<<== and here
.attr("y2", height - margin.top - margin.bottom)
.style("stroke-width", 2)
.style("stroke", "red")
.style("fill", "none");
}
function addLine(svg) {
const rectHeight = 20;
const rectYoffset = -10;
const rectXoffset = 0;
const rectPadding = 10;
// Add SLA element group and position
const sla = svg.selectAll('.sla')
.data([10])
.enter()
.append('g')
.attr('transform', d => `translate(-50, ${y(d)})`);
// Add SLA line
sla.append('line')
.attr('x1', 0)
.attr('x2', width + 50)
.attr('class', 'sla__line');
// Add SLA label group (default position)
const labelEl = sla.append('g');
// Position text box
const rectEl = labelEl.append('rect')
.attr('rx', '3')
.attr('ry', '3')
.attr('fill', '#F74C7D')
.attr('height', rectHeight)
.attr('transform', `translate(${rectXoffset}, ${-rectHeight - rectYoffset})`);
// Position text
const textEl = labelEl.append('text')
.attr('class', 'sla__label')
.text(d => `${d}ms`)
.attr('dx', rectPadding / 2)
.attr('dy', rectPadding / 2);
// Read box width from text length
rectEl
.attr('width', textEl.node().getComputedTextLength() + rectPadding);
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment