D3 tick with background

How does the D3 tick axis have a background color?

The hard way to do this is to add a rect element inside each g.tick and have fill on it, but it's pretty hard to achieve, since the rect must be the same size as the text inside tick ..

Here's an example of Mike Bostock's main ticks (and another with a chart)




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

enter image description here




Does anyone know of any reasonable way to have the background color on Ticks? Thanks

+2
Feb 19 '17 at 12:27
source share
3 answers

I would not reject your rect idea so quickly. It is quite simple to implement and allows you to adjust the size of the "background" as you want. Here's what it would look like with your 3 extra pixels:

 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> 
+3
Feb 19 '17 at 15:47
source share

Another option is to create 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 mark add filter as follows:

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

working code here

+5
Feb 19 '17 at 13:17
source share

Indented SVG Background Color

 <svg width="200" height="200"> <defs> <filter x="-0.5" y="-0.5" width="2" height="2" id="solid"> <feFlood flood-color="#BDBDBD"></feFlood> <feComposite in="SourceGraphic"></feComposite></filter> </defs> <text x="50" y="50" font-size="13" fill="#fff" filter="url(#solid)">7%</text> </svg> 
+2
Jun 12 '17 at 6:22
source share



All Articles