круговая диаграмма d3v4 — при наведении на сегмент — развернуть сегмент, как кусочек торта

#javascript #d3.js

#javascript #d3.js

Вопрос:

Я корректирую этот код круговой диаграммы и пытаюсь анимировать сегмент, чтобы он выступал, как кусок торта при наведении. Не уверен, почему область действия событий наведения / оставления курсора мыши не работает. Я пытался настроить радиус, но это так, как будто он не получает объект arc должным образом

http://jsfiddle.net/xejmwnob/

 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 размер среза вместо изменения радиуса. Обновленный ответ