Home > OS >  D3 extra tag over axis with custom shape
D3 extra tag over axis with custom shape

Time:11-08

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?

enter image description here

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>

  • Related