Создание интерактивных диаграмм с помощью D3.js

D3.js — это мощная библиотека JavaScript, которая позволяет создавать интерактивные данные визуализаций и диаграммы. Она предоставляет множество возможностей для манипулирования данными и их представления в виде графиков, диаграмм, карт и других визуальных элементов. В этой статье мы подробно разберем процесс создания интерактивных диаграмм с помощью D3.js.

Установка и настройка

Перед началом работы убедитесь, что у вас установлен Node.js и npm. Затем выполните следующие шаги:

  1. Создайте новую папку для проекта и перейдите в нее:
mkdir d3-project
cd d3-project
  1. Инициализируйте проект npm:
npm init -y
  1. Установите D3.js:
npm install d3
  1. Создайте файл index.html со следующим содержимым:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>D3.js Interactive Diagram</title>
</head>
<body>
    <div id="chart"></div>
    <script src="node_modules/d3/dist/d3.min.js"></script>
    <script src="app.js"></script>
</body>
</html>
  1. Создайте файл app.js рядом с index.html:
// app.js
console.log("Hello from D3.js!");

Теперь вы готовы начать создание интерактивных диаграмм!

Простой линейный график

Начнем с простого примера — построения линейного графика.

  1. Откройте файл app.js и добавьте следующий код:
// app.js
const data = [10, 20, 30, 40, 50];

const svgWidth = 500, svgHeight = 300;
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = svgWidth - margin.left - margin.right;
const height = svgHeight - margin.top - margin.bottom;

const svg = d3.select("#chart")
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`);

const xScale = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, width]);

const yScale = d3.scaleBand()
    .domain(d3.range(data.length))
    .rangeRound([0, height])
    .paddingInner(0.05);

const lineGenerator = d3.line()
    .x((d, i) => xScale(i))
    .y(yScale);

svg.append("path")
    .datum(data)
    .attr("fill", "none")
    .attr("stroke", "steelblue")
    .attr("stroke-width", 1.5)
    .attr("d", lineGenerator);
  1. Сохраните изменения и откройте index.html в браузере. Вы увидите простой линейный график.

Интерактивность

Теперь добавим немного интерактивности. Например, сделаем так, чтобы при наведении курсора на точку графика появлялась подсказка с ее значением.

  1. Обновите файл app.js следующим образом:
// app.js
const data = [10, 20, 30, 40, 50];

const svgWidth = 500, svgHeight = 300;
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = svgWidth - margin.left - margin.right;
const height = svgHeight - margin.top - margin.bottom;

const svg = d3.select("#chart")
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`);

const xScale = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, width]);

const yScale = d3.scaleBand()
    .domain(d3.range(data.length))
    .rangeRound([0, height])
    .paddingInner(0.05);

const lineGenerator = d3.line()
    .x((d, i) => xScale(i))
    .y(yScale);

svg.append("path")
    .datum(data)
    .attr("fill", "none")
    .attr("stroke", "steelblue")
    .attr("stroke-width", 1.5)
    .attr("d", lineGenerator);

const tooltip = d3.select("body").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);

svg.selectAll(".dot")
    .data(data)
    .enter().append("circle")
    .attr("class", "dot")
    .attr("cx", (d, i) => xScale(i))
    .attr("cy", yScale)
    .attr("r", 5)
    .on("mouseover", function(event, d) {
        tooltip.transition()
            .duration(200)
            .style("opacity", 0.9);
        tooltip.html(d)
            .style("left", event.pageX + "px")
            .style("top", event.pageY + "px");
    })
    .on("mouseout", () => {
        tooltip.transition()
            .duration(500)
            .style("opacity", 0);
    });
  1. Добавьте стили для подсказки в файл index.html:
<style> .tooltip { position: absolute; text-align: center; padding: 5px; font-size: 12px; background-color: white; border: 1px solid #ddd; pointer-events: none; opacity: 0; } </style>
  1. Сохраните изменения и обновите страницу в браузере. Теперь при наведении курсора на точки графика будет появляться подсказка с их значениями.

Дополнительные примеры

Вот еще несколько примеров использования D3.js для создания интерактивных диаграмм:

Гистограмма

// app.js
const data = [10, 20, 30, 40, 50];

const svgWidth = 500, svgHeight = 300;
const margin = { top: 20, right: 20, bottom: 30, left: 40 };
const width = svgWidth - margin.left - margin.right;
const height = svgHeight - margin.top - margin.bottom;

const svg = d3.select("#chart")
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`);

const xScale = d3.scaleBand()
    .domain(d3.range(data.length))
    .rangeRound([0, width])
    .paddingInner(0.05);

const yScale = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([height, 0]);

svg.selectAll(".bar")
    .data(data)
    .enter().append("rect")
    .attr("class", "bar")
    .attr("x", (d, i) => xScale(i))
    .attr("y", d => yScale(d))
    .attr("width", xScale.bandwidth())
    .attr("height", d => height - yScale(d));

Круговая диаграмма

// app.js
const data = [10, 20, 30, 40, 50];

const svgWidth = 400, svgHeight = 400;
const radius = Math.min(svgWidth, svgHeight) / 2;

const color = d3.scaleOrdinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);

const pie = d3.pie()
    .value(d => d);

const arc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(0);

const labelArc = d3.arc()
    .outerRadius(radius - 40)
    .innerRadius(radius - 40);

const svg = d3.select("#chart")
    .append("svg")
    .attr("width", svgWidth)
    .attr("height", svgHeight)
    .append("g")
    .attr("transform", `translate(${svgWidth / 2}${svgHeight / 2})`);

const g = svg.selectAll(".arc")
    .data(pie(data))
    .enter().append("g")
    .attr("class", "arc");

g.append("path")
    .attr("d", arc)
    .style("fill", (d, i) => color(i));

g.append("text")
    .attr("transform", d => `translate(${labelArc.centroid(d)})`)
    .attr("dy", ".35em")
    .text(d => `${d.data}`);

Эта статья дала общее представление о возможностях D3.js для создания интерактивных диаграмм. Хотя мы рассмотрели лишь базовые примеры, D3.js обладает огромным потенциалом для реализации сложных и красивых визуализаций. Надеюсь, эта информация станет отправной точкой для дальнейшего изучения и экспериментов с библиотекой.


Пример гистограммы, созданный с помощью D3.js, в одном HTML-файле:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Гистограмма с D3.js</title>
    <style>
        body {
            font-family: Arial, sans-serif;
        }
        
        .bar {
            fill: steelblue;
        }
        
        .axis path,
        .axis line {
            fill: none;
            stroke: black;
            shape-rendering: crispEdges;
        }
    </style>
</head>
<body>
    <div id="chart"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
    <script>
        // Данные для гистограммы
        const data = [10, 20, 30, 40, 50];

        // Размеры диаграммы
        const svgWidth = 500, svgHeight = 300;
        const margin = { top: 20, right: 20, bottom: 30, left: 40 };
        const width = svgWidth - margin.left - margin.right;
        const height = svgHeight - margin.top - margin.bottom;

        // Создание SVG-контейнера
        const svg = d3.select("#chart")
            .append("svg")
            .attr("width", svgWidth)
            .attr("height", svgHeight)
            .append("g")
            .attr("transform", `translate(${margin.left},${margin.top})`);

        // Масштабирование осей
        const xScale = d3.scaleBand()
            .domain(d3.range(data.length))
            .rangeRound([0, width])
            .paddingInner(0.05);

        const yScale = d3.scaleLinear()
            .domain([0, d3.max(data)])
            .range([height, 0]);

        // Оси
        const xAxis = d3.axisBottom(xScale);
        const yAxis = d3.axisLeft(yScale);

        // Рисование столбцов
        svg.selectAll(".bar")
            .data(data)
            .enter().append("rect")
            .attr("class", "bar")
            .attr("x", (d, i) => xScale(i))
            .attr("y", d => yScale(d))
            .attr("width", xScale.bandwidth())
            .attr("height", d => height - yScale(d));

        // Добавление осей
        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", `translate(0,${height})`)
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis);
    </script>
</body>
</html>

Пример круговой диаграммы (пирога), созданной с помощью D3.js, в одном HTML-файле:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Круговая диаграмма с D3.js</title>
    <style>
        body {
            font-family: Arial, sans-serif;
        }
        
        .arc text {
            font-size: 12px;
            fill: #333;
        }
    </style>
</head>
<body>
    <div id="chart"></div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
    <script>
        // Данные для круговой диаграммы
        const data = [10, 20, 30, 40, 50];

        // Размеры диаграммы
        const svgWidth = 400, svgHeight = 400;
        const radius = Math.min(svgWidth, svgHeight) / 2;

        // Цветовая шкала
        const color = d3.scaleOrdinal()
            .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);

        // Генерация пирога
        const pie = d3.pie()
            .value(d => d);

        // Дуги
        const arc = d3.arc()
            .outerRadius(radius - 10)
            .innerRadius(0);

        // Позиционирование меток
        const labelArc = d3.arc()
            .outerRadius(radius - 40)
            .innerRadius(radius - 40);

        // Создание SVG-контейнера
        const svg = d3.select("#chart")
            .append("svg")
            .attr("width", svgWidth)
            .attr("height", svgHeight)
            .append("g")
            .attr("transform", `translate(${svgWidth / 2}, ${svgHeight / 2})`);

        // Генерируем дуги
        const arcs = pie(data);

        // Рисуем дуги
        svg.selectAll(".arc")
            .data(arcs)
            .enter().append("g")
            .attr("class", "arc")
            .each(function(d, i) {
                d3.select(this).append("path")
                    .attr("d", arc)
                    .style("fill", color(i));
                
                d3.select(this).append("text")
                    .attr("transform", d => `translate(${labelArc.centroid(d)})`)
                    .attr("dy", ".35em")
                    .text(d => `${d.data}`);
            });
    </script>
</body>
</html>

Добавить комментарий

Войти с помощью: