Реализации SVG идеальны, если на них есть анимация. В этой статье мы обсудим, как сделать анимацию на изображениях SVG с помощью D3. SVG имеет встроенную возможность создания анимаций / преобразований. Мы можем добавить эту возможность через d3.

Один из прекрасных вариантов использования SVG - это создание анимации. Используя преимущества SVG-анимации, вы можете создавать простые игры, анимировать персонажей, анимацию загрузки графиков и диаграмм.

В этой статье мы делаем многострочную диаграмму с анимацией при загрузке. Если вы хотите более подробно изучить концепцию SVG-анимации, прочтите мою статью об SVG-анимации.



Приступим к кодированию….

Это набор шагов, которые мы обсуждаем в этой статье.

  1. Сначала мы настроим рабочее пространство и прочитаем входные данные с помощью библиотеки d3.js.
  2. Далее сделаем линейный график.
  3. Наконец, мы создадим график анимации загрузки.

Перейдем к первому шагу…. Настройка рабочего места.

Шаг 1. Настройка рабочего пространства

Во-первых, давайте подготовим нашу HTML-страницу. Чтобы сначала поиграть с d3 на своей HTML-странице, вам нужно добавить специфические для d3 библиотеки на HTML-страницу.

Ага… .. наше рабочее пространство готово поиграть с d3.js

Приступим к написанию кода для создания холста SVG с полями. Следующий фрагмент кода создает холст SVG шириной 630px и высотой 400px.

var margin = {top: 20, right: 50, bottom: 30, left: 50},
    width = 630 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;
 
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

Теперь наш холст SVG готов. Здесь следуйте тегам SVG, созданным на основе приведенного выше фрагмента кода.

<svg width="630" height="400">
    <g transform="translate(50,20)"></g>
</svg>

Далее нам нужно получить данные для двух линий линейного графика. Итак, нам нужно проанализировать два файла данных и построить график результата. Здесь я использую данные об акциях компаний Amazon и Apple за последние 6 месяцев. Формат данных выглядит следующим образом.

В этой ситуации нам нужно читать данные из двух файлов. Реализация d3.queue помогает читать одновременно с нескольких ресурсов.

var parseDate = d3.timeParse("%m/%d/%Y");
d3.queue()
  .defer(d3.csv, "/data/apple-6-months-data.csv")
  .defer(d3.csv, "/data/amazon-6-months-data.csv")
  .await(ready);
function ready(error, apple, amazon) {
    if (error) throw error;
    
    apple.forEach(function(d) {
        d.date = parseDate(d.date);
    });
    apple.forEach(function(d) {
        d.close = Number(d.close.replace(/[^0-9.-]+/g,""));
    });
apple.sort(function(a, b) {
        return a.date - b.date;
    });
amazon.forEach(function(d) {
        d.date = parseDate(d.date);
    });
    amazon.forEach(function(d) {
        d.close = Number(d.close.replace(/[^0-9.-]+/g,""));
    });
amazon.sort(function(a, b) {
        return a.date - b.date;
    });
}

Приведенный выше фрагмент кода является примером чтения из нескольких ресурсов с использованием d3.queue реализации. После завершения чтения ресурса он вызовет функцию обратного вызова ready() с параметром error, first file data, second file data. Внутри функции ready вы можете играть с данными файла.

В приведенном выше фрагменте кода выполняется следующий набор действий.

  1. Прочтите содержимое файла с помощью d3.queue.
  2. После завершения чтения файла запускается функция готовности с ошибкой и данными файла.
  3. Если есть ошибка, функция выдает error.
  4. Разбор типа переменной apple date (d.date) на дату из строки.
  5. Преобразование конечного баланса яблока в числовой тип.
  6. Сортировка данных яблока по дате.
  7. Повторите шаги 4,5,6 и для Amazon.

Шаг 2: Создание линейного графика

Итак, мы анализируем данные. Далее мы собираемся создать линейную диаграмму, используя проанализированные данные. Ниже следует часть построения линейной диаграммы в нашей готовой функции.

var xAxis = d3.axisBottom()
    .scale(x)
    .ticks(5)
    .tickSizeInner(15)
    .tickSizeOuter(0);
