我正在开发一个处理大型关系数据可视化表示的项目。我们使用饼图来显示数据组件(按顺序)。由于空间不足,我们一次只能显示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");
}
然后,如果用户想要查看其余组件,我将提供两个按钮来旋转(时钟或反时钟)内容。
如果当前视图是 - &gt; 1,2,3,4,5,6,7,8,9,10
顺时针旋转一个单元格,结果视图应为 - &gt; 100,1,2,3,4,5,6,7,8,9
在这种情况下,我需要隐藏组件'10'并显示组件'100',并移动其余的单元格。为了实现这一点,我只需要改变弧的起始和终止角度。我可以创建具有计算角度的新弧对象。
这里的问题是我不知道如何获得动态创建的弧的内半径和外半径。
答案 0 :(得分:2)
从技术上讲,可以从innerRadius
元素的outerRadius
属性中检索d
和path
,但它需要解析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);
});
}
答案 1 :(得分:2)
就像那样,
...
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)
...
答案 2 :(得分:1)
以下是我编写的几个函数,用于获取使用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;
}