Remove d3.js path on resize - javascript

I'm trying to remove a previous path on the resize of a window. You can see my attempts at the line/path removal at the end. I suspect I'm not referencing the correct element(s); I'd like to remove all the contents of the svg (axes, path) and redraw them. Currently I just get a smear of all previous paths/axes.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Test Plot Viewer</title>
<script src="js/lib/d3.v4.min.js"></script>
<style>
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
#chart {
position: fixed;
left: 55px;
right: 15px;
top: 10px;
bottom: 55px;
}
</style>
</head>
<body>
<div id="chart"></div>
<script>
var chartDiv = document.getElementById("chart");
var svg = d3.select(chartDiv).append("svg");
function render() {
// Extract the width and height that was computed by CSS.
var width = chartDiv.clientWidth;
var height = chartDiv.clientHeight;
// Use the extracted size to set the size of an SVG element.
svg
.attr("width", width)
.attr("height", height);
// set the dimensions and margins of the graph
var margin = {top: 10, right: 15, bottom: 55, left: 55};
width = width - margin.left - margin.right,
height = height - margin.top - margin.bottom;
// parse the date time
var parseTime = d3.timeParse("%m/%d %H:%M");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the line
var valueline = d3.line()
.x(function(d) { return x(d.time); })
.y(function(d) { return y(d.solar); });
// Get the data
d3.csv("data_eos.csv", function(error, data) {
if (error) throw error;
// format the data
data.forEach(function(d) {
d.time = parseTime(d.time);
d.solar = +d.solar;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.time; }));
y.domain([0, d3.max(data, function(d) { return d.solar; })]);
// Add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat("%m/%d %H:%M ")))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-45)");
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
});
}
// d3.select("svg").remove();
// svg.remove();
// d3.selectAll("g > *").remove()
// d3.selectAll("chartDiv.path.line").remove();
// d3.select("path.line").remove();
render();
// Redraw based on the new size whenever the browser window is resized.
window.addEventListener("resize", render);
</script>
</body>
</html>
My feeble attempts at removing just the line are commented out near the end.
Any Ideas? TIA.

Add jQuery to your scripts and add $("svg").empty() right after your render function starts.
Like so..
function render() {
$("svg").empty();
// Extract the width and height that was computed by CSS.
var width = chartDiv.clientWidth;
var height = chartDiv.clientHeight;
// Use the extracted size to set the size of an SVG element.
svg
.attr("width", width)
.attr("height", height);...
So every time the window is resized, all the contents of your svg are emptied/removed.
Also refer to this website. There's a nice example for responsive charts. Try to structure yours in the same way and you're sorted :)

Removing All path by class
//d3.selectAll("chartDiv.path.line").remove();
d3.selectAll('.line').remove()
Removing path on nasted element
//d3.selectAll("chartDiv.path.line").remove();
var chartDiv = document.getElementById("chart");
var svg = d3.select(chartDiv).append("svg")
svg.attr('id','mysvg')
d3.select('#chart').selectAll('.line').remove()
Removing svg
//d3.select("svg").remove();
d3.select('#mysvg').remove()

Related

area chart not able render D3.js

I am learning d3.js and this is me trying to learn area chart but i am getting this error of :
<!DOCTYPE html>
<meta charset="utf-8" />
<style>
/* set the CSS */
.line {
fill: none;
stroke: green;
stroke-width: 2px;
}
.area {
fill: green;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
// set the dimensions and margins of the graph
var margin = { top: 20, right: 20, bottom: 30, left: 50 },
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%B %e, %Y");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the area
var area = d3
.area()
.x(function (d) {
return x(d.Date);
})
.y0(height)
.y1(function (d) {
return y(d["New cases"]);
});
// define the line
var valueline = d3
.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.newcases);
});
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var 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 + ")");
// get the data
d3.csv(
"https://raw.githubusercontent.com/pravinpoudel/file-host/main/COVID-Utah.csv"
).then(function (data) {
// format the data
data.forEach(function (d) {
d.Date = parseTime(d.Date);
d["New cases"] = +d["New cases"];
});
x.domain(
d3.extent(data, function (d) {
return d.Date;
})
);
y.domain([
0,
d3.max(data, function (d) {
return d["New cases"];
}),
]);
// add the area
svg.append("path").data([data]).attr("class", "area").attr("d", area);
// add the valueline path.
svg
.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// add the X Axis
svg
.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the Y Axis
svg.append("g").call(d3.axisLeft(y));
});
</script>
</body>
can anyone please help me on this !!
I think I've found an answer, so let me try and pitch in.
The biggest issue is how you append the <path> elements for the area and line.
svg.append("path").data([data]).attr("class", "area").attr("d", area);
svg.append("path").data([data]).attr("class", "line").attr("d", valueline);
Once you append the <path> element you instead need to pass the data in the area and valueline functions.
svg.append("path").attr("class", "area").attr("d", area(data));
svg.append("path").attr("class", "line").attr("d", valueline(data));
Unfortunately this is not enough, and the console points you to the error.
Error: <path> attribute d: Expected number, "…5.1232876712329,NaNL882.68493150…"
Some coordinates are assigned a value of NaN, and looking at the data this has to do with the New cases field. The value is not always a number, often NaN or N/A. As a workaround you can try the conversion and provide a fallback.
d["New cases"] = +d["New cases"]
+d["New cases"] = +d["New cases"] || 0;
It's a bit of a judgment call, however. You need to decide how to interpret data points which do not have an available value.
With these two changes you finally are able to display the area, but not the line. Looking at the definition of valueline it seems you point to two different properties.
var valueline = d3
.line()
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.newcases);
});
Be sure to reference the properties of the data, as you have done with the area function.
-return x(d.date);
+return x(d.Date);
-return y(d.newcases);
+return y(d['New cases']);
As the line and area have the same color you might find it difficult to distinguish them visually, but they are both plotted.
A minor note on the name of the svg variable.
var 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 + ")");
As you mention in the comment you append a group element to translate the origin. This means the variable refers to the group element, and not the svg.
Hope it helps.

