2017-02-19 86 views
2

D3軸tick如何具有背景顏色?帶背景的D3刻度

它這樣做追加每g.tickrect元素,並在其上具有fill的野蠻方式,但它是非常難以實現的,因爲rect必須是尺寸爲tick內的文本一樣..

這裏有一個basic ticks example由邁克·博斯托克(和another帶圖),我想蜱有背景色


我參加了一個屏幕截圖,並標註(紅色邊框):

enter image description here


有誰知道具有對蜱背景色,任何理智的方法是什麼? 感謝

回答

3

我不會」請儘快解僱您的想法。實現起來非常簡單,並允許您根據需要調整「背景」的大小。下面是它會怎樣看你的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>