Как показать круги (созданные с использованием данных JSON) в обратном порядке с помощью функции задержки? - PullRequest
1 голос
/ 06 октября 2019

Я пытаюсь создать динамическую визуализацию, используя круги, которые «растягиваются» в течение некоторого времени, и все круги имеют одинаковую центральную точку.

У меня есть отдельный скрипт, который создает круги исохраняет данные в файле JSON - первый кружок в файле JSON - это наименьший кружок в верхней части изображения, связанного выше.

См. фрагмент кода ниже. По сути, скрипт добавляет данные кругов в круги в svg с видимостью, равной none. Скрипт показывает круги один за другим.

В добавляющей функции я попытался использовать функцию .lower (), чтобы изменить порядок добавления кругов к svg, потому что если бы я добавлял их в порядкечто файл JSON находится, каждый последующий круг будет скрывать тот, который находится под ним. Но затем анимация отображается в обратном направлении, где сначала отображается большой круг.

В раскрывающей функции я затем попытался добавить аналогичную функцию .lower () в метод перехода, чтобы каждый последующий круг отображался заранее выявленный круг но потом код ломается. Я просто в растерянности - любые указатели были бы очень благодарны.

html,
body,
#svg {
  background-color: #FFFFFF;
}
<html>

<head>
  <meta charset="utf-8" />
  <title>Visualizer</title>
</head>

<body>
  <div>
    <button onclick="plotStatically(0, 0, 'testingcircle.json')">Draw Static &#9658;</button>

    <button onclick="plotConsecutively(0, 0, 'testingcircle.json')">Draw Dynamic &#9658;</button>
  </div>


  <script src="https://d3js.org/d3.v5.min.js" charset="utf-8"></script>

  <script>
    function plotConsecutively(x, y, nameFile) {

      d3.json(nameFile).then(function(data) {

        var svgHeight = window.innerHeight - 100;
        var svgWidth = window.innerWidth - 10;

        var svg = d3.select('body').append('svg')
          .attr('width', svgWidth)
          .attr('height', svgHeight);

        svg.selectAll("circle")
          .data(data)
          .enter()
          .append('circle')
          .attr('r', function(d) {
            return d.r;
          })
          .attr('cx', function(d) {
            return d.cx + x;
          })
          .attr('cy', function(d) {
            return d.cy + y;
          })
          .attr('fill', function(d) {
            return d.fill;
          })
          .attr('visibility', 'hidden')

        svg.selectAll("circle")
          .transition()
          .delay(function(d, i) {
            return 3.4 * i;
          })
          .duration(10)
          .attr('visibility', 'visible');
      })
    }


    function plotStatically(x, y, nameFile) {

      d3.json(nameFile).then(function(data) {

        var svgHeight = window.innerHeight - 100;
        var svgWidth = window.innerWidth - 10;

        var svg = d3.select('body').append('svg')
          .attr('width', svgWidth)
          .attr('height', svgHeight);

        svg.selectAll("circle")
          .data(data)
          .enter()
          .append('circle')
          .attr('r', function(d) {
            return d.r;
          })
          .attr('cx', function(d) {
            return d.cx;
          })
          .attr('cy', function(d) {
            return d.cy;
          })
          .attr('fill', function(d) {
            return d.fill;
          });
      })
    }
  </script>


</body>

</html>

1 Ответ

1 голос
/ 06 октября 2019

Я думаю, что вы в значительной степени были там.

Как вы сказали, сначала нужно добавить большие круги к svg, чтобы они не блокировали меньшие круги под ними. Я думаю, что это проще всего сделать, просто изменив порядок массива данных сразу после того, как вы получите результаты файла json:

d3.json(nameFile).then(function(data) {

  data = data.reverse();
  ...

Затем, чтобы показать круги изнутри, выможно изменить функцию задержки так, чтобы элементы в конце массива, которые вы хотите показать первыми (меньшие кружки), имели наименьшую задержку, а элементы в начале массива, которые вы хотите показать последними (большие кружки)) имеют наибольшую задержку.

Третьим аргументом функции delay() является NodesList, содержащий все выбранные элементы DOM, поэтому вы можете использовать свойство length этого массива в своих вычислениях.

...
.delay(function(d, i, circleNodes) {
  return 3.4 * ((circleNodes.length - 1) - i);
})
...

let data = [
  {"r":5,"cx":100,"cy":100,"fill":"red"},       {"r":10,"cx":100,"cy":100,"fill":"magenta"},{"r":15,"cx":100,"cy":100,"fill":"orange"},{"r":20,"cx":100,"cy":100,"fill":"green"},{"r":25,"cx":100,"cy":100,"fill":"blue"}
];

data = data.reverse();

function plotConsecutively() {

    var svg = d3.select('#svg')
      .append('svg')
      .attr('width', 200)
      .attr('height', 200);

    svg.selectAll("circle")
      .data(data)
      .enter()
      .append('circle')
      .attr('r', function(d) {
        return d.r;
      })
      .attr('cx', function(d) {
        return d.cx;
      })
      .attr('cy', function(d) {
        return d.cy;
      })
      .attr('fill', function(d) {
        return d.fill;
      })
      .attr('visibility', 'hidden')

    svg.selectAll('circle')
      .transition()
      .delay(function(d, i, nodes) {
        return 150 * ((nodes.length - 1) - i);
      })
      .duration(10)
      .attr('visibility', 'visible');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<button onclick="plotConsecutively()">Draw Dynamic &#9658;</button>

<div id="svg"></div>
...