#javascript #d3.js
#javascript #d3.js
Вопрос:
Я корректирую этот код круговой диаграммы и пытаюсь анимировать сегмент, чтобы он выступал, как кусок торта при наведении. Не уверен, почему область действия событий наведения / оставления курсора мыши не работает. Я пытался настроить радиус, но это так, как будто он не получает объект arc должным образом
var color = d3.scale.category20c();
var data = [{"label":"Category A", "value":20},
{"label":"Category B", "value":50},
{"label":"Category C", "value":30},
{"label":"Category A", "value":20},
{"label":"Category B", "value":50},
{"label":"Category C", "value":30},
{"label":"Category A", "value":20},
{"label":"Category B", "value":50},
{"label":"Category C", "value":5}];
var $this = '#chart';
d3.select($this)
.selectAll('svg')
.remove();
const width = 300,
height = 300,
radius = 120,
innerradius = 0;
var arc = d3
.arc()
.outerRadius(radius)
.innerRadius(innerradius);
data.forEach(function(d) {
d.total = d.value;
});
var pie = d3
.pie()
.sort(null)
.value(function(d) {
return d.total;
});
var svg = d3
.select($this)
.append('svg')
.attr('width', width)
.attr('height', height)
.append('g')
.attr('class', 'piechart')
.attr('transform', 'translate(' width / 2 ',' height / 2 ')');
var segments = svg.append('g').attr('class', 'segments');
var slices = segments
.selectAll('.arc')
.data(pie(data))
.enter()
.append('g')
.attr('class', 'arc');
slices
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) {
return color(i);
})
.transition()
.attrTween('d', function(d) {
var i = d3.interpolate(d.startAngle 0.1, d.endAngle);
return function(t) {
d.endAngle = i(t);
return arc(d);
}
});
slices.on('mouseover', function(d) {
console.log("mouseover", radius);
console.log("this", this)
console.log("d3.select(this)", d3.select(this))
let expandArc = d3.arc()
.innerRadius(innerradius)
.outerRadius(radius * 1.2);
/*
d3
.arc()
.outerRadius(radius)
.innerRadius(innerradius)
*/
d3.select(this)
.transition()
.duration(1000)
//.ease('bounce')
.attr('d', expandArc);
});
slices.on('mouseout', function() {
console.log("mouseout");
});
Ответ №1:
Если я правильно вас понял, «вытащив срез», то вы хотите перевести положение среза, а не изменить его форму.
Самое сложное — выяснить, куда перевести фигуру, чтобы срез перемещался от центра под правильным углом. Самое простое решение — использовать центроид, среднюю точку среза, а затем скорректировать эти значения по мере необходимости:
slices.on('mouseover', function(d) {
d3.select(this)
.transition()
.duration(1000)
.attr('transform', 'translate(' (arc.centroid(d)[0] / 2) ',' (arc.centroid(d)[1] / 2) ')');
});
slices.on('mouseout', function() {
d3.select(this)
.transition()
.duration(500)
.attr('transform', 'translate(0, 0)');
});
Здесь я делю значения центроидов x и y пополам, чтобы срезы не выходили за пределы области SVG.
PS: var color = d3.scale.category20c();
это d3v3, чтобы сделать это в d3v4, это было бы: var color = d3.scaleOrdinal(d3.schemeCategory20);
. Скрипка, которую вы связали, использует оба.
Комментарии:
1. это здорово — как вы его немного вытягиваете — (arc.centroid(d) [0] / 2) — зачем делить на 2?
2. Я вижу — без / 2 — он выступает в сторону половины сегмента
Ответ №2:
Разверните срез
Событие мыши привязывается к slices
<g>
элементу на самом деле. Тогда d3.select(this)
<g>
вместо точного path
элемента. Вы можете видеть <g>
d
, что после наведения будет иметь атрибут, но нам нужно изменить d
path
его.
Попробуйте
slices.on('mouseover', function(d) {
let expandArc = d3.arc()
.innerRadius(innerradius)
.outerRadius(radius * 1.2);
d3.select(this)
.select("path")
.transition()
.duration(1000)
//.ease('bounce')
.attr('d', expandArc);
});
Переведите фрагмент
Найдите центр тяжести пути и переведите его при наведении курсора
let offset = 4;// how much do you want to translate from the origin
slices.on('mouseover', function(d) {
d3.select(this)
.transition()
.duration(1000)
.attr('transform', 'translate(' arc.centroid(d)[0] / offset ',' arc.centroid(d)[1] / offset ')')
});
slices.on('mouseout', function() {
d3.select(this)
.transition()
.duration(1000)
.attr('transform', 'translate(0,0)')
});
Комментарии:
1. Я вижу — как вы вытаскиваете кусочек — больше похоже на кусочек торта — чтобы его вытащили из центра
2. Тогда мы должны изменить
translate
размер среза вместо изменения радиуса. Обновленный ответ