Реализации SVG идеальны, если на них есть анимация. В этой статье мы обсудим, как сделать анимацию на изображениях SVG с помощью D3. SVG имеет встроенную возможность создания анимаций / преобразований. Мы можем добавить эту возможность через d3.
Один из прекрасных вариантов использования SVG - это создание анимации. Используя преимущества SVG-анимации, вы можете создавать простые игры, анимировать персонажей, анимацию загрузки графиков и диаграмм.
В этой статье мы делаем многострочную диаграмму с анимацией при загрузке. Если вы хотите более подробно изучить концепцию SVG-анимации, прочтите мою статью об SVG-анимации.
Приступим к кодированию….
Это набор шагов, которые мы обсуждаем в этой статье.
- Сначала мы настроим рабочее пространство и прочитаем входные данные с помощью библиотеки d3.js.
- Далее сделаем линейный график.
- Наконец, мы создадим график анимации загрузки.
Перейдем к первому шагу…. Настройка рабочего места.
Шаг 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
вы можете играть с данными файла.
В приведенном выше фрагменте кода выполняется следующий набор действий.
- Прочтите содержимое файла с помощью
d3.queue
. - После завершения чтения файла запускается функция готовности с ошибкой и данными файла.
- Если есть ошибка, функция выдает
error
. - Разбор типа переменной apple
date
(d.date
) на дату из строки. - Преобразование конечного баланса яблока в числовой тип.
- Сортировка данных яблока по дате.
- Повторите шаги 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. Здесь, в приведенном выше фрагменте кода, выполняется следующий набор действий.
- Модуль
d3.extent
определяет максимальное и минимальное значения диапазона дат за последние 6 месяцев. И для Amazon, и для Apple диапазон дат здесь одинаковый. Так что рассматривая только Амазонку. - Определение максимальных и минимальных значений
amazon
иapple
сальдо закрытия с помощьюd3.extent.
- узнать минимальное и максимальное значения данных из шага 2. Это необходимо для определения минимальных и максимальных значений оси Y.
- Построение осей x и y с использованием SVG.
- Создание массива переменных
combinedData
, который содержит два значения: данные Apple и Amazon за 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); }
Вышеупомянутая строка кода выполняет следующий набор действий.
- Создайте два пути на основе массива
combinedData
. - Повторение
path._groups[0][0]
и применение линейного перехода длительностью 5 секунд. - Итерируем
path._groups[0][1]
и применяем линейный переход длительностью 5 секунд.
Здесь следует полный набор кода для реализации линейной диаграммы.
Результат приведенного выше фрагмента кода выглядит следующим образом.
В этой статье мы увидели, как сделать базовую анимацию на линейном графике с помощью d3. На официальном сайте D3 вы можете увидеть более сложные примеры графиков d3.