Как я могу переместить график области D3 со значениями ползунка? - PullRequest
0 голосов
/ 13 апреля 2019

У меня есть два комбинированных графика (гистограмма и график площади) на холсте. Чего я хочу добиться, так это, если пользователь перемещает ползунок, график площади меняется в зависимости от этого. На данный момент мои значения хранятся в базе данных Firebase, но я думаю вместо этого жестко их кодировать. Значения ползунка - это, в основном, долларовые значения, которые будут умножаться на постоянный заряд и затем делиться на значение, введенное пользователем. Таким образом, пользователь может переместить ползунок к различным значениям в долларах, которые изменяют график площади.

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

Ссылка на изображение

// select the svg container first
const svg = d3.select('.canvas')
  .append('svg')
  .attr('width', 500)
  .attr('height', 500);

// create margins & dimensions
const margin = {
  top: 20,
  right: 20,
  bottom: 100,
  left: 100
};
const graphWidth = 500 - margin.left - margin.right;
const graphHeight = 500 - margin.top - margin.bottom;

const graph = svg.append('g')
  .attr('width', graphWidth)
  .attr('height', graphHeight)
  .attr('transform', `translate(${margin.left}, ${margin.top})`);

// create axes groups
const xAxisGroup = graph.append('g')
  .attr('transform', `translate(0, ${graphHeight})`)

xAxisGroup.selectAll('text')
  .attr('fill', '#19b393')
  .attr('transform', 'rotate(-40)')
  .attr('text-anchor', 'end');

const yAxisGroup = graph.append('g');

const y = d3.scaleLinear()
  .range([graphHeight, 0]);

const x = d3.scaleBand()
  .range([0, graphWidth])
  .paddingInner(0.2)
  .paddingOuter(0.1);


// create & call axes
const xAxis = d3.axisBottom(x)
  .ticks(6);

const yAxis = d3.axisLeft(y)
  .ticks(3)
  .tickFormat(d => d + ' kWh');

const t = d3.transition().duration(1000);

const line = d3.area()
  .x(function(d) {
    return x(d.month_name)
  })
  .y1(function(d) {
    return y(d.power_production)
  })
  .y0(y(0))


const path = graph.append('path');



// the update function
const update = (data) => {

  // join the data to circs
  const rects = graph.selectAll('rect')
    .data(data)

  const area = graph.selectAll('path')

  rects.exit().remove();

  // update the domains
  y.domain([0, d3.max(data, d => d.power_production)]);
  x.domain(data.map(item => item.month_name));

  area.attr('fill', '#dcdcdc')
    .attr('stroke', '#d3d3d3')
    .attr('stroke-width', 2)
    .attr('d', line(data));

  rects.enter()
    .append('rect')
    .attr('width', x.bandwidth)
    .attr("height", d => 0)
    .attr('fill', '#19b393')
    .attr('x', (d) => x(d.month_name))
    .attr('y', d => graphHeight)
    .merge(rects)
    .transition(t)
    .attr("height", d => graphHeight - y(d.ac_out))
    .attr('y', d => y(d.ac_out));




  xAxisGroup.call(xAxis);
  yAxisGroup.call(yAxis);

};

var data = [];
var ref = '/test1/CafX0cm7FTSaIlT5WcfY/monthly_data/';

db.collection(ref).onSnapshot(res => {

  res.docChanges().forEach(change => {

    const doc = { ...change.doc.data(),
      id: change.doc.id
    };

    switch (change.type) {
      case 'added':
        data.push(doc);
        break;
      case 'modified':
        const index = data.findIndex(item => item.id == doc.id);
        data[index] = doc;
        break;
      case 'removed':
        data = data.filter(item => item.id !== doc.id);
        break;
      default:
        break;
    }

  });

  update(data);

});

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

...