【问题标题】:Add border-radius property to D3js Donut Chart向 D3js 圆环图添加边框半径属性
【发布时间】:2018-10-13 03:59:59
【问题描述】:

我目前在一个 AngularJS 应用程序中使用这个圆环图:

但是设计模型说我们想要这个,注意圆弧绿色部分的border-radius属性:

如何为 d3js 输出的 SVG 添加边框半径,我目前使用的代码如下所示:

let data = [
    {
        label: 'Data',
        count: scope.data
    },
    {
        label: 'Fill',
        count: 100 - scope.data
    }
];

let width = 60;
let height = 60;
let radius = Math.min(width, height) / 2;
let color = d3.scale
    .ordinal()
    .range(['#3CC692', '#F3F3F4']);
let selector = '#donut-asset-' + scope.chartId;

d3
    .select(selector)
    .selectAll('*')
    .remove();

let svg = d3
    .selectAll(selector)
    .append('svg')
    .attr('width', width)
    .attr('height', height)
    .append('g')
    .attr(
        'transform',
        'translate(' + width / 2 + ',' + height / 2 + ')'
    );
let arc = d3.svg
    .arc()
    .innerRadius(23)
    .outerRadius(radius);
let pie = d3.layout
    .pie()
    .value(function(d) {
        return d.count;
    })
    .sort(null);
let path = svg
    .selectAll('path')
    .data(pie(data))
    .enter()
    .append('path')
    .attr('d', arc)
    .attr('fill', function(d, i) {
        return color(d.data.label);
    });
let legend = svg
    .selectAll('.legend')
    .data(data)
    .enter()
    .append('g')
    .attr('class', 'legend')
    .attr('transform', function(d, i) {
        return 'translate(' + 0 + ',' + 0 + ')';
    });
legend
    .append('text')
    .attr('x', 1)
    .attr('y', 1)
    .attr('text-anchor', 'middle')
    .attr('dominant-baseline', 'central')
    .text(function(d) {
        return d.count + '%';
    });

};

我知道要使用cornerRadius,但是当我这样做时,它会为两条弧线设置一个半径,它只需要存在于彩色弧线上即可。有任何想法吗?提前感谢您的帮助!

【问题讨论】:

    标签: javascript jquery angularjs d3.js donut-chart


    【解决方案1】:

    尝试使用笔画属性,例如:

    • 中风
    • 笔划破折号
    • 笔划-dashoffset
    • 笔画线帽
    • 笔划线连接
    • 中风斜接限制
    • 中风不透明度
    • 笔画宽度

    并将条形的宽度设置为较低的值,即 0。

    参考:https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute

    但更好的方法是在画布上制作图表,因为您可以绘制任何您想要的东西。或者使用库。

    【讨论】:

    • 我正在使用一个库,它是 d3js。
    • 这是实现目标的错误选择。尝试另一个。或者尝试手动操作,很简单。但先试试我对中风的建议。
    • 我认为你不能在这样的封闭路径上设置笔触
    • 在说先检查之前
    【解决方案2】:

    您可以将圆角半径应用于 d3 圆弧,从而允许圆角:

    let arc = d3.svg
        .arc()
        .innerRadius(23)
        .outerRadius(radius)
        .cornderRadius(10);
    

    但是,缺点是所有圆弧的边框都是圆形的:

    如果您仅将cornerRadius 应用于变暗的弧线 - 其他弧线将不会填充圆角后面的背景。相反,我们可以附加一个圆弧(完整的甜甜圈)并将变暗的圆弧放在顶部并进行四舍五入(我的示例没有调整您的代码,只是展示了它是如何完成的,同样使用 d3v4 使用 d3.arc() 而不是d3.svg.arc()):

    var backgroundArc = d3.arc()
      .innerRadius(30)
      .outerRadius(50)
      .startAngle(0)
      .endAngle(Math.PI*2);
      
    var mainArc = d3.arc()
      .innerRadius(30)
      .outerRadius(50)
      .cornerRadius(10)
      .startAngle(0)
      .endAngle(function(d) { return d/100*Math.PI* 2 });
      
    var data = [10,20,30,40,50] // percents.
      
    var svg = d3.select("body").append("svg")
      .attr("width", 600)
      .attr("height", 200);
      
    var charts = svg.selectAll("g")
      .data(data)
      .enter()
      .append("g")
      .attr("transform",function(d,i) { 
         return "translate("+(i*100+50)+",100)";
      });
      
    charts.append("path")
      .attr("d", backgroundArc)
      .attr("fill","#ccc")
    
    charts.append("path")
      .attr("d", mainArc) 
      .attr("fill","orange")
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

    【讨论】:

    • 好的,所以我必须分开弧线,只给有颜色的那条圆角半径。
    • 这可能是最直接的 - 否则您需要修改灰色弧线的开始和结束角度,以便它可以覆盖圆形部分,此外,饼图中可能存在分层问题布局。