【问题标题】:D3 tick with background带背景的 D3 刻度线
【发布时间】:2017-07-08 16:57:21
【问题描述】:

D3 轴tick 怎么会有背景色?

这样做的一种粗暴方法是在每个 g.tick 中附加一个 rect 元素并在其上添加一个 fill,但这很难实现,因为 rect 的大小必须与tick..里面的文字。

这是 Mike Bostock 的 basic ticks example(以及带有图表的 another


我截取了一张屏幕截图并标记了(红色边框)我希望刻度具有背景颜色的位置:


有谁知道在 Ticks 上设置背景颜色的合理方法? 谢谢

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    另一种选择是制作这样的过滤器:

      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

    【讨论】:

    • 这可以为背景生成自定义填充吗?我正在考虑过滤器,但它无法弄清楚如何让填充工作。例如背景是3px padding
    • 虽然这可行,但我将颜色作为SCSS 变量,我更愿意从 CSS 文件中控制颜色,而不是在 html/JS 中硬编码
    【解决方案2】:

    我不会这么快就否定您的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>

    【讨论】:

    • 谢谢! getBBox() 是我所需要的
    【解决方案3】:

    带填充的 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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-03
      • 2019-03-03
      • 2013-04-07
      • 2019-05-30
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 2013-02-16
      相关资源
      最近更新 更多