Столбчатая диаграмма с накоплением и общим шаблоном обновления d3.js

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

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

const margin = {top: 10, right: 30, bottom: 20, left: 50},
    width = 800 - margin.left - margin.right,
    height = 600 - margin.top - margin.bottom;

// append the svg object to the body of the page
const svg = d3.select("#chart")
    .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})`);

// Parse the Data
d3.csv("https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_stacked.csv").then( function(data) {

// List of subgroups = header of the csv files = soil condition here
const subgroups = data.columns.slice(1)

// List of groups = species here = value of the first column called group -> I show them on the X axis
const groups = data.map(d => (d.group))

// Add X axis
const x = d3.scaleBand()
    .domain(groups)
    .range([0, width])
    .padding([0.2])
svg.append("g")
    .attr("transform", `translate(0, ${height})`)
    .call(d3.axisBottom(x).tickSizeOuter(0));

// Add Y axis
const y = d3.scaleLinear()
    .domain([0, 60])
    .range([ height, 0 ]);
svg.append("g")
    .call(d3.axisLeft(y));

// color palette = one color per subgroup
const color = d3.scaleOrdinal()
    .domain(subgroups)
    .range(['#e41a1c','#377eb8','#4daf4a'])

//stack the data? --> stack per subgroup
const stackedData = d3.stack()
    .keys(subgroups)
    (data)

// Show the bars
let bars = svg.append("g")
    .selectAll("g")
    .data(stackedData, d => d)

    bars.join(
    enter => {
        enter
        .append('g')
        .attr("fill", d => color(d.key))
        .selectAll("rect")
        .data(d=>d)
        .attr("x", d => x(d.data.group))
        .attr("y", d => y(d[1]))
        .attr("height", d => y(d[0]) - y(d[1]))
        .attr("width",x.bandwidth())
}, update => update, exit => exit.remove());
})

Я изменил код только после //Показать полосы

Работает, если вместо join(enter=> enter)

Я использую только enter().append('g)... и т.д. Я думал, что они делают то же самое?

Наконец, я пытался рисовать все напрямую из D3. Глупо делать это самому вместо того, чтобы использовать готовые функции из таких мест, как Observable? Я хочу учиться, но я также хочу быть эффективным.

спасибо за любые советы и помощь!

Ваши переменные bar содержат около g элементов, не выбирайте прямоугольники на входной части. Вы также привязываете прямое выделение к данным, но никогда не добавляете их на диаграмму (вводите часть). Обновляющая и выходная часть соединения снова будет иметь дело только с элементами g. Не будет обновлять прямоугольники внутри. Просто выполните объединение для g элементов, а затем отдельное для прямоугольников.

Carlos Moura 09.04.2022 19:04

Спасибо @CarlosMoura. Я был довольно смущен этим, я несколько раз переименовывал это, вместе с отличным ответом ниже я наконец понял, что я делал неправильно. Спасибо еще раз!

Olli 09.04.2022 20:33
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
0
2
19
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Вам нужно вернуть выбор enter (вы используете функцию стрелки, ничего не возвращая из нее)
  2. Вам нужно сделать .join('rect') после selectAll('rect').data(d => d) (если вы не присоединитесь, ничего не будет добавлено в стек <g>)

Вот полное рабочее решение (нажмите кнопку Выполнить фрагмент кода ниже):

const margin = {
    top: 10,
    right: 30,
    bottom: 20,
    left: 50
  },
  width = 800 - margin.left - margin.right,
  height = 600 - margin.top - margin.bottom;

// append the svg object to the body of the page
const svg = d3
  .select("#chart")
  .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})`);

// Parse the Data
d3.csv(
  "https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/data_stacked.csv"
).then(function(data) {
  // List of subgroups = header of the csv files = soil condition here
  const subgroups = data.columns.slice(1);

  // List of groups = species here = value of the first column called group -> I show them on the X axis
  const groups = data.map((d) => d.group);

  // Add X axis
  const x = d3.scaleBand().domain(groups).range([0, width]).padding([0.2]);
  svg
    .append("g")
    .attr("transform", `translate(0, ${height})`)
    .call(d3.axisBottom(x).tickSizeOuter(0));

  // Add Y axis
  const y = d3.scaleLinear().domain([0, 60]).range([height, 0]);
  svg.append("g").call(d3.axisLeft(y));

  // color palette = one color per subgroup
  const color = d3
    .scaleOrdinal()
    .domain(subgroups)
    .range(["#e41a1c", "#377eb8", "#4daf4a"]);

  //stack the data? --> stack per subgroup
  const stackedData = d3.stack().keys(subgroups)(data);

  // Show the bars
  let bars = svg
    .append("g")
    .selectAll("g")
    .data(stackedData, (d) => d);

  bars.join(
    (enter) => {
      // don't forget to return the enter selection after appending 
      return enter
        .append("g")
        .attr("fill", (d) => color(d.key))
        .selectAll("rect")
        .data((d) => d)
        // don't forget to join 'rect'
        .join("rect")
        .attr("x", (d) => x(d.data.group))
        .attr("y", (d) => y(d[1]))
        .attr("height", (d) => y(d[0]) - y(d[1]))
        .attr("width", x.bandwidth());
    },
    (update) => update,
    (exit) => exit.remove()
  );
});
<div id="chart"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.4.3/d3.min.js"></script>

Другие вопросы по теме