Interacting with a tooltip in d3js v4

I'm creating a proof of concept in v4 of D3JS. One of the things I'm trying to do is have a tooltip display when hovering over a data point. I found a good example of this here.
What I now need to do is add a link (or any clickable element) to the tooltip. I created a plunkr based on the example above and added a link to the tooltip. I can't click on the link and the tooltip appears to be below the line-chart as far as z-index goes.
I've tried setting the z-index on the chart and the tooltip to no avail. Can anyone point me in the right direction to sort this?
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 150px;
height: 100px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
</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
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%d-%b-%y");
var formatTime = d3.timeFormat("%e %B");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the line
var valueline = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var 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 + ")");
var div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// Get the data
d3.csv("data.csv", function(error, data) {
if (error) throw error;
// format the data
data.forEach(function(d) {
d.date = parseTime(d.date);
d.close = +d.close;
});
// scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// add the dots with tooltips
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
div.transition()
.duration(200)
.style("opacity", .9);
div.html(formatTime(d.date) + "<br/>" + d.close + "<br/><a href='www.google.com'>Test it</a>")
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
});
// add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
});
</script>
</body>
When creating your tooltip based on the example in the link, you copied its CSS:
div.tooltip {
pointer-events: none;
...
}
The reason we generally set pointer-events to none in a <div> tooltip, as the linked example did, is that we want to get the mouseout event on the element that fired the mouseover (normally to set the tooltip's opacity to zero), and if the tooltip is positioned to close from the element (sometimes even directly over it) the pointer can hover over the div and ruin the mouseout. Besides that, another important reason to set pointer-events to none is that it allows other elements behind the tooltip to get mouseover events, just like if the tooltip was not there.
However, because in your code there is no mouseout, the easier solution here is simply eliminating the pointer-events: none in the CSS. That way the <div> get the click event.
This is the updated plunker: https://plnkr.co/edit/xfa8cjQd3tHYNu0dUla4?p=preview

D3.js Line Chart - Can't get x-axis to show up

I'm following this example by Mike himself. The timeFormat in the example is ("%d-%b-%y"), but using my own data uses just the year. I've made all the necessary changes (I think). The y-axis shows, but the x-axis doesn't. There are also no errors showing, so I'm not sure where to go. Below is my code. Thanks!
<!DOCTYPE html>
<meta charset="utf-8">
<p></p>
<style>
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<!--We immediately define the variables of our svg/chart-->
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
// Now we give our svg some attributes. We use conventional margins as set out by Mike Bostock himself.
// Sets width and height minus the margins.
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 50},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Here we set out the time format: date-month-year.
//var parseTime = d3.timeParse("%d-%b-%y");
var formatTime = d3.timeFormat("%Y");
formatTime(new Date); // "2015"
// Now we set our axis. X is according to the time, and y is linear.
// We use rangeRound to round all the values to the nearest whole number.
// We don't use rangeBands or rangePoints as we're not creating a bar chart or scatter plot.
var x = d3.scaleTime()
.rangeRound([0, width]);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
// Now we tell what we want our line to do/represent.
// x is the date, and y is the close price.
var line = d3.line()
.x(function(d) {
return x(d.date);
})
.y(function(d) {
return y(d.close);
});
// This is where we load our tsv file.
d3.tsv("/LineCharts/Line Chart 2 - MO Capital Punishment/data/data.tsv", function(d) {
d.date = formatTime(d.date);
d.close = +d.close;
return d;
}, function(error, data) {
if (error) throw error;
// The .extent function returns the minimum and maximum value in the given array.
// Then, function(d) { return d.date; } returns all the 'date' values in 'data'.
// The .domain function which returns those maximum and minimum values to D3 as the range for the x axis.
x.domain(d3.extent(data, function(d) {
return d.date;
}));
//Same as above for the x domain.
y.domain(d3.extent(data, function(d) {
return d.close;
}));
// Note that we use attr() to apply transform as an attribute of g.
// SVG transforms are quite powerful, and can accept several different kinds of transform definitions, including scales and rotations.
// But we are keeping it simple here with only a translation transform, which simply pushes the whole g group over and down by some amount, each time a new value is loaded onto the page.
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// Doing the same as above but for the y axis.
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y))
//This is where we append(add) text labels to our y axis.
.append("text")
.attr("fill", "#000")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "0.71em")
.style("text-anchor", "end")
.text("Total");
g.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
});
</script>

