I have created the discrete legend using svg and I want to show the index as its label.
// creating svg
selectedLegend
.append("svg")
.attr("viewBox", `0 0 ${count} 1`)
.attr("preserveAspectRatio", "none")
function legend(g: any) {
// appending data
g.selectAll("g.legendCells")
.data(itemColor)
.enter()
.append("rect");
// appending text for label, which is not working as expected
g.selectAll("rect")
.append("text")
.attr("class", "breakLabels")
.style("fill", "red")
.attr("x", cellWidth cellPadding)
.attr("y", 5 cellHeight / 2)
.text(function (d: Record<string, unknown>, i: any) {
// return the index, which should be label for legend
return i;
});
}
CodePudding user response:
Be careful not to place the <text>
elements as children to <rect>
. They are independent. The scaling (preserveAspectRatio="none"
) also apply to the text, so it could be a good idea to have an SVG inside another SVG. The inner SVG has the scaling and the outer SVG has the texts. The outer SVG has a viewBox that matches the height/width ratio (10 to 1 is = to 250 to 25).
On the <text>
I added the attributes dominant-baseline="middle"
and text-anchor="middle"
to position the handle of the text in the middle of it.
<div id="container">
<svg viewBox="0 0 20 2" width="400px">
<svg viewBox="0 0 4 1" preserveAspectRatio="none" width="100%" height="1" >
<rect x="0" y="0" height="1" width="1" style="fill: rgb(255, 46, 0);"/>
<rect x="1" y="0" height="1" width="1" style="fill: rgb(0, 184, 0);"/>
<rect x="2" y="0" height="1" width="1" style="fill: rgb(0, 25, 255);"/>
<rect x="3" y="0" height="1" width="1" style="fill: rgb(179, 179, 179);"/>
</svg>
<g dominant-baseline="middle" text-anchor="middle" font-size=".73">
<text x="2.5" y="1.5" style="fill: black;">0</text>
<text x="7.5" y="1.5" style="fill: black;">1</text>
<text x="12.5" y="1.5" style="fill: black;">2</text>
<text x="17.5" y="1.5" style="fill: black;">3</text>
</g>
</svg>
</div>