Графики обновляются только тогда, когда я пишу enter () в конце - PullRequest
2 голосов
/ 02 августа 2020

Я попытался переключить данные с помощью d3.interval и отобразить данные в виде гистограмм на моем svg.

Как показано ниже.

interval -

d3.interval(function(){update(data);
                       flag =! flag;
                      },1000)  

рендеринг -

function update(input){
    
    var value = flag ? 'revenue':'profit'


    x.domain(input.map(function(d){return d.month}));
    y.domain([0,d3.max(input, function(d){return d[value]})])

    var xAxisCall = d3.axisBottom(x);
    var yAxisCall = d3.axisLeft(y).tickFormat(function(d){return '$'+d})
    
    xAxisGroup.call(xAxisCall.tickSizeOuter(0))
    yAxisGroup.call(yAxisCall.tickSizeOuter(0))

    var rects = svg.selectAll('rect').data(data)

    rects.exit().remove()


    
    rects.enter().append('rect').attr('y', (d)=>{return height-y.range([0,height])(d[value])})
                 .attr('x', (d)=>{ return 50+x(d.month)})
                 .attr('height',(d)=>{return y(d[value])})
                 .attr('width',x.bandwidth())
                 .attr('fill','grey')
                 
    }

Однако он не переключает график в зависимости от данных, введенных в прямоугольники. Это сработало только тогда, когда я поместил .append () в конец рендеринга прямоугольника, как показано ниже.

rects.attr('y', (d)=>{return height-y.range([0,height])(d[value])})
             .attr('x', (d)=>{ return 50+x(d.month)})
             .attr('height',(d)=>{return y(d[value])})
             .attr('width',x.bandwidth())
             .attr('fill','grey')
             .enter().append('rect')

Почему мне нужно добавить ввод и добавить в конце? Причина, по которой я этого не понимаю, заключается в том, что даже если я поставлю .enter (). Append ('rect') в начале, свойства прямоугольника можно переопределить и обновить.

Однако свойства прямоугольников не были обновлены после того, как я заранее ввел аргумент enter ().

Я проверил, добавив console.log, как показано ниже.

rects.enter().append('rect').attr('fill',function(){return flag? "rgba(100,0,0,0.2)":'rgba(0,100,0,0.2)'}).attr('y', (d)=>{return height-y.range([0,height])(d[value])})
             .attr('x', (d)=>{ return 50+x(d.month)})
             .attr('height',(d)=>{console.log(d[value])
                                  ;return y(d[value])})
             .attr('width',x.bandwidth())

Это не записывать что-нибудь, он записывается только тогда, когда я помещаю ввод в конец.

Почему не запускаются все аргументы?

Ответы [ 2 ]

3 голосов
/ 02 августа 2020

В первом случае у вас есть выбор введите , но ничего не меняет ваш выбор обновления. Во втором случае вы меняете свой выбор update , ничего не делая с вашим выбором ввода.

Напишите свои update и введите выбор четко и отдельно. Обычно это приводит к дублированию кода ... если вам не нравятся эти дублирования, используйте merge():

var rects = svg.selectAll('rect').data(data)

rects.exit().remove()

rects = rects.enter()
  .append('rect')
  .attr('fill', 'grey')
  .merge(rects)
  .attr('y', (d) => {
    return height - y.range([0, height])(d[value])
  })
  .attr('x', (d) => {
    return 50 + x(d.month)
  })
  .attr('height', (d) => {
    return y(d[value])
  })
  .attr('width', x.bandwidth())
1 голос
/ 02 августа 2020

D3 использует соединение данных, которое не действует напрямую на элементы, а описывает их преобразования. Когда вы делаете:

var rects = svg.selectAll('rect').data(data)

, вы выбираете не все прямоугольники, а только те, которые находятся в выделении «обновить». Вот более подробное объяснение автора D3.

В настоящее время рекомендуется использовать метод selection.join(), который делает код на основе выбора более понятным:

svg.selectAll('rect')
  .data(data)
  .join(
    enter => enter.append('rect')
      .attr('fill', 'grey'),
    update => update
      .attr('x', (d) => 50 + x(d.month))
      .attr('y', (d) => height-y.range([0,height])(d[value]))
      .attr('width', x.bandwidth())
      .attr('height', (d) => y(d[value])),
    exit => exit.remove()
   )
...