Svg 使用D3的圆弧上的点
我在SVG上绘制了几个同心圆弧,代码如下:-Svg 使用D3的圆弧上的点,svg,d3.js,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 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的w.r.t),p2和q2在同一高度,依此类推
请帮忙
编辑:-请找到我试图实现的目标的图像:-
在中,您需要使用一些trig来确定点的位置,但是逻辑应该不会那么困难 您知道每个圆弧的半径,并且可能知道每组匹配点应位于的高度(y值) 看看这个单位圆图: 在我们的例子中,不是一个单位圆,而是一个已知的半径R,它是当前圆弧的半径,但数学原理是相同的 需要为每个圆弧查找的缺失值为x。要找到它,我们首先需要找到角度是多少。这就是三角游戏的用武之地,老好人 给出如图所示的直角三角形,我们知道: sin(θ)=y/R 所以要找到角度本身,我们可以取反正弦,或弧正弦: theta=asin(y/R) 我们还知道: cos(θ)=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
的半径之一,并且每个对象还包含高度的数组
让每个对象包含相同的高度数组会有一些不必要的冗余,但这样做会使绘图部分更简单
要绘制点,我将首先创建一个组,以包含每个单独圆弧上的点:
var pointGroup = group.selectAll('.point-group')
.data(combinedData)
.enter().append('g')
.attr('class', 'point-group');
这是棘手的部分。然后,我将使用嵌套选择在每个单独的高度创建一个点。对于.data()
,我们将使用点组选择中的数据函数,该函数仅返回高度数组。这意味着“输入”选择将为每个单独的高度包含一个元素
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值和父节点的半径值,因为父节点是共享半径的所有点的组
下面是一个工作示例。您需要使用一些触发器来确定点的位置,但逻辑应该不会那么困难
您知道每个圆弧的半径,并且可能知道每组匹配点应位于的高度(y值)
看看这个单位圆图:
在我们的例子中,不是一个单位圆,而是一个已知的半径R,它是当前圆弧的半径,但数学原理是相同的
需要为每个圆弧查找的缺失值为x。要找到它,我们首先需要找到角度是多少。这就是三角游戏的用武之地,老好人
给出如图所示的直角三角形,我们知道:
sin(θ)=y/R
所以要找到角度本身,我们可以取反正弦,或弧正弦:
theta=asin(y/R)
我们还知道:
cos(θ)=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
的半径之一,并且每个对象还包含高度的数组
让每个对象包含相同的高度数组会有一些不必要的冗余,但这样做会使绘图部分更简单
要绘制点,我将首先创建一个组,以包含每个单独圆弧上的点:
var pointGroup = group.selectAll('.point-group')
.data(combinedData)
.enter().append('g')
.attr('class', 'point-group');
这是棘手的部分。然后,我将使用嵌套选择在每个单独的高度创建一个点。对于.data()
,我们将使用点组选择中的数据函数,该函数仅返回高度数组。这意味着“输入”选择将为每个单独的高度包含一个元素
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);