d3.js 中的堆积圆散点图?
Scatterplot of packed circles in d3.js?
有没有办法创建稀疏散点图可视化,其中每个 "point" 是一个 one-level packed circle?我一直在尝试用 d3 来做这个,但我不知道是否有可能在同一个 svg 中制作多个不同的包布局......(或者我是否应该这样做)。任何帮助将不胜感激!
我希望它最终看起来像下面的草图:
这是您要实现的目标的示例:
只是把它放在一起。它需要 d3 耀斑数据并将 scatter-plot 输出第一级 children 和它们的 children.
数据结构:
var flareData = {
"name": "root",
"children": [{
"name": "pointOne",
"scatX": 10,
"scatY": 20,
"children": [{
"name": "pointOneA",
"children": [{
"name": "A",
"size": 40
}, {
"name": "B",
"size": 50
}]
}, {
"name": "pointOneB",
"children": [{
"name": "C",
"size": 10
}, {
"name": "D",
"size": 23
}]
}]
}, {
"name": "pointTwo",
...
创建绘图和轴的典型 d3
代码:
var
WIDTH = 600,
HEIGHT = 600,
DIAMETER = 200;
var vis = d3.select('body')
.append('svg')
.attr('width', WIDTH)
.attr('height', HEIGHT);
var MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale
.linear()
.range([MARGINS.left, WIDTH - MARGINS.right])
.domain([d3.min(flareData.children, function(d) {
return d.scatX;
}) - 10, d3.max(flareData.children, function(d) {
return d.scatX;
}) + 10]),
yRange = d3.scale
.linear()
.range([HEIGHT - MARGINS.top, MARGINS.bottom])
.domain([d3.min(flareData.children, function(d) {
return d.scatY;
}) - 10, d3.max(flareData.children, function(d) {
return d.scatY;
}) + 10]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient('left')
.tickSubdivide(true);
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
让打包布局的滥用开始:
// normal packed layout
var pack = d3.layout.pack()
.size([DIAMETER - 4, DIAMETER - 4])
.value(function(d) {
return d.size;
});
// classify each level
var node = vis.datum(flareData).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) {
// root level
if (!d.parent) {
return "node rootNode";
// first level children, these are our scatter points
} else if (d.children && !d.parent.parent) {
return "node pointNode";
// an intermediate circle
} else if (d.children) {
return "node innerNode";
// last level packing
} else {
return "node innerNode packedNode";
}
});
// use calculated radius
node.append("circle")
.attr("r", function(d) {
return d.r;
});
// we don't care about root circle, move off page
node.filter(".rootNode")
.attr("transform", "translate(" + -100 + "," + -100 + ")");
// this is our scatter point
node.filter(".pointNode")
.attr("transform", function(d) {
return "translate(" + xRange(d.scatX) + "," + yRange(d.scatY) + ")";
});
// any circle in a scatter point
node.filter(".innerNode")
.attr("transform", function(d) {
var iter = d;
while(!iter.scatX){
iter = iter.parent;
}
// diff from scatter point...
var difX = iter.x - d.x,
difY = iter.y - d.y;
return "translate(" + (xRange(iter.scatX) + difX) + "," + (yRange(iter.scatY) + difY) + ")";
})
// finally label our last level
node.filter(".packedNode")
.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.name;
});
例子here.
产生:
有没有办法创建稀疏散点图可视化,其中每个 "point" 是一个 one-level packed circle?我一直在尝试用 d3 来做这个,但我不知道是否有可能在同一个 svg 中制作多个不同的包布局......(或者我是否应该这样做)。任何帮助将不胜感激!
我希望它最终看起来像下面的草图:
这是您要实现的目标的示例:
只是把它放在一起。它需要 d3 耀斑数据并将 scatter-plot 输出第一级 children 和它们的 children.
数据结构:
var flareData = {
"name": "root",
"children": [{
"name": "pointOne",
"scatX": 10,
"scatY": 20,
"children": [{
"name": "pointOneA",
"children": [{
"name": "A",
"size": 40
}, {
"name": "B",
"size": 50
}]
}, {
"name": "pointOneB",
"children": [{
"name": "C",
"size": 10
}, {
"name": "D",
"size": 23
}]
}]
}, {
"name": "pointTwo",
...
创建绘图和轴的典型 d3
代码:
var
WIDTH = 600,
HEIGHT = 600,
DIAMETER = 200;
var vis = d3.select('body')
.append('svg')
.attr('width', WIDTH)
.attr('height', HEIGHT);
var MARGINS = {
top: 20,
right: 20,
bottom: 20,
left: 50
},
xRange = d3.scale
.linear()
.range([MARGINS.left, WIDTH - MARGINS.right])
.domain([d3.min(flareData.children, function(d) {
return d.scatX;
}) - 10, d3.max(flareData.children, function(d) {
return d.scatX;
}) + 10]),
yRange = d3.scale
.linear()
.range([HEIGHT - MARGINS.top, MARGINS.bottom])
.domain([d3.min(flareData.children, function(d) {
return d.scatY;
}) - 10, d3.max(flareData.children, function(d) {
return d.scatY;
}) + 10]),
xAxis = d3.svg.axis()
.scale(xRange)
.tickSize(5)
.tickSubdivide(true),
yAxis = d3.svg.axis()
.scale(yRange)
.tickSize(5)
.orient('left')
.tickSubdivide(true);
vis.append('svg:g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + (HEIGHT - MARGINS.bottom) + ')')
.call(xAxis);
vis.append('svg:g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (MARGINS.left) + ',0)')
.call(yAxis);
让打包布局的滥用开始:
// normal packed layout
var pack = d3.layout.pack()
.size([DIAMETER - 4, DIAMETER - 4])
.value(function(d) {
return d.size;
});
// classify each level
var node = vis.datum(flareData).selectAll(".node")
.data(pack.nodes)
.enter().append("g")
.attr("class", function(d) {
// root level
if (!d.parent) {
return "node rootNode";
// first level children, these are our scatter points
} else if (d.children && !d.parent.parent) {
return "node pointNode";
// an intermediate circle
} else if (d.children) {
return "node innerNode";
// last level packing
} else {
return "node innerNode packedNode";
}
});
// use calculated radius
node.append("circle")
.attr("r", function(d) {
return d.r;
});
// we don't care about root circle, move off page
node.filter(".rootNode")
.attr("transform", "translate(" + -100 + "," + -100 + ")");
// this is our scatter point
node.filter(".pointNode")
.attr("transform", function(d) {
return "translate(" + xRange(d.scatX) + "," + yRange(d.scatY) + ")";
});
// any circle in a scatter point
node.filter(".innerNode")
.attr("transform", function(d) {
var iter = d;
while(!iter.scatX){
iter = iter.parent;
}
// diff from scatter point...
var difX = iter.x - d.x,
difY = iter.y - d.y;
return "translate(" + (xRange(iter.scatX) + difX) + "," + (yRange(iter.scatY) + difY) + ")";
})
// finally label our last level
node.filter(".packedNode")
.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) {
return d.name;
});
例子here.
产生: