Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 tick with background

Tags:

d3.js

How can a D3 axis tick have a background color?

A brute way of doing so it to append a rect element inside each g.tick and have a fill on it, but it's quite difficult to achieve, since the rect has to be the same size as the text inside the tick..

Here's a basic ticks example by Mike Bostock (and another with graph)


I took a screenshot and marked (red border) where I want the ticks to have background color:

enter image description here


Does anyone know of any sane way of having background color on Ticks? Thanks

like image 432
vsync Avatar asked Nov 29 '25 11:11

vsync


2 Answers

Another option would be to make a filter like this:

  var filter = svg.append("defs").append("filter")
    .attr("x", "0")
    .attr("y", "0")
    .attr("width", "1")
    .attr("height", "1")
    .attr("id", "background")//id of the filter
  filter.append("feFlood")
    .attr("flood-color", "red");
  filter.append("feComposite")
    .attr("in", "SourceGraphic");

and to ticks add the filter like this:

 g.selectAll(".tick text").attr("filter","url(#background)");

working code here

like image 188
Cyril Cherian Avatar answered Dec 02 '25 04:12

Cyril Cherian


I wouldn't dismiss your rect idea so quickly. It's pretty simple to implement and allows you to adjust the size of the "background" however you want. Here's how it would look with your 3 extra pixel:

d3.selectAll(".tick").each(function(d,i){
  var tick = d3.select(this),
      text = tick.select('text'),
      bBox = text.node().getBBox();

  tick.insert('rect', ':first-child')
    .attr('x', bBox.x - 3)
    .attr('y', bBox.y - 3)
    .attr('height', bBox.height + 6)
    .attr('width', bBox.width + 6)
    .style('fill', d3.schemeCategory20[i % 20]);      
});

Full example:

<!DOCTYPE html>
<meta charset="utf-8">
<svg width="960" height="500"></svg>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>

var svg = d3.select("svg"),
    margin = {top: 20, right: 0, bottom: 20, left: 0},
    width = svg.attr("width") - margin.left - margin.right,
    height = svg.attr("height") - margin.top - margin.bottom,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scalePoint()
    .domain([0, 1, 2])
    .range([0, width])
    .padding(1);

var y = d3.scaleLinear()
    .domain([-1e6, 2e6])
    .range([height, 0]);

g.append("g")
    .attr("transform", "translate(" + x(0) + ",0)")
    .attr("class", "axis")
    .call(d3.axisLeft(y)
        .ticks(20, "s"));

g.append("g")
    .attr("transform", "translate(" + x(1) + ",0)")
    .attr("class", "axis")
    .call(d3.axisLeft(y)
        .ticks(20)
        .tickFormat(d3.format(".0s")));

g.append("g")
    .attr("transform", "translate(" + x(2) + ",0)")
    .attr("class", "axis")
    .call(d3.axisLeft(y)
        .ticks(20)
        .tickFormat(d3.formatPrefix(".1", 1e6)));
        
d3.selectAll(".tick").each(function(d,i){
  var tick = d3.select(this),
      text = tick.select('text'),
      bBox = text.node().getBBox();
      
  tick.insert('rect', ':first-child')
    .attr('x', bBox.x - 3)
    .attr('y', bBox.y - 3)
    .attr('height', bBox.height + 6)
    .attr('width', bBox.width + 6)
    .style('fill', d3.schemeCategory20[i % 20]);
  
});

</script>
like image 35
Mark Avatar answered Dec 02 '25 03:12

Mark



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!