使用D3在弧上的点

时间:2014-07-15 18:11:55

标签: svg d3.js

按照以下代码,我在SVG上绘制了一些同心圆弧: -

var width = 2000;
var height = 500;



var canvas = d3.select("body").append("svg")
        .attr("width",width)
        .attr("height",height);

var group = canvas.append("g")
        .attr("transform","translate(100,200)");


var arc = d3.svg.arc()
        .innerRadius(function(d){return (d-1)})
        .outerRadius(function(d){return d})
        .startAngle(1)
        .endAngle(p/2);

var arcs = group.selectAll(".arc")
        .data(orbitRadius)
        .enter()
        .append("g")
        .attr("class","arc");

    arcs.append("path")
        .attr("d",arc);

这里的orbitRadius数组保存每个弧的半径。

现在我想找出" n"每个弧上的点(x和y坐标)在每个弧上处于相同的高度。弧上的四个点可以是等距的。也就是说,假设p1,p2,p3,p4是4点或弧1,q1,q2,q3,q4是弧2上的4个点,则p1和q1处于相同的高度(与SVG相对),p2和q2是等等等等。

请帮忙。

编辑: - 请找到我想要实现的图像: - 在https://www.dropbox.com/s/w87118tphnmya7a/image.PNG

1 个答案:

答案 0 :(得分:1)

您需要使用一些触发来确定放置点的位置,但逻辑不应该那么困难。

你知道每个弧的半径,并且你可能知道每组匹配点的高度(y值)。

看看这个单位圆图:

unit circle

在我们的例子中,我们有一个已知半径 R 而不是单位圆,它是当前弧的半径,但数学运算方式相同。

您需要为每个弧找到的缺失值是 x 。为了找到这个,我们首先需要找到角度是什么。这里是三角形的来源,老旧的SOH-CAH-TOA。

如图所示,我们知道:

sin(theta)= y / R

所以为了找到角度本身,我们可以采用反正弦或反正弦:

theta = asin(y / R)

我们也知道:

cos(theta)= x / R

所以把它们放在一起,我们得到:

cos(asin(y / R))= x / R

解决x:

x = cos(asin(y / R))* R

然后我们可以使用它创建一个函数,给定y值和半径,返回x值:

function getPointX(y, radius) {
  return Math.cos(Math.asin(y/radius)) * radius;
}

现在我们已经完成了所有这一切,直到d3部分。

要绘制您的点数,您需要根据弧线的原点制作一组您希望用于高度的值。请记住,在SVG坐标中,较高的 y 值表示图表上的较低。因此,原点以下的距离为正,其上方的距离为负。举个例子:

var heights = [-70, -15, 20, 60];

接下来我要创建一个组合数据集。

var combinedData = orbitRadius.map(function(d) {
  return {
    r: d,
    heights: heights
  };
});

这会创建一个对象数组,其中每个对象都有一个属性r,它是orbitRadius的半径之一,每个对象也包含heights数组。

让每个对象包含相同的高度数组会有一些不必要的冗余,但它会使绘图部分更容易这样做。

为了绘制点,我首先会创建一个组以包含每个单独弧上的点:

var pointGroup = group.selectAll('.point-group')
  .data(combinedData)
  .enter().append('g')
  .attr('class', 'point-group');

这是棘手的部分。然后,我将使用嵌套选择在每个单独的高度创建一个点。对于.data(),我们将使用pointGroup选择中的数据函数,该函数仅返回高度数组。这意味着输入选择将包含每个单独高度的一个元素。

pointGroup.selectAll('.point')
  .data(function(d) {return d.heights;})
  .enter().append('circle')
  .attr('class', 'point')
  .attr('cx', function(d) {
    return getPointX(d, this.parentNode.__data__.r);
  })
  .attr('cy', function(d) {return d;})
  .attr('r', 4);

cy属性只是d,因为高度数据代表y值。对于cx我调用我们之前创建的getPointX()函数,传递y值和父节点的半径值,因为父节点是共享半径的所有点的组。

以下是JSBin的工作示例。