Многоцелевой полупрозрачный график областей d3js с выводом индикатора при наведении курсора

Вопрос или проблема

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

введите описание изображения здесь

Моя текущая версия — обычные многолинейные графики
https://codesandbox.io/p/sandbox/magical-wiles-forked-wnzkfk

Пример базового графика площадей

<!DOCTYPE html>
<meta charset="utf-8">

<!-- Загружаем d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Создаем див, где будет располагаться график -->
<div id="my_dataviz"></div>

<script>

// устанавливаем размеры и отступы графика
var margin = {top: 10, right: 30, bottom: 30, left: 50},
    width = 460 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

// добавляем объект svg в тело страницы
var svg = d3.select("#my_dataviz")
  .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 + ")");

// Читаем данные
d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv",

  // При чтении csv я должен отформатировать переменные:
  function(d){
    return { date : d3.timeParse("%Y-%m-%d")(d.date), value : d.value }
  },

  // Теперь я могу использовать этот набор данных:
  function(data) {

    // Добавляем ось X --> это формат даты
    var x = d3.scaleTime()
      .domain(d3.extent(data, function(d) { return d.date; }))
      .range([ 0, width ]);
    svg.append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    // Добавляем ось Y
    var y = d3.scaleLinear()
      .domain([0, d3.max(data, function(d) { return +d.value; })])
      .range([ height, 0 ]);
    svg.append("g")
      .call(d3.axisLeft(y));

    // Добавляем площадь
    svg.append("path")
      .datum(data)
      .attr("fill", "#cce5df")
      .attr("stroke", "#69b3a2")
      .attr("stroke-width", 1.5)
      .attr("d", d3.area()
        .x(function(d) { return x(d.date) })
        .y0(y(0))
        .y1(function(d) { return y(d.value) })
        )

})

</script>

Ответ или решение

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

Ниже приведен обновленный пример кода на JavaScript, который реализует такие функции:

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <title>Многослойный полупрозрачный график области</title>
    <script src="https://d3js.org/d3.v6.min.js"></script>
    <style>
        .tooltip {
            position: absolute;
            text-align: center;
            padding: 6px;
            font: 12px sans-serif;
            background: lightsteelblue;
            border: 0px;
            border-radius: 8px;
            pointer-events: none;
        }
    </style>
</head>
<body>
    <div id="my_dataviz"></div>

    <script>
        // Устанавливаем размеры и отступы графика
        var margin = {top: 10, right: 30, bottom: 30, left: 50},
            width = 460 - margin.left - margin.right,
            height = 400 - margin.top - margin.bottom;

        // Создаем SVG элемент
        var svg = d3.select("#my_dataviz")
            .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 + ")");

        // Чтение данных
        d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered_comma.csv").then(function(data) {
            // Форматирование данных
            data.forEach(function(d) {
                d.date = d3.timeParse("%Y-%m-%d")(d.date);
                d.value = +d.value;
            });

            // Установка шкалы оси X
            var x = d3.scaleTime()
                .domain(d3.extent(data, function(d) { return d.date; }))
                .range([0, width]);
            svg.append("g")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x));

            // Установка шкалы оси Y
            var y = d3.scaleLinear()
                .domain([0, d3.max(data, function(d) { return d.value; })])
                .range([height, 0]);
            svg.append("g").call(d3.axisLeft(y));

            // Создаем массив данных для нескольких областей
            var areaData = [
                { color: "#cce5df", name: "Area 1" },
                { color: "#69b3a2", name: "Area 2" }
            ];

            areaData.forEach(function(area, index) {
                // Добавляем область
                svg.append("path")
                    .datum(data)
                    .attr("fill", area.color)
                    .attr("opacity", 0.5)
                    .attr("d", d3.area()
                        .x(function(d) { return x(d.date); })
                        .y0(y(0) + index * 20) // Сдвиг области вниз
                        .y1(function(d) { return y(d.value); })
                    );

                // Добавление события наведения для отображения значений
                svg.selectAll(".dot" + index)
                    .data(data)
                    .enter().append("circle")
                    .attr("class", "dot" + index)
                    .attr("cx", function(d) { return x(d.date); })
                    .attr("cy", function(d) { return y(d.value); })
                    .attr("r", 5)
                    .attr("fill", area.color)
                    .on('mouseover', function(event, d) {
                        tooltip.style("display", "block")
                               .html(area.name + ": " + d.value)
                               .style("left", (event.pageX + 5) + "px")
                               .style("top", (event.pageY - 28) + "px");
                    })
                    .on('mouseout', function() {
                        tooltip.style("display", "none");
                    });
            });

            // Создаем подложку для инструментальной подсказки
            var tooltip = d3.select("body").append("div")
                .attr("class", "tooltip")
                .style("display", "none");
        });
    </script>
</body>
</html>

Объяснение кода:

  1. SVG и размеры: Код создает SVG-элемент и задает его размеры и отступы.
  2. Чтение данных: Данные загружаются из CSV-файла и содержимое столбцов преобразуется в формат, подходящий для D3.js.
  3. Установка осей: X и Y оси настроены для отображения значений.
  4. Области: Создаются две области с различными цветами и полупрозрачностями. Скрипт добавляет сдвиг для каждой области, чтобы они не накладывались друг на друга.
  5. Инструментальная подсказка: При наведении на точки данных отображается подсказка с названием области и соответствующим значением.

Этот пример можно адаптировать для добавления большего числа областей и настройки стилей по вашему усмотрению.

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

Капча загружается...