如何使用d3.js绘制渐变弧形?

15

我开始使用d3.js。 我有以下需求:

需求:

输入图像描述信息

我尝试了什么?

演示例子

问题?

如何实现与上面图片相同的渐变效果。

任何建议或想法都将不胜感激。

注意

我刚开始学习 d3.js


也许如果你在弧线边缘模糊高斯模糊,那就可以了。 - Robert Longson
1
你可能会使用d3.arc,它有指定的起始和结束角度。所以你只需要将每个段分成许多小部分,并对其应用渐变(可以通过数组或使用d3比例尺)。你也可以简单地创建一个由100个弧组成的饼图,并根据百分比分别为每个弧着色。 - JSBob
我相信我已经成功在白色背景的弧上做了一个渐变 http://jsfiddle.net/BTfmH/242/,虽然我不确定它是如何工作的。实际上这是一个径向渐变,但它可以在具有线性渐变坐标(x1,y1...)的圆上正常工作,而不是在具有cx,cy,r的圆上工作...奇怪。 - GL.awog
1个回答

10

编辑 - 更改数据结构和小样链接以表示在开头未填充的块。

我会使用d3中的饼图函数来创建一个饼图。上面的图像基本上是一个饼图,应用了两种不同的渐变样式到饼块中。一个红色线性渐变和一个黑白径向渐变。

我创建了下面链接的小样来展示一个例子。关键在于你需要构造你的数据同时包含不应该应用红色渐变的百分比。使用上面的例子,我们有三个饼块是红色的,其余部分为空。想象数据集如下:

    var data = [{
    percent: 10,
    pie: 0
}, {
    percent: 13,
    pie: 1
}, {
    percent: 13,
    pie: 1
}, {
    percent: 6,
    pie: 1
}, {
    percent: 56,
    pie: 0
}];

我们已经有了百分比值,并使用“pie”属性标记哪些块应该呈现为红色,哪些块应该是未填充的部分。

您可以使用任何数据集,但我只是用这个作为示例。

接下来要做的事情是创建SVG元素:

 var width = 400;
    var height = 400;
    var radius = Math.min(width, height) / 2;

    var arc = d3.svg.arc()
     .outerRadius(radius - 10)
     .innerRadius(((radius - 10) / 5) * 4);


    var pie = d3.layout.pie()
    .sort(null)
    .value(function (d) { return d.percent });

    var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

接下来我们将创建两个渐变来样式化饼图块。首先是线性红色渐变:

// append a defs tag to SVG, This holds all our gradients and can be used
//by any element within the SVG we append it to
var defs = svg.append("svg:defs")

//next we append a linear gradient 
var red_gradient = defs.append("svg:linearGradient")
  .attr("id", "gradient")
  .attr("x1", "0%")
  .attr("y1", "0%")
  .attr("x2", "0%")
  .attr("y2", "100%")
  .attr("spreadMethod", "pad");

//first dark red color
    red_gradient.append("svg:stop")
        .attr("offset", "0%")
        .attr("stop-color", "rgb(221,48,2)")
        .attr("stop-opacity", 1);
//second light red color
    red_gradient.append("svg:stop")
        .attr("offset", "100%")
        .attr("stop-color", "rgb(247, 78, 1)")
        .attr("stop-opacity", 1);

然后我们为未填充的部分追加了径向渐变。这个有点棘手,因为我们需要通过转换移动渐变来获得正确的径向中心。如果你将它平移半个宽度和高度,我认为它应该可以解决。

var radial_gradient = defs.append("radialGradient")
.attr("gradientUnits", "userSpaceOnUse")
.attr("cx", '50%')
.attr("cy", '50%')
.attr("r", "75%")
.attr("fx", '50%')
.attr("fy", '50%')
.attr('gradientTransform', "translate(-200,-200)")
.attr("id", 'gradient2');
 radial_gradient.append("stop").attr("offset", "0%").style("stop-color", "black");
 radial_gradient.append("stop").attr("offset", "55%").style("stop-color", "white");
 radial_gradient.append("stop").attr("offset", "95%").style("stop-color", "black");

一旦我们设置好梯度,就可以添加馅饼:

   var g = svg.selectAll(".arc")
     .data(pie(data))
     .enter().append("g")
     .attr("class", "arc");

    // we create a function to append the different chucks of the pie. 
    // we check the pie attribute from the data and apply the correct gradient.

    g.append("path")
    .attr("d", arc)
    .style("fill", function (d) {
        if (d.data.pie === 1) {
            console.log('true' + d.data.pie);
            return "url(#gradient)"
        }
        else {
            console.log('false' + d.data.pie);
            return "url(#gradient2)"
        }
    })

JSFiddle:http://jsfiddle.net/staceyburnsy/afo292ty/2/


没问题,如果你在圆形或动画方面遇到困难,请告诉我。 - Stacey Burns
实际上它应该是响应式的。无论如何,非常感谢。 - karthick
不认为将硬编码的值更改为基于父元素宽度/高度的动态值是什么大不了的事。渐变和SVG对象可以在窗口加载和调整大小时通过其ID /类进行定位。 - Stacey Burns

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接