I'm using css-grid to create a 4 row (1 column) grid layout. I have items inside the first 3 rows and this works fine. Those items are a leaflet map, a table, and a D3 plot. My fourth item (a D3 edge bundle chart) will not display inside the 4th row, it seems to display underneath it (outside of the overall grid container).
Here is a scaled down version of my code:
css..
.grid-container {
display: grid;
grid-template-columns: 1fr;
background-color: #ffffff;
padding: 10px;
grid-template-rows: auto auto auto auto;
grid-row-gap: 10px;
}
.grid-item1 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(160, 160, 160, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.grid-item2 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(160, 160, 160, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.grid-item3 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(160, 160, 160, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.grid-item4 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(210, 3, 3, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
HTML/JS..
<body>
<div ></div>
<div id="map"></div>
<div >
<script>
DATATABLE CODE HERE
</script>
</div>
<div id="my_plot">
<script>
D3 PLOT CODE HERE
</script>
</div>
<div id="edgeB">
test
<script>
var diameter = 760,
radius = diameter / 2;
innerRadius = radius - 160;
var cluster = d3.cluster()
.size([360, innerRadius]);
var line = d3.radialLine()
.curve(d3.curveBundle.beta(0.85))
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(" radius "," radius ")");
var link = svg.append("g").selectAll(".link"),
node = svg.append("g").selectAll(".node");
d3.json("flare.json", function(error, classes) {
if (error) throw error;
var root = packageHierarchy(classes)
.sum(function(d) { return d.size; });
cluster(root);
link = link
.data(packageImports(root.leaves()))
.enter().append("path")
.each(function(d) { d.source = d[0], d.target = d[d.length - 1]; })
.attr("class", "link")
.attr("d", line);
node = node
.data(root.leaves())
.enter().append("text")
.attr("class", "node")
.attr("dy", "0.31em")
.attr("transform", function(d) { return "rotate(" (d.x - 90) ")translate(" (d.y 8) ",0)" (d.x < 180 ? "" : "rotate(180)"); })
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.text(function(d) { return d.data.key; })
.on("mouseover", mouseovered)
.on("mouseout", mouseouted);
});
function mouseovered(d) {
node
.each(function(n) { n.target = n.source = false; });
link
.classed("link--target", function(l) { if (l.target === d) return l.source.source = true; })
.classed("link--source", function(l) { if (l.source === d) return l.target.target = true; })
.filter(function(l) { return l.target === d || l.source === d; })
.raise();
node
.classed("node--target", function(n) { return n.target; })
.classed("node--source", function(n) { return n.source; });
}
function mouseouted(d) {
link
.classed("link--target", false)
.classed("link--source", false);
node
.classed("node--target", false)
.classed("node--source", false);
}
// Lazily construct the package hierarchy from class names.
function packageHierarchy(classes) {
var map = {};
function find(name, data) {
var node = map[name], i;
if (!node) {
node = map[name] = data || {name: name, children: []};
if (name.length) {
node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
node.parent.children.push(node);
node.key = name.substring(i 1);
}
}
return node;
}
classes.forEach(function(d) {
find(d.name, d);
});
return d3.hierarchy(map[""]);
}
// Return a list of imports for the given array of nodes.
function packageImports(nodes) {
var map = {},
imports = [];
// Compute a map from name to node.
nodes.forEach(function(d) {
map[d.data.name] = d;
});
// For each import, construct a link from the source to target node.
nodes.forEach(function(d) {
if (d.data.imports) d.data.imports.forEach(function(i) {
imports.push(map[d.data.name].path(map[i]));
});
});
return imports;
}
</script>
</div>
</body>
</html>
The part I can't understand is that the "test" text I have in grid-item4 does correctly appear in the grid-item4 area, it's specifically my D3.js chart that will not display there, it displays underneath. The only thing I can think of try is to play around with various div opening and closing tags but that did not make any difference.
Thanks
CodePudding user response:
Though I was not able to run your code I found the issue. d3.js requires you to append the svg element to another dom element. You selected the body element to append the svg element to.
var svg = d3.select("body").append("svg")
If you want the chart to be appended to the correct grid cell use the id selector for that specific cell instead of body.
var svg = d3.select("#edgeB").append("svg")
CodePudding user response:
please replace the
d3.select("body")
with
d3.select("#edgeB")
so the chart will appear with in the container. I attached a demo below. I hope it will solve your problem.
.grid-container {
display: grid;
grid-template-columns: 1fr;
background-color: #ffffff;
padding: 10px;
grid-template-rows: auto auto auto auto;
grid-row-gap: 10px;
}
.grid-item1 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(160, 160, 160, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.grid-item2 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(160, 160, 160, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.grid-item3 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(160, 160, 160, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.grid-item4 {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(210, 3, 3, 0.8);
padding: 15px;
font-size: 13px;
text-align: left;
grid-row-gap: 10px;
}
.node {
font: 300 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
fill: #bbb;
}
.node:hover {
fill: #000;
}
.link {
stroke: steelblue;
stroke-opacity: 0.4;
fill: none;
pointer-events: none;
}
.node:hover,
.node--source,
.node--target {
font-weight: 700;
}
.node--source {
fill: #2ca02c;
}
.node--target {
fill: #d62728;
}
.link--source,
.link--target {
stroke-opacity: 1;
stroke-width: 2px;
}
.link--source {
stroke: #d62728;
}
.link--target {
stroke: #2ca02c;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div ></div>
<div id="map"></div>
<div >
<script>
// DATATABLE CODE HERE
</script>
</div>
<div id="my_plot">
<script>
// D3 PLOT CODE HERE
var data = [10, 5, 10, 12, 15];
var width = 600,
height = 250,
scaleFactor = 20,
barWidth = 40;
barGap = 2.5;
var svg = d3.select("#my_plot")
.append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.append("g")
.attr("transform", "translate(" 20 "," 20 ")");
g.append("path")
.datum(data)
.attr("class", "line")
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("d", d3.line()
.x(function(d, i) { return i * barWidth * barGap; })
.y(function(d) { return d3.max(data) * scaleFactor - d * scaleFactor; })
);
</script>
</div>
<div id="edgeB">
test
<script>
var diameter = 760,
radius = diameter / 2;
innerRadius = radius - 160;
var cluster = d3.cluster()
.size([360, innerRadius]);
var line = d3.radialLine()
.curve(d3.curveBundle.beta(0.85))
.radius(function(d) { return d.y; })
.angle(function(d) { return d.x / 180 * Math.PI; });
var svg = d3.select("#edgeB").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.append("g")
.attr("transform", "translate(" radius "," radius ")");
var link = svg.append("g").selectAll(".link"),
node = svg.append("g").selectAll(".node");
d3.json("https://atikur-rabbi.github.io/d3-edge/flare.json", function(error, classes) {
if (error) throw error;
var root = packageHierarchy(classes)
.sum(function(d) { return d.size; });
cluster(root);
link = link
.data(packageImports(root.leaves()))
.enter().append("path")
.each(function(d) { d.source = d[0], d.target = d[d.length - 1]; })
.attr("class", "link")
.attr("d", line);
node = node
.data(root.leaves())
.enter().append("text")
.attr("class", "node")
.attr("dy", "0.31em")
.attr("transform", function(d) { return "rotate(" (d.x - 90) ")translate(" (d.y 8) ",0)" (d.x < 180 ? "" : "rotate(180)"); })
.attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
.text(function(d) { return d.data.key; })
.on("mouseover", mouseovered)
.on("mouseout", mouseouted);
});
function mouseovered(d) {
node
.each(function(n) { n.target = n.source = false; });
link
.classed("link--target", function(l) { if (l.target === d) return l.source.source = true; })
.classed("link--source", function(l) { if (l.source === d) return l.target.target = true; })
.filter(function(l) { return l.target === d || l.source === d; })
.raise();
node
.classed("node--target", function(n) { return n.target; })
.classed("node--source", function(n) { return n.source; });
}
function mouseouted(d) {
link
.classed("link--target", false)
.classed("link--source", false);
node
.classed("node--target", false)
.classed("node--source", false);
}
// Lazily construct the package hierarchy from class names.
function packageHierarchy(classes) {
var map = {};
function find(name, data) {
var node = map[name], i;
if (!node) {
node = map[name] = data || {name: name, children: []};
if (name.length) {
node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
node.parent.children.push(node);
node.key = name.substring(i 1);
}
}
return node;
}
classes.forEach(function(d) {
find(d.name, d);
});
return d3.hierarchy(map[""]);
}
// Return a list of imports for the given array of nodes.
function packageImports(nodes) {
var map = {},
imports = [];
// Compute a map from name to node.
nodes.forEach(function(d) {
map[d.data.name] = d;
});
// For each import, construct a link from the source to target node.
nodes.forEach(function(d) {
if (d.data.imports) d.data.imports.forEach(function(i) {
imports.push(map[d.data.name].path(map[i]));
});
});
return imports;
}
</script>
</div>
</body>
</html>