2017-02-19 7 views
2

Как ось D3 tick имеет цвет фона?D3 тик с фоном

скотины способа сделать так это для добавления rect элемента внутри каждый g.tick и имеет fill на нем, но это довольно трудно достичь, поскольку rect должен быть тем же размером, что и текст внутри tick ..

Вот basic ticks example Майк Босток (и another с графом)


Я взял скриншот и промаркирован (красная граница), где я хочу тиков иметь цвет фона:

enter image description here


Кто-нибудь знает любой здравомыслящий способ иметь цвет фона на тиков? Благодаря

ответ

3

I Wouldn» t увольняйте идею rect так быстро. Это довольно просто реализовать и позволяет вам настроить размер «фона», как вы хотите. Вот как это будет выглядеть с 3 дополнительных пикселя:

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]);  
}); 

Полный пример:

<!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>

+0

Спасибо! 'getBBox()' был тем, что мне было нужно – vsync

5

Другим вариантом было бы сделать фильтр так:

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"); 

и клещами добавить фильтр, как это:

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

рабочий код here

+0

Можно ли изготовить пользовательские дополнения на задний план? Я рассматривал фильтр, но он не мог понять, как получить отступы. например, иметь фон с надписью «3px» – vsync

2

SVG текста цвет фона с прокладкой

<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>