var yAxis = d3.axisLeft()
    .scale(y)
    .tickFormat(d3.format("$.2f"))
    .ticks(5)
    .tickSizeInner(15)
    .tickSizeOuter(0);
function ready(error, apple, amazon) {
.....
//apple - contains apple 6 months data
//amazon - contains amazon 6 months data
x.domain(d3.extent(apple, function(d) { return d.date; }));
var amzn_ext = d3.extent(amazon, function(d) { return d.close; });
var apple_ext = d3.extent(apple, function(d) { return d.close; });
y.domain([
       d3.min([amzn_ext[0],apple_ext[0]]),
       d3.max([amzn_ext[1],apple_ext[1]])
 ]);
svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
svg.append("g")
      .attr("class", "y axis")
      .call(yAxis);
svg.append("line")
        .attr(
        {
            "class":"horizontalGrid",
            "x1" : 0,
            "x2" : width,
            "y1" : y(0),
            "y2" : y(0),
            "fill" : "none",
            "shape-rendering" : "crispEdges",
            "stroke" : "black",
            "stroke-width" : "1px",
            "stroke-dasharray": ("3, 3")
        });
var combinedData = [];
combinedData[0] = {name: 'apple', data: apple};
combinedData[1] = {name: 'amazon', data: amazon};
svg.selectAll(".plot-axis")
      .data(combinedData)
    .enter().append("g")
      .attr("class", "plot-axis")
   .append("path")
      .attr("class", "line")
      .attr("d", function(d) { return line(d.data); });
}

В приведенном выше фрагменте кода переменная apple содержит данные Apple за 6 месяцев, а переменная amazon содержит данные Amazon за 6 месяцев. Эта совокупность данных объясняется в шаге 1. Здесь, в приведенном выше фрагменте кода, выполняется следующий набор действий.

  1. Модуль d3.extent определяет максимальное и минимальное значения диапазона дат за последние 6 месяцев. И для Amazon, и для Apple диапазон дат здесь одинаковый. Так что рассматривая только Амазонку.
  2. Определение максимальных и минимальных значений amazon и apple сальдо закрытия с помощью d3.extent.
  3. узнать минимальное и максимальное значения данных из шага 2. Это необходимо для определения минимальных и максимальных значений оси Y.
  4. Построение осей x и y с использованием SVG.
  5. Создание массива переменных combinedData , который содержит два значения: данные Apple и Amazon за 6 месяцев.
  6. Создание линейного графика на основе массива combinedData.

Мы закончили построение линейного графика. Далее мы перейдем к основной идее этой статьи, а именно к анимации линейного графика.

Шаг 3: Создание анимации

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

function ready(error, apple, amazon) {
  ...
svg.selectAll(".plot-axis")
     .data(combinedData)
     .enter().append("g")
     .attr("class", "plot-axis");
var path = svg.selectAll(".plot-axis").append("path")
      .attr("class", "line")
      .attr("d", function(d) { return line(d.data); });
   
d3.select(path._groups[0][0])
      .attr("stroke-dasharray", totalLength[0] + " " + totalLength[0] ) 
      .attr("stroke-dashoffset", totalLength[0])
      .transition()
      .duration(5000)
      .ease(d3.easeLinear)
      .attr("stroke-dashoffset", 0);
d3.select(path._groups[0][1])
      .attr("stroke-dasharray", totalLength[1] + " " + totalLength[1] )
      .attr("stroke-dashoffset", totalLength[1])
      .transition()
      .duration(5000)
      .ease(d3.easeLinear)
      .attr("stroke-dashoffset", 0);
  
  }

Вышеупомянутая строка кода выполняет следующий набор действий.

  1. Создайте два пути на основе массива combinedData.
  2. Повторение path._groups[0][0] и применение линейного перехода длительностью 5 секунд.
  3. Итерируем path._groups[0][1] и применяем линейный переход длительностью 5 секунд.

Здесь следует полный набор кода для реализации линейной диаграммы.

Результат приведенного выше фрагмента кода выглядит следующим образом.

В этой статье мы увидели, как сделать базовую анимацию на линейном графике с помощью d3. На официальном сайте D3 вы можете увидеть более сложные примеры графиков d3.