Unable to get time value with date in d3.js line chart

I'm new to D3.js. I have two problem while creating line chart in D3.js.
One is, I have tried to create line chart in D3.js using the following input values. In my output graph X-axis, I didn't get the time along with date which is present in the input file. I didn't understand how do date parsing into some format happening while creating graph. I don't know how to parse the date into some format to get date with time in my graph x-axis.
file name : lne1-data.csv
date,value
1-May-12 7:30,58.13
30-Apr-12 8:30,53.98
27-Apr-12 9:10,67.00
26-Apr-12 10:20,89.70
25-Apr-12 11:00,99.00
24-Apr-12 12:30,130.28
23-Apr-12 13:20,166.70
20-Apr-12 14:40,234.98
19-Apr-12 15:10,345.44
My Code:
<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: grey;
stroke-width: 1;
shape-rendering: crispEdges;
}
</style>
<body>
<!-- load the d3.js library -->
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>
// Set the dimensions of the canvas / graph
//var margin = {top: 30, right: 20, bottom: 30, left: 50},
var margin = {top: 30, right: 40, bottom: 70, left: 50},
width = 1600 - margin.left - margin.right,
height = 270 - margin.top - margin.bottom;
// Parse the date / time
var parseDate = d3.time.format("%d-%b-%y %H:%M").parse;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
//var xAxis = d3.svg.axis().scale(x)
// .orient("bottom").ticks(5);
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(6)
.tickFormat(d3.time.format("%Y-%m-%d %H:%M"));
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(7);
// Define the line
var valueline = d3.svg.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.close); });
// Adds the svg canvas
var 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 + ")");
// Get the data
d3.csv("lne1-data.csv", function(error, data) {
data.forEach(function(d) {
d.date = parseDate(d.date);
d.close = +d.close;
});
// Scale the range of the data
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([0, d3.max(data, function(d) { return d.close; })]);
// Add the valueline path.
svg.append("path")
.attr("class", "line")
.attr("d", valueline(data));
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
</script>
</body>
My output graph:
Instead of the above graph, I need a graph which should have date with time in X-axis. what do i need to do to get time?
Another one is, I need to draw a vertical line to make two seperate parts like pre cutover, post cutover in that graph for particular date.
Eg. I need a vertical line on the date "2012-Apr-25 11:00"
How do I solve this problems? Can anyone help me to solve these problem please?

Loading JSON in Place of CSV D3

I'm currently working on a spin-off of d3noob's page here: http://www.d3noob.org/2014/07/d3js-multi-line-graph-with-automatic.html
It's almost an identical copy except for two elements. One, I'm trying to load a JSON file instead of D3Noob's preferred CSV. I also want to know if it is easier to use a flat or nested JSON file. If nested would be better, can someone explain or direct me to somewhere that explains nested JSON in d3 a little bit better than what I have been looking for? That'd be great.
Just to sum up. 1. How to load JSON in place of a CSV 2. Nested or flat?
Nested Data
Flat Data
Thank you in advance!
Code:
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: none;
stroke-width: 1;
shape-rendering: crispEdges;
}
.axis text {
fill:red;
}
.legend {
font-size: 16px;
font-weight: bold;
text-anchor: middle;
}
</style>
<script src="d3.js"></script>
<script>
function init(){
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 70, left: 50},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valline = d3.svg.line()
.x(function(d) { return x(d.week); })
.y(function(d) { return y(d.val); });
// Adds the svg canvas
var 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 + ")");
// Get the data
d3.json("data.01.json", function(error, data) {
data.chartdata.forEach(function(d) {
d.week = d.week;
d.val = +d.val;
});
// Scale the range of the data
x.domain(d3.extent(data.chartdata, function(d) { return d.week; }));
y.domain([0, d3.max(data.chartdata, function(d) { return d.val; })]);
// Nest the entries by name
var dataNest = d3.nest()
.key(function(d) {return d.name;})
.entries(data.chartdata);
var color = d3.scale.category10(); // set the colour scale
legendSpace = width/dataNest.length; // spacing for the legend
// Loop through each name / key
dataNest.forEach(function(d,i) {
svg.append("path")
.attr("class", "line")
.style("stroke", function() { // Add the colours dynamically
return d.color = color(d.key); })
.attr("id", 'tag'+d.key.replace(/\s+/g, '')) // assign ID
.attr("d", valline(d.values));
// Add the Legend
svg.append("text")
.attr("x", (legendSpace/2)+i*legendSpace) // space legend
.attr("y", height + (margin.bottom/2)+ 5)
.attr("class", "legend") // style the legend
.style("fill", function() { // Add the colours dynamically
return d.color = color(d.key); })
.on("click", function(){
// Determine if current line is visible
var active = d.active ? false : true,
newOpacity = active ? 0 : 1;
// Hide or show the elements based on the ID
d3.select("#tag"+d.key.replace(/\s+/g, ''))
.transition().duration(100)
.style("opacity", newOpacity);
// Upweek whether or not the elements are active
d.active = active;
})
.text(d.key);
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
}
</script>
</head>
<body onload="init()">
<!-- load the d3.js library -->
</body>
</html>
The answer is rather simple and I should have realized it earlier. Though I was doing everything correctly, it wasn't working. My problem was that my code was in the head and I was trying to append an SVG to the body without the body existing yet. The only thing I had to do was make all of the head script into a function and call the function when the body loaded, as such.
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
<style> /* set the CSS */
body { font: 12px Arial;}
path {
stroke: steelblue;
stroke-width: 2;
fill: none;
}
.axis path,
.axis line {
fill: none;
stroke: none;
stroke-width: 1;
shape-rendering: crispEdges;
}
.axis text {
fill:red;
}
.legend {
font-size: 16px;
font-weight: bold;
text-anchor: middle;
}
</style>
<script src="d3.js"></script>
<script>
function init(){
// Set the dimensions of the canvas / graph
var margin = {top: 30, right: 20, bottom: 70, left: 50},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// Set the ranges
var x = d3.time.scale().range([0, width]);
var y = d3.scale.linear().range([height, 0]);
// Define the axes
var xAxis = d3.svg.axis().scale(x)
.orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y)
.orient("left").ticks(5);
// Define the line
var valline = d3.svg.line()
.x(function(d) { return x(d.week); })
.y(function(d) { return y(d.val); });
// Adds the svg canvas
var 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 + ")");
// Get the data
d3.json("data.01.json", function(error, data) {
data.chartdata.forEach(function(d) {
d.week = d.week;
d.val = +d.val;
});
// Scale the range of the data
x.domain(d3.extent(data.chartdata, function(d) { return d.week; }));
y.domain([0, d3.max(data.chartdata, function(d) { return d.val; })]);
// Nest the entries by name
var dataNest = d3.nest()
.key(function(d) {return d.name;})
.entries(data.chartdata);
var color = d3.scale.category10(); // set the colour scale
legendSpace = width/dataNest.length; // spacing for the legend
// Loop through each name / key
dataNest.forEach(function(d,i) {
svg.append("path")
.attr("class", "line")
.style("stroke", function() { // Add the colours dynamically
return d.color = color(d.key); })
.attr("id", 'tag'+d.key.replace(/\s+/g, '')) // assign ID
.attr("d", valline(d.values));
// Add the Legend
svg.append("text")
.attr("x", (legendSpace/2)+i*legendSpace) // space legend
.attr("y", height + (margin.bottom/2)+ 5)
.attr("class", "legend") // style the legend
.style("fill", function() { // Add the colours dynamically
return d.color = color(d.key); })
.on("click", function(){
// Determine if current line is visible
var active = d.active ? false : true,
newOpacity = active ? 0 : 1;
// Hide or show the elements based on the ID
d3.select("#tag"+d.key.replace(/\s+/g, ''))
.transition().duration(100)
.style("opacity", newOpacity);
// Upweek whether or not the elements are active
d.active = active;
})
.text(d.key);
});
// Add the X Axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
// Add the Y Axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
});
}
</script>
</head>
<body onload="init()">
<!-- load the d3.js library -->
</body>
</html>

Categories