按照以下代码,我在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
答案 0 :(得分:1)
您需要使用一些触发来确定放置点的位置,但逻辑不应该那么困难。
你知道每个弧的半径,并且你可能知道每组匹配点的高度(y值)。
看看这个单位圆图:
在我们的例子中,我们有一个已知半径 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的工作示例。