I want to create a plot of plots. That is, I want to a figure with multiple plots of data in the same image.
I can do this with the code below (thanks to an answer to another question) but each plot is its own SVG.
Is there any way to use D3 to plot this as one svg, so it is exportable as a complete image?
<!DOCTYPE html>
<meta charset="utf-8">
<title>Example</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
<style>
path {
stroke: darkblue;
stroke-width: 2px;
fill: none;
}
svg {
border: solid 2px red;
width: 300px
height: 150px;
}
#plotsHere{
display: grid;
grid-auto-flow: column;
grid-gap: 0px;
grid-template-rows: 150px 150px;
grid-template-columns: 300px 300px;
}
</style>
<body>
<div id="plotsHere">
</div>
</body>
<script>
const signalData = [
{
name: "Signal 1",
data: [1,2,3,4,5,6,7],
},
{
name: "Signal 2",
data: [2,3,1,4,5,1,3],
},
{
name: "Signal 3",
data: [1,7,2,6,3,5,4],
},
];
// This is a line generator. Normally, you pass the x- and y-scales in,
// see also d3-scale on github
const line = d3.line()
// The first argument is always the datum object, the second is the index
// Note that I use the index to determine the x coordinate of each point here
.x((d, i) => i * 50)
// And the datum object for the y-coordinate
.y(d => 150 - (15 * d));
// The term `datum` is unrelated to date, but is the singular value of `data`.
// One datum, many data.
d3.select("#plotsHere")
.selectAll("svg")
// Append one svg per array entry, look up the so-called enter, update, exit
// cycle for this. It's the most complex part of d3
.data(signalData)
.enter()
.append("svg")
// Execute a custom function for each element. People who are new to d3.js
// over-use this function, very often you don't need it!
.each(function(d, i) {
// I pass the current svg element, the datum object, and the index for convenience
draw(d3.select(this), d, i);
});
function draw(svg, data, index) {
// Append a label, set the text to the name
svg.append("text")
.attr("x", 20)
.attr("y", 20)
.text(d => d.name);
// Append a path, take the datum of the svg, pick it's `data` property,
// which is the array of numbers, and set that as the datum of the path,
// then call the line generator
svg.append("path")
.datum(d => d.data)
.attr("d", line);
}
</script>