读取圆弧的内外半径 - d3.js
Read inner and outer radius of arc - d3.js
我正在从事一个处理大型关系数据的可视化表示的项目。我们正在使用饼图来显示数据组件(按顺序)。由于缺少 space,我们一次只显示 10 个。
考虑以下示例:
假设我有 100 个数据组件,在给定的时间点我将只显示其中的 10 个。我使用的逻辑是,我将其他 90 个组件的开始和结束角度设置为 0(零)。对于这 10 个组件,我计算的开始和结束角度如下-
var angle = 360;
var count = 10;
if(data.length > count) angle = angle/count; //data is array of data component names
else angle = angle/data.length;
//Initially I'll be displaying first ten components
for(var i=0; i<data.length; i++){
var startAngle = i * angle;
var endAngle = startAngle + angle;
var pi = = Math.PI/180;
var arc = d3.svg.arc()
.innerRadius(innerRadius) //dynamic value, calculated based on available space
.outerRadius(outerRadius) //dynamic value, calculated based on available space
.startAngle((startAngle)*pi)
.endAngle((endAngle)*pi);
//Hiding rest of the data components
if(i >= count){
arc.startAngle(0);
arc.endAngle(0);
}
arcGroup.append("path")
.attr("d", arc)
.attr("stroke", "#2E2E2E")
.attr("stroke-width", "1")
.attr("fill","gold");
var text = arcGroup.append("text")
.attr("transform", "translate(" + arc.centroid() + ")")
.attr("text-anchor", "middle")
.attr("font-family","noto_sansregular")
.attr("font-size", 40)
.attr("font-weight","Bold")
.attr("fill", "#000000")
.attr("y",0)
.style("visibility", "visible")
.text(data[i]);
//Hiding text of hidden arcs
if(i >= count) text.style("visibility", "hidden");
}
然后,如果用户想要查看其余组件,我将提供两个按钮来旋转(时钟或逆时钟)内容。
如果当前视图是 -> 1、2、3、4、5、6、7、8、9、10
顺时针旋转一个单元格,结果视图应为 -> 100, 1, 2, 3, 4, 5, 6, 7, 8, 9
在这种情况下,我需要隐藏组件“10”并显示组件“100”,并移动其余单元格。为此,我只需要更改圆弧的起点和终点角度。我可以用计算出的角度创建新的圆弧对象。
这里的问题是我不知道如何获取圆弧的内外半径,它们是动态创建的。
从技术上讲,可以从 path
元素的 d
属性中检索 innerRadius
和 outerRadius
,但需要解析 DSL 并将很乏味。这些值没有被 d3 很好地 存储在元素本身上。
因此,如果您在更新元素时重新计算 innerRadius
和 outerRadius
会更好:
function showFromIdx(firstIndex) {
argGroup.selectAll('path')
.data( d3.range(data.length)
.map(function (d) {
return (d - firstIndex + data.length) % data.length;
})
)
.attr('d', function (d) {
// You will have to calculate the radii again here.
var innerRadius = foo(d), outerRadius = bar(d);
return d3.svg.arc()
.startAngle(i < count ? i * angle : 0)
.endAngle(i < count ? (i + 1) * angle : 0)
.innerRadius(innerRadius)
.outerRadius(outerRadius)(d);
});
}
就这样,
...
arcGroup.append("path")
.filter(function(d) {
// You're Not restricted to the "filter" function
var innerRadius = d.innerRadius()(d);
var outerRadius = d.outerRadius()(d);
})
.attr("d", arc)
...
这是我编写的几个函数,用于获取使用 d3 创建的圆弧的内外半径。如果您发现代码中有错误,请告诉我。
function getInnerRadiusFromArc(arc) {
var numbersInPattern = _getArcNumbers(arc);
// Possibly, that's sector, so it starts from 0.
// Or maybe that's something else.
if (numbersInPattern.length < 4) {
return 0;
}
// Getting minimum from the array.
var innerRadius = Math.min.apply(null, numbersInPattern);
return innerRadius;
}
function getOuterRadiusFromArc(arc) {
var numbersInPattern = _getArcNumbers(arc);
// Getting maximum from the array.
var outerRadius = Math.max.apply(null, numbersInPattern);
return outerRadius;
}
function _getArcNumbers(arc) {
// Path description parameter, containing necessary data.
var pathDescription = arc.getAttribute("d");
// We need to get all patterns like A<number>,<number>.
// RegExp source:
// http://www.regular-expressions.info/floatingpoint.html
const numberRegExp = /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/g;
var arcPattern = new RegExp("A" + numberRegExp.source + "," + numberRegExp.source, "g");
var arcParameters = pathDescription.match(arcPattern);
var numbersInPattern = [];
// We get all the numbers from array ["A<number>,<number>", "A<number>,<number>", ...].
for (let parameterIndex = 0; parameterIndex < arcParameters.length; parameterIndex++) {
let parameter = arcParameters[parameterIndex];
let numbers = parameter.match(numberRegExp);
if (numbers !== null) {
numbersInPattern = numbersInPattern.concat(numbers);
}
}
// Transform strings in our array to numbers.
numbersInPattern = numbersInPattern.map(function (numberString) {
return parseFloat(numberString);
});
return numbersInPattern;
}
我正在从事一个处理大型关系数据的可视化表示的项目。我们正在使用饼图来显示数据组件(按顺序)。由于缺少 space,我们一次只显示 10 个。
考虑以下示例:
假设我有 100 个数据组件,在给定的时间点我将只显示其中的 10 个。我使用的逻辑是,我将其他 90 个组件的开始和结束角度设置为 0(零)。对于这 10 个组件,我计算的开始和结束角度如下-
var angle = 360;
var count = 10;
if(data.length > count) angle = angle/count; //data is array of data component names
else angle = angle/data.length;
//Initially I'll be displaying first ten components
for(var i=0; i<data.length; i++){
var startAngle = i * angle;
var endAngle = startAngle + angle;
var pi = = Math.PI/180;
var arc = d3.svg.arc()
.innerRadius(innerRadius) //dynamic value, calculated based on available space
.outerRadius(outerRadius) //dynamic value, calculated based on available space
.startAngle((startAngle)*pi)
.endAngle((endAngle)*pi);
//Hiding rest of the data components
if(i >= count){
arc.startAngle(0);
arc.endAngle(0);
}
arcGroup.append("path")
.attr("d", arc)
.attr("stroke", "#2E2E2E")
.attr("stroke-width", "1")
.attr("fill","gold");
var text = arcGroup.append("text")
.attr("transform", "translate(" + arc.centroid() + ")")
.attr("text-anchor", "middle")
.attr("font-family","noto_sansregular")
.attr("font-size", 40)
.attr("font-weight","Bold")
.attr("fill", "#000000")
.attr("y",0)
.style("visibility", "visible")
.text(data[i]);
//Hiding text of hidden arcs
if(i >= count) text.style("visibility", "hidden");
}
然后,如果用户想要查看其余组件,我将提供两个按钮来旋转(时钟或逆时钟)内容。
如果当前视图是 -> 1、2、3、4、5、6、7、8、9、10
顺时针旋转一个单元格,结果视图应为 -> 100, 1, 2, 3, 4, 5, 6, 7, 8, 9
在这种情况下,我需要隐藏组件“10”并显示组件“100”,并移动其余单元格。为此,我只需要更改圆弧的起点和终点角度。我可以用计算出的角度创建新的圆弧对象。
这里的问题是我不知道如何获取圆弧的内外半径,它们是动态创建的。
从技术上讲,可以从 path
元素的 d
属性中检索 innerRadius
和 outerRadius
,但需要解析 DSL 并将很乏味。这些值没有被 d3 很好地 存储在元素本身上。
因此,如果您在更新元素时重新计算 innerRadius
和 outerRadius
会更好:
function showFromIdx(firstIndex) {
argGroup.selectAll('path')
.data( d3.range(data.length)
.map(function (d) {
return (d - firstIndex + data.length) % data.length;
})
)
.attr('d', function (d) {
// You will have to calculate the radii again here.
var innerRadius = foo(d), outerRadius = bar(d);
return d3.svg.arc()
.startAngle(i < count ? i * angle : 0)
.endAngle(i < count ? (i + 1) * angle : 0)
.innerRadius(innerRadius)
.outerRadius(outerRadius)(d);
});
}
就这样,
...
arcGroup.append("path")
.filter(function(d) {
// You're Not restricted to the "filter" function
var innerRadius = d.innerRadius()(d);
var outerRadius = d.outerRadius()(d);
})
.attr("d", arc)
...
这是我编写的几个函数,用于获取使用 d3 创建的圆弧的内外半径。如果您发现代码中有错误,请告诉我。
function getInnerRadiusFromArc(arc) {
var numbersInPattern = _getArcNumbers(arc);
// Possibly, that's sector, so it starts from 0.
// Or maybe that's something else.
if (numbersInPattern.length < 4) {
return 0;
}
// Getting minimum from the array.
var innerRadius = Math.min.apply(null, numbersInPattern);
return innerRadius;
}
function getOuterRadiusFromArc(arc) {
var numbersInPattern = _getArcNumbers(arc);
// Getting maximum from the array.
var outerRadius = Math.max.apply(null, numbersInPattern);
return outerRadius;
}
function _getArcNumbers(arc) {
// Path description parameter, containing necessary data.
var pathDescription = arc.getAttribute("d");
// We need to get all patterns like A<number>,<number>.
// RegExp source:
// http://www.regular-expressions.info/floatingpoint.html
const numberRegExp = /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/g;
var arcPattern = new RegExp("A" + numberRegExp.source + "," + numberRegExp.source, "g");
var arcParameters = pathDescription.match(arcPattern);
var numbersInPattern = [];
// We get all the numbers from array ["A<number>,<number>", "A<number>,<number>", ...].
for (let parameterIndex = 0; parameterIndex < arcParameters.length; parameterIndex++) {
let parameter = arcParameters[parameterIndex];
let numbers = parameter.match(numberRegExp);
if (numbers !== null) {
numbersInPattern = numbersInPattern.concat(numbers);
}
}
// Transform strings in our array to numbers.
numbersInPattern = numbersInPattern.map(function (numberString) {
return parseFloat(numberString);
});
return numbersInPattern;
}