Первый переход d3 при обновлении внутри интервала не переходит

У меня есть кольцевая диаграмма, которая используется как способ показать прогресс. У меня нет возможности показать вам кольцевую диаграмму, но код достаточно прост для копирования и вставки.

Я добавил код, чтобы показать вам пример. Я пробовал различные неразумные методы, чтобы переход работал с первого раза. Но почему-то до сих пор не работает. Все примеры в Интернете очень похожи, поэтому я не совсем уверен, почему это происходит.

    var data = [95, 5];
    var pie = d3.pie().sort(null);
    var svg = d3.select("svg"),
        width = svg.attr("width"),
        height = svg.attr("height"),
        radius = Math.min(width, height) / 2;
    var arc = d3.arc()
        .innerRadius(60)
        .outerRadius(radius);

    function createdonut() {
            g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
        //Inner SVG Circle
        svg.append("svg:circle")
            .attr("cx", width / 2)
            .attr("cy", height / 2)
            .attr("r", 60)
            .style("fill", "#ead4d4")
            .append("g");
        var color = d3.scaleOrdinal(['#4daf4a', '#377eb8', '#ff7f00', '#984ea3', '#e41a1c']);
        
        //Generate groups

        var arcs = g.selectAll("arc")
            .data(pie(data))
            .enter()
            .append("g")
            .attr("class", "arc")

        //Draw arc paths
        arcs.append("path")
            .attr("fill", function (d, i) {
                return color(i);
            })
            .attr("d", arc)
            .on('mouseover', mouseover);

        function mouseover(d, i) {
            $('#percentage').html(i.data + ' units');
        }
    }
    function updateDoNut(update) {
        data[0] = data[0] - update;
        data[1] = data[1] + update;

        var path = d3.select("svg").selectAll("path").data(pie(data));
        
        /*path.enter().append("path")
            .attr("fill", function (d, i) {
                return color[i];
            })
            .attr("d", arc);*/

        path.transition().duration(100).attrTween("d", arcTween);
    }
    function arcTween(a) {
        var i = d3.interpolate(this._current, a);
        this._current = i(0);
        return function (t) {
            return arc(i(t));
        };
    }

    createdonut();
    //updateDoNut(0);
    var inter = setInterval(function () { updateDoNut(5); },  3000);
<script src = "https://d3js.org/d3.v6.min.js"></script>
<div id = "my_dataviz">
    <svg width = "300" height = "200"> </svg>
    <div id = "percentage">0 units</div>
</div>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
5
0
149
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если мы посмотрим на вашу функцию твина, мы увидим проблему:

    var i = d3.interpolate(this._current, a);
    this._current = i(0);

this.current не определено, когда вы впервые начинаете переходить — так как же D3 интерполировать между undefined и объектом, содержащим свойства дуги? Это не так. Результатом является отсутствие перехода, который вы видите. Установите this._current при добавлении дуг:

 arcs.append("path")
     .attr("fill", function (d, i) {
        return color(i);
     })
     .attr("d", arc)     
     .each(function(d) {
          this._current = d;
        })
     .on('mouseover', mouseover);

Теперь, когда вы обновляете окружность, для интерполятора есть допустимая начальная точка, и вы должны увидеть переход:

var data = [95, 5];
    var pie = d3.pie().sort(null);
    var svg = d3.select("svg"),
        width = svg.attr("width"),
        height = svg.attr("height"),
        radius = Math.min(width, height) / 2;
    var arc = d3.arc()
        .innerRadius(60)
        .outerRadius(radius);

    function createdonut() {
            g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
        //Inner SVG Circle
        svg.append("svg:circle")
            .attr("cx", width / 2)
            .attr("cy", height / 2)
            .attr("r", 60)
            .style("fill", "#ead4d4")
            .append("g");
        var color = d3.scaleOrdinal(['#4daf4a', '#377eb8', '#ff7f00', '#984ea3', '#e41a1c']);
        
        //Generate groups

        var arcs = g.selectAll("arc")
            .data(pie(data))
            .enter()
            .append("g")
            .attr("class", "arc")

        //Draw arc paths
        arcs.append("path")
            .attr("fill", function (d, i) {
                return color(i);
            })
            .attr("d", arc)
            .each(function(d) {
              this._current = d;
            })
            .on('mouseover', mouseover);

        function mouseover(d, i) {
            $('#percentage').html(i.data + ' units');
        }
    }
    function updateDoNut(update) {
        data[0] = data[0] - update;
        data[1] = data[1] + update;

        var path = d3.select("svg").selectAll("path").data(pie(data));
        path.transition().duration(2000).attrTween("d", arcTween);
    }
    function arcTween(a) {
        
        var i = d3.interpolate(this._current, a);
        this._current = i(0);
        return function (t) {
            return arc(i(t));
        };
    }

    createdonut();
    //updateDoNut(0);
    var inter = setInterval(function () { updateDoNut(5); },  3000);
<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src = "https://d3js.org/d3.v6.min.js"></script>
<div id = "my_dataviz">
    <svg width = "300" height = "200"> </svg>
    <div id = "percentage">0 units</div>
</div>

Почему эта интерполяция между undefined и объектом не приводит к ошибке? Ну, D3-interpolate будет очень сильно пытаться интерполировать. В этом случае между undefined и объектом будет использоваться d3-interpolateObject, который будет интерполировать следующим образом:

Для каждого свойства в b, если существует соответствующее свойство в a, общий интерполятор создается для двух элементов с использованием интерполировать. Если такого свойства нет, статическое значение из b равно используется в шаблоне. (документы)

Итак, поскольку в undefined нет свойств, интерполятор просто использует статическое значение для каждой точки интерполяции, отсюда и отсутствие перехода при первом обновлении: каждая интерполируемая точка одинакова: значения конечных точек.

Ничего себе, хорошо имеет смысл. Я предполагаю, что мой дополнительный вопрос будет таким: почему при вызове функции интерполятора не возникает ошибка, если this._current не определен?

essessonsee 18.12.2020 19:25

@essessonsee, добавил некоторые подробности о том, почему вы не видите ошибку.

Andrew Reid 19.12.2020 05:13

Другие вопросы по теме