I'd like to replicate these tags with a triangle at the end in D3 to show the last data points.
The way I can think of is to append a triangle at the end of a rect element, but is quite messy since I have to align the triangle with the rectangle position. I was wonder if there was there a better way of doing it?
CodePudding user response:
You can use a path
with a fill to get the solid shape you are looking for:
.join("path")
.attr("d", (d, i) => `M ${1} ${yScale(d)} l 6,-6 h 24 v 12 h -24 l -6,-6`)
.attr("fill", (d, i) => d3.schemeTableau10[i])
This is simpler than drawing a rect
and then bolting on the little triangle. See below:
const width = 200;
const height = 180;
const svg = d3.select("body").append("svg").attr("width", width).attr("height", height);
const yScale = d3.scaleLinear().domain([0, 1]).range([160, 10]);
const yAxis = d3.axisLeft(yScale);
const yAxisG = svg.append("g").attr("transform", `translate(60, 10)`).call(yAxis);
const markerY = [0.25, 0.45, 0.65];
const markers = yAxisG.selectAll(".marker")
.data(markerY)
.join("path")
.attr("d", (d, i) => `M ${1} ${yScale(d)} l 6,-6 h 24 v 12 h -24 l -6,-6`)
.attr("fill", (d, i) => d3.schemeTableau10[i])
const labels = yAxisG.selectAll(".label")
.data(markerY)
.join("text")
.text(d => d)
.attr("x", 0)
.attr("y", d => yScale(d))
.attr("dx", 8)
.attr("dy", 4)
.attr("text-anchor", "start")
.attr("fill", "#000");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>