D3. js V5 - Создание сгруппированной положительной и отрицательной гистограммы для отраслевых данных - PullRequest
0 голосов
/ 04 мая 2020

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

... и более пристальный взгляд ... enter image description here

Данные всплывающей подсказки поступают из массива с 6 значениями, также есть массив, содержащий 6 целочисленных значений со средними данными по миру. Среднемировые данные можно найти в массиве worldAvg. Например, скажем, средние мировые показатели: [-20, -30, -40, -10,10,20].

Как мне изменить текущую реализацию, чтобы сравнить уменьшение увеличения сектора по сравнению с мировым среднее увеличение уменьшается? Я полагаю, что средние мировые данные могут быть окрашены в красный цвет, например. Я бы sh реализовал что-то вроде следующего графика, но с разными цветными полосами и с отрицательными значениями:

enter image description here

так, например, гистограмма будет показывать увеличение и уменьшение розничных% страны, помимо увеличения и уменьшения% в мире, а затем будет немного места для группировки этих данных, а затем увеличение продуктовых% ... et c .

Любая помощь будет оценена. Я всего лишь новичок D3 ie и просто пытаюсь с этим смириться. Это текущий код:

  // draw maps and tooltips
  const drawMap = (svg, geoJson, geoPath, covid, key, impact) => {
    // clear svgs
    svg.select('g').remove();

    const g = svg.append('g');
    g
      .selectAll('path')
      .data(geoJson.features)
      .enter()
      .append('path')
      .attr('d', geoPath)
      .attr('class', (d) => {
        const mobilityData = covid.data[d.properties[key]] || {};
        const { leastHitName, mostHitName } = getData(mobilityData);
        const filterType = getFilterType(impact);
        if (filterType === 'least-impacted') {
          return `county ${leastHitName}`;
        }
        return `county ${mostHitName}`;
      })
      .on('mouseover', ({ properties }) => {
        // get county data
        const mobilityData = covid.data[properties[key]] || {};


        //GET AVERAGES - IMPLEMENT LATER
      // const {
      //   retailAverage,
      //   groceryAverage,
      //   parksAverage,
      //   transitAverage,
      //   workplaceAverage,
      //   residentialAverage,
      // } = getAverage(covid1);
      //

        //Theoretical averages for testing
      let avgArray = [-20,-30,-40,-10,10,20];

        // create tooltip
        div = d3.select('body')
          .append('div')
          .attr('class', 'tooltip')
          .style('opacity', 0);

        div.html(properties[key]);

        div.transition()
          .duration(200)
          .style('opacity', 0.9);

        // calculate bar graph data for tooltip
        const barData = [];

        Object.keys(mobilityData).forEach((industry) => {
          const stringMinusPercentage = mobilityData[industry].slice(0, -1);
          barData.push(+stringMinusPercentage); // changing it to an integer value, from string
        });
        // barData = barData.sort(function (a, b) {  return a - b;  });
        // sort into ascending ^ keeping this in case we need it later
        const height2 = 220;
        const width2 = 250;
        const margin = {
          left: 50, right: 10, top: 20, bottom: 15,
        };

        // create bar chart svg
        const svgA = div.append('svg')
          .attr('height', height2)
          .attr('width', width2)
          .style('border', '1px solid')
          .append('g')
        // apply the margins:
          .attr('transform', `translate(${[`${margin.left},${margin.top}`]})`);

        const barWidth = 30; // Width of the bars

        // plot area is height - vertical margins.
        const chartHeight = height2 - margin.top - margin.left;

        // set the scale:
        const yScale = d3.scaleLinear()
          .domain([-100, 100])
          .range([chartHeight, 0]);

        // draw some rectangles:
        svgA
          .selectAll('rect')
          .data(barData)
          .enter()
          .append('rect')
          .attr('x', (d, i) => i * barWidth)
          .attr('y', (d) => {
            if (d < 0) {
              return yScale(0); // if the value is under zero, the top of the bar is at yScale(0);
            }

            return yScale(d); // otherwise the rectangle top is above yScale(0) at yScale(d);
          })
          .attr('height', (d) => Math.abs(yScale(0) - yScale(d))) // the height of the rectangle is the difference between the scale value and yScale(0);
          .attr('width', barWidth)
          .style('fill', (d, i) => colours[i % 6]) // colour the bars depending on index
          .style('stroke', 'black')
          .style('stroke-width', '1px');

        // Labelling the Y axis
        const yAxis = d3.axisLeft(yScale);
        svgA.append('text')
          .attr('class', 'y label')
          .attr('text-anchor', 'end')
          .attr('x', -15)
          .attr('y', -25)
          .attr('dy', '-.75em')
          .attr('transform', 'rotate(-90)')
          .text('Percentage Change (%)');

        svgA.append('g')
          .call(yAxis);
      })
      .on('mouseout', () => {
        div.style('opacity', 0);
        div.remove();
      })
      .on('mousemove', () => div
        .style('top', `${d3.event.pageY - 140}px`)
        .style('left', `${d3.event.pageX + 15}px`));

    svg.append('g')
      .attr('transform', 'translate(25,25)')
      .call(colorLegend, {
        colorScale,
        circleRadius: 10,
        spacing: 30,
        textOffset: 20,
      });
  };

  drawMap(svg1, geoJson1, geoPath1, covid1, key1, 'impact1');
  drawMap(svg2, geoJson2, geoPath2, covid2, key2, 'impact2');
};


Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...