带有可拖动外半径的 d3 圆环图
d3 donut chart with draggable outerRadius
我正在尝试制作一个在每个楔形处具有可变半径的圆环图。每个 Wedge 都应该可以拖动以更改此楔形的宽度(宽度表示外半径)。
但是我不知道如何实现这个拖动功能。有人可以帮助我吗?
这是我的代码:
var width = 760,
height = 550;
var innerradius = 200;
var color = d3.scale.category20b();
var cScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);
var dataset = [
{ label: 'Abulia', count: 10, start: 0, end: 10, radius: 10 },
{ label: 'Betelgeuse', count: 20, start: 10, end: 20, radius: 20 },
{ label: 'Cantaloupe', count: 30, start: 30, end: 60, radius: 20 },
{ label: 'Dijkstra', count: 40, start: 60, end: 100, radius: 20 }
];
var svg = d3.select('#content').append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
var arc = d3.svg.arc()
.innerRadius(innerradius)
.outerRadius(function(d){return d.radius + innerradius;})
.startAngle(function(d){return cScale(d.start);})
.endAngle(function(d){return cScale(d.end);});
var path = svg.selectAll('path')
.data(dataset)
.enter()
.append('path')
.attr('d', arc)
.style("fill", function(d){return color(d.label);});
var drag = d3.behavior.drag()
.on('drag', function() {
//don't know what to do
})
这是我的解决方案。
.on('drag', function(d) {
if (d3.event.sourceEvent.button == 0)
d.radius += Math.sqrt(d3.event.dx * d3.event.dx + d3.event.dy * d3.event.dy);
else if (d3.event.sourceEvent.button == 2){
d.radius -= Math.sqrt(d3.event.dx * d3.event.dx + d3.event.dy * d3.event.dy);
d.radius = Math.max (d.radius, 1);
}
path.each(function (d2){
if (d == d2){
d3.select(this).attr('d', arc);
}
});
});
这样,左键单击并拖动将增加楔形的半径,而右键单击并拖动将减小它。如果您选择保留此行为,那么您还需要覆盖默认的上下文菜单以防止它弹出。
但是,如果您希望能够通过左键单击来展开和收缩,事情就会变得有点复杂。这是因为此方法依赖于 drag
事件的 dx
和 dy
属性,无论弧在哪里,它都会是相同的方向。要通过单个鼠标按钮使用它,您必须相对于圆弧所面对的方向计算 dx
和 dy
(可能需要为此深入研究一些三角函数)。
我正在尝试制作一个在每个楔形处具有可变半径的圆环图。每个 Wedge 都应该可以拖动以更改此楔形的宽度(宽度表示外半径)。 但是我不知道如何实现这个拖动功能。有人可以帮助我吗?
这是我的代码:
var width = 760,
height = 550;
var innerradius = 200;
var color = d3.scale.category20b();
var cScale = d3.scale.linear().domain([0, 100]).range([0, 2 * Math.PI]);
var dataset = [
{ label: 'Abulia', count: 10, start: 0, end: 10, radius: 10 },
{ label: 'Betelgeuse', count: 20, start: 10, end: 20, radius: 20 },
{ label: 'Cantaloupe', count: 30, start: 30, end: 60, radius: 20 },
{ label: 'Dijkstra', count: 40, start: 60, end: 100, radius: 20 }
];
var svg = d3.select('#content').append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')');
var arc = d3.svg.arc()
.innerRadius(innerradius)
.outerRadius(function(d){return d.radius + innerradius;})
.startAngle(function(d){return cScale(d.start);})
.endAngle(function(d){return cScale(d.end);});
var path = svg.selectAll('path')
.data(dataset)
.enter()
.append('path')
.attr('d', arc)
.style("fill", function(d){return color(d.label);});
var drag = d3.behavior.drag()
.on('drag', function() {
//don't know what to do
})
这是我的解决方案。
.on('drag', function(d) {
if (d3.event.sourceEvent.button == 0)
d.radius += Math.sqrt(d3.event.dx * d3.event.dx + d3.event.dy * d3.event.dy);
else if (d3.event.sourceEvent.button == 2){
d.radius -= Math.sqrt(d3.event.dx * d3.event.dx + d3.event.dy * d3.event.dy);
d.radius = Math.max (d.radius, 1);
}
path.each(function (d2){
if (d == d2){
d3.select(this).attr('d', arc);
}
});
});
这样,左键单击并拖动将增加楔形的半径,而右键单击并拖动将减小它。如果您选择保留此行为,那么您还需要覆盖默认的上下文菜单以防止它弹出。
但是,如果您希望能够通过左键单击来展开和收缩,事情就会变得有点复杂。这是因为此方法依赖于 drag
事件的 dx
和 dy
属性,无论弧在哪里,它都会是相同的方向。要通过单个鼠标按钮使用它,您必须相对于圆弧所面对的方向计算 dx
和 dy
(可能需要为此深入研究一些三角函数)。