嗨,我已经使用d3js搜索了金字塔图,但是没有找到任何不对数据进行排序即可呈现金字塔图的示例。我正在尝试通过删除代码的排序部分来适应this pyramid图表示例。
这就是我所拥有的(fiddle form):。
d3.pyramid = function() {
var size = [1,1],
value = function(d) { return d.value},
coordinates;
var percentageValues = function (data) {
var values = data.map(value);
var sum = d3.sum(values, function (d){
return +d;
});
var percentValues = data.map(function (d,i){
d.value = +values[i];
return values[i]/sum*100;
});
//I don't want sorting, i want to display in the same order data is passwed, i pass high-medium-low
//like in high chart https://jsfiddle.net/nc7bzdx3/7/
/* percentValues.sort(function(a,b){
return b-a;
}); */
return percentValues;
}
var coordinatesCalculation = function(data){
var w = size[0],
h = size[1],
ratio = (w/2)/h,
percentValues = percentageValues(data),
coordinates = [],
area_of_triangle = (w * h) / 2;
function d3Sum (i) {
return d3.sum(percentValues,function (d, j){
if (j>=i) {
return d;
}
});
}
for (var i=0,len=data.length;i<len; i++){
var selectedPercentValues = d3Sum(i),
area_of_element = selectedPercentValues/100 * area_of_triangle,
height1 = Math.sqrt(area_of_element/ratio),
base = 2 * ratio * height1,
xwidth = (w-base)/2;
if (i===0){
coordinates[i] = {"values":[{"x":w/2,"y":0},{"x":xwidth,"y":height1},{"x":base+xwidth,"y":height1}]};
}else{
coordinates[i] = {"values":[coordinates[i-1].values[1],{"x":xwidth,"y":height1},{"x":base+xwidth,"y":height1},coordinates[i-1].values[2]]};
}
}
coordinates[0].values[1] = coordinates[coordinates.length-1].values[1];
coordinates[0].values[2] = coordinates[coordinates.length-1].values[2];
var first_data = coordinates.splice(0,1);
coordinates = coordinates.reverse();
coordinates.splice(0,0,first_data[0]);
return coordinates;
}
function pyramid(data) {
var i = 0,
coordinates = coordinatesCalculation(data);
/* data.sort(function(a,b) {
return a.value - b.value;
}) */
data.forEach(function(){
data[i].coordinates = coordinates[i].values;
i++;
})
return data;
}
pyramid.size = function(s){
if(s.length === 2) {
size = s;
}
return pyramid;
}
pyramid.value = function(v) {
if (!arguments.length) return value;
value = v;
return pyramid;
};
return pyramid;
}
var data = [
{priority: 'High', count: 1000, key: 1},
{priority: 'Medium', count: 120, key: 2},
{priority: 'Low', count: 60, key: 3}
];
var svg;
var CANVAS_CLASS = "canvas";
var MARGIN = {top: 20, right: 40, bottom: 30, left: 40};
var width = 400, height = 300;
var color = d3.scale.ordinal()
.range(["#F24936", "#F6BF18", "#FFFFFF", "#0000FF"]);
var svg = d3.select("body").append('svg')
.attr("width", width + 300)
.attr("height", height)
.attr('class', CANVAS_CLASS)
.append("g");
var pyramid = d3.pyramid()
.size([width, height])
.value(function (d) {
return d.count;
});
var line = d3.svg.line()
.interpolate('linear-closed')
.x(function (d, i) {
return d.x;
})
.y(function (d, i) {
return d.y;
});
var pyramidData = pyramid(data);
var g = svg.selectAll(".pyramid-group")
.data(pyramidData)
.enter().append("g")
.attr("class", "pyramid-group");
g.append("path")
.attr("d", function (d) {
return line(d.coordinates);
})
.style("fill", function (d) {
return color(d.priority);
});
g.append("text")
.attr({
"y": function (d, i) {
if (d.coordinates.length === 4) {
return (((d.coordinates[0].y - d.coordinates[1].y) / 2) + d.coordinates[1].y) + 5;
} else {
return (d.coordinates[0].y + d.coordinates[1].y) / 2 + 10;
}
},
"x": function (d, i) {
return width / 2;
}
})
.style("text-anchor", "middle")
.text(function (d) {
return d.priority+ '_'+d.count;
});
* {
margin: 0;
padding: 0;
border: 0;
}
body {
background: #ffd;
}
.arc path {
stroke: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.10/d3.min.js"></script>
我已注释掉排序,但是输出不正确:区域不对应于未排序的值。如何使金字塔形图按输入顺序显示输入数据的区域?
任何帮助将不胜感激。谢谢
答案 0 :(得分:0)
如果我理解正确,则不会为每个分段呈现正确的区域。如果我们看一下原始代码,则有两种倒置类型b-a
和a-b
,它们都基于value属性。似乎按百分比排序时,排序与按值排序数据时相反。通过删除所有排序,我们没有基准和百分比相反的顺序。
因此,如果我们反转百分比的顺序,则应该使基准面与面积正确对齐:
d3.pyramid = function() {
var size = [1,1],
value = function(d) { return d.value},
coordinates;
var percentageValues = function (data) {
var values = data.map(value);
var sum = d3.sum(values, function (d){
return +d;
});
var percentValues = data.map(function (d,i){
d.value = +values[i];
return values[i]/sum*100;
});
percentValues.reverse();
return percentValues;
}
var coordinatesCalculation = function(data){
var w = size[0],
h = size[1],
ratio = (w/2)/h,
percentValues = percentageValues(data),
coordinates = [],
area_of_triangle = (w * h) / 2;
function d3Sum (i) {
return d3.sum(percentValues,function (d, j){
if (j>=i) {
return d;
}
});
}
for (var i=0,len=data.length;i<len; i++){
var selectedPercentValues = d3Sum(i),
area_of_element = selectedPercentValues/100 * area_of_triangle,
height1 = Math.sqrt(area_of_element/ratio),
base = 2 * ratio * height1,
xwidth = (w-base)/2;
if (i===0){
coordinates[i] = {"values":[{"x":w/2,"y":0},{"x":xwidth,"y":height1},{"x":base+xwidth,"y":height1}]};
}else{
coordinates[i] = {"values":[coordinates[i-1].values[1],{"x":xwidth,"y":height1},{"x":base+xwidth,"y":height1},coordinates[i-1].values[2]]};
}
}
coordinates[0].values[1] = coordinates[coordinates.length-1].values[1];
coordinates[0].values[2] = coordinates[coordinates.length-1].values[2];
var first_data = coordinates.splice(0,1);
coordinates = coordinates.reverse();
coordinates.splice(0,0,first_data[0]);
return coordinates;
}
function pyramid(data) {
var i = 0,
coordinates = coordinatesCalculation(data);
/* data.sort(function(a,b) {
return a.value - b.value;
}) */
data.forEach(function(){
data[i].coordinates = coordinates[i].values;
i++;
})
return data;
}
pyramid.size = function(s){
if(s.length === 2) {
size = s;
}
return pyramid;
}
pyramid.value = function(v) {
if (!arguments.length) return value;
value = v;
return pyramid;
};
return pyramid;
}
var data = [
{priority: 'High', count: 1000, key: 1},
{priority: 'Medium', count: 500, key: 2},
{priority: 'Low', count: 160, key: 3}
];
var svg;
var CANVAS_CLASS = "canvas";
var MARGIN = {top: 20, right: 40, bottom: 30, left: 40};
var width = 400, height = 150;
var color = d3.scale.ordinal()
.range(["#F24936", "#F6BF18", "#FFFFFF", "#0000FF"]);
var svg = d3.select("body").append('svg')
.attr("width", width + 300)
.attr("height", height)
.attr('class', CANVAS_CLASS)
.append("g");
var pyramid = d3.pyramid()
.size([width, height])
.value(function (d) {
return d.count;
});
var line = d3.svg.line()
.interpolate('linear-closed')
.x(function (d, i) {
return d.x;
})
.y(function (d, i) {
return d.y;
});
var pyramidData = pyramid(data);
var g = svg.selectAll(".pyramid-group")
.data(pyramidData)
.enter().append("g")
.attr("class", "pyramid-group");
g.append("path")
.attr("d", function (d) {
return line(d.coordinates);
})
.style("fill", function (d) {
return color(d.priority);
});
g.append("text")
.attr({
"y": function (d, i) {
if (d.coordinates.length === 4) {
return (((d.coordinates[0].y - d.coordinates[1].y) / 2) + d.coordinates[1].y) + 5;
} else {
return (d.coordinates[0].y + d.coordinates[1].y) / 2 + 10;
}
},
"x": function (d, i) {
return width / 2;
}
})
.style("text-anchor", "middle")
.text(function (d) {
return d.priority+ '_'+d.count;
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>