D3.js — это мощная библиотека JavaScript, которая позволяет создавать интерактивные данные визуализаций и диаграммы. Она предоставляет множество возможностей для манипулирования данными и их представления в виде графиков, диаграмм, карт и других визуальных элементов. В этой статье мы подробно разберем процесс создания интерактивных диаграмм с помощью D3.js.
Установка и настройка
Перед началом работы убедитесь, что у вас установлен Node.js и npm. Затем выполните следующие шаги:
- Создайте новую папку для проекта и перейдите в нее:
mkdir d3-project
cd d3-project
- Инициализируйте проект npm:
npm init -y
- Установите D3.js:
npm install d3
- Создайте файл
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>
- Создайте файл
app.js
рядом сindex.html
:
// app.js
console.log("Hello from D3.js!");
Теперь вы готовы начать создание интерактивных диаграмм!
Простой линейный график
Начнем с простого примера — построения линейного графика.
- Откройте файл
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);
- Сохраните изменения и откройте
index.html
в браузере. Вы увидите простой линейный график.
Интерактивность
Теперь добавим немного интерактивности. Например, сделаем так, чтобы при наведении курсора на точку графика появлялась подсказка с ее значением.
- Обновите файл
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);
});
- Добавьте стили для подсказки в файл
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>
- Сохраните изменения и обновите страницу в браузере. Теперь при наведении курсора на точки графика будет появляться подсказка с их значениями.
Дополнительные примеры
Вот еще несколько примеров использования 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>