I have been working on a stacked barchart for quite some time and i think i have a messy code where i had used <svg>
at 2 places for this one chart.
Please refer to this codepen https://codepen.io/a166617/pen/dyzEvMG I tried putting it under one svg tag so that the code looks lot sorted and better but i am unsuccessful. Any number of iterations to put the code in one svg tag has resulted in either messing up with the code even more and sometimes the barchart doesnot show up at all with my changes.
Can someone please let me know how to fix this mess i created. Would really appreciate any inputs on this.
The most important mess is the below code where i had put svg for each individual barchart.
{entries.map((entry, indx) => (
<div class="mGraph content-style" key={Math.random()}>
<svg
viewBox={`0, 0, 80, 450`}
height={500}
width={90}
style={{ transform: `rotateX(180deg)` }}
>
{rows(entry)}
</svg>
<div class="x-title">{entry.name}</div>
{ indx === 1 && <text class="label-title">PROJECTS</text>}
</div>
))}
I tried reorganizing the code and here is the codepen for it https://codepen.io/a166617/pen/NWvZGLd
CodePudding user response:
I tried to do it using plain JS. Was able to create a single SVG for the graph:
const svgNS = "http://www.w3.org/2000/svg";
const addLine = (parent_g, x1, x2, y1, y2) => {
var line = document.createElementNS(svgNS, "line");
line.setAttribute("x1", x1);
line.setAttribute("y1", y1);
line.setAttribute("x2", x2);
line.setAttribute("y2", y2);
parent_g.appendChild(line);
};
const addText = (parent_g, x, y, text_val, class_ = "", dy = "", textanchor="", transform="") => {
var text = document.createElementNS(svgNS, "text");
text.setAttribute("x", x);
text.setAttribute("y", y);
if (class_ !== "")
text.classList.add(class_);
if (dy !== "")
text.setAttribute("dy", dy);
if (textanchor !== "")
text.setAttribute("textAnchor", textanchor);
if (transform !== "")
text.setAttribute("transform", transform);
text.innerHTML = text_val;
parent_g.appendChild(text);
};
const addRect = (parent_g, width, height, x, y, fill) => {
var rect = document.createElementNS(svgNS, "rect");
rect.setAttribute("width", width);
rect.setAttribute("height", height);
rect.setAttribute("x", x);
rect.setAttribute("y", y);
rect.setAttribute("fill", fill);
parent_g.appendChild(rect);
};
const addBarsToGraph = (entries) => {
const barWidth = 50;
const maxBarHeight = 490;
var svgGraph = document.getElementById("svg-graph");
var xpos = 100;
for (var i = 0; i < entries.length; i )
{
//console.log(entries[i].bars);
for (var j = 0; j < entries[i].bars.length; j )
{
const height = (entries[i].bars[j].value * maxBarHeight) / entries[i].total;
const y = maxBarHeight - height - ((entries[i].bars[j].y * maxBarHeight) / entries[i].total);
//console.log(height, y);
addRect(svgGraph, 50, height, xpos, y, entries[i].bars[j].color);
addText(svgGraph, xpos 15, y height / 2 - 10, entries[i].bars[j].value, "bar-count", "1.3em", "middle");
}
//console.log(xpos, maxBarHeight 50);
//var graphLabel = document.createElementNS(svgNS, "g");
var rotateStr = "rotate(-45," xpos "," (maxBarHeight 50) ")";
addText(svgGraph, xpos, maxBarHeight 50, entries[i].name, "x-title", "", "middle", rotateStr);
//svgGraph.appendChild(graphLabel);
xpos = 60;
}
};
const addGridLinesAndGraphLabel = () => {
var rootDiv = document.getElementById("root");
rootDiv.style.display = "flex";
var svg = document.createElementNS(svgNS, "svg");
svg.setAttribute("id", "svg-graph");
svg.classList.add("graph");
var xgrid = document.createElementNS(svgNS, "g");
xgrid.classList.add("grid");
xgrid.classList.add("x-grid");
xgrid.setAttribute("id", "xGrid");
addLine(xgrid, "90", "90", "5", "490");
svg.appendChild(xgrid);
var ygrid = document.createElementNS(svgNS, "g");
ygrid.classList.add("grid");
ygrid.classList.add("y-grid");
ygrid.setAttribute("id", "yGrid");
addLine(ygrid, "90", "1805", "490", "490");
svg.appendChild(ygrid);
var ylabels = document.createElementNS(svgNS, "g");
ylabels.classList.add("labels");
ylabels.classList.add("y-labels");
addText(ylabels, "80", "15", 100);
addText(ylabels, "80", "131", 75);
addText(ylabels, "80", "248", 50);
addText(ylabels, "80", "373", 25);
addText(ylabels, "80", "500", 0);
addText(ylabels, "60", "200", "Pass %", "label-title");
svg.appendChild(ylabels);
addText(svg, "500", "550", "PROJECTS", "label-title");
rootDiv.appendChild(svg);
};
const ReleaseScopeCharts = () => {
const data = [
{
name: 'Transit',
passed: 20,
skipped: 50,
failed: 30,
untested: 0
},
{
name: 'Access',
passed: 0,
skipped: 0,
failed: 0,
untested: 100
},
];
const colors = ['#30D158', '#005EA7', '#FF453A', '#ffcc00'];
const entries = data.map(d => ({
name: d.name,
total: ['passed', 'skipped', 'failed', 'untested'].reduce(
(acc, key) => acc d[key],
0
),
bars: ['passed', 'skipped', 'failed', 'untested']
.map((key, i) => ({
value: d[key],
color: colors[i],
y:
key === 'passed'
? 0
: key === 'skipped'
? d.passed
: d.skipped d.passed,
}))
.filter(bar => bar.value),
}));
addGridLinesAndGraphLabel();
addBarsToGraph(entries);
};
window.onload = () => { ReleaseScopeCharts(); }
body {
font-family: 'Open Sans', sans-serif;
margin-top: 1rem;
}
.mGraph > svg {
position: relative;
left: -60rem;
top: -.65rem;
}
.mGraph > div {
position: relative;
left: -58rem;
top: -.65rem;
}
.mGraph > text {
position: relative;
left: -50rem;
}
.graph .labels.x-labels {
text-anchor: middle;
}
.graph .labels.y-labels {
text-anchor: end;
}
.graph {
height: 600px;
width: 1200px;
}
.graph .grid {
stroke: #ccc;
stroke-dasharray: 0;
stroke-width: 1;
}
.labels {
font-size: 13px;
}
.label-title {
font-weight: bold;
text-transform: uppercase;
font-size: 12px;
fill: black;
margin-left: 50%
}
.data {
fill: red;
stroke-width: 1;
}
.bar-count {
fill: white;
font-size: 12px;
transform-box: fill-box;
transform: rotateX(0deg)
}
.x-title {
color: red;
margin-top: 20%;
/*transform: rotate(-45deg)*/
};
.content-style {
display: flex;
flex-flow: column;
align-items: center;
}
<!DOCTYPE html>
<div id="root"></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>