Обновить ось y диаграммы области щеткой

17

Я использую d3.js, и я работаю над графикой в ​​матовой области, изменив этот пример . В дополнение к изменению оси x, основанной на кисти, я хотел бы перерисовать ось y на основе значений y, которые попадают в кисть (аналогично поведению график Google Finance ).

Я получил функциональность, но только так, чтобы позволить кисти рисоваться как в x, так и в у-пространстве. Я сделал это, сначала добавив масштаб y к переменной brush :

var brush = d3.svg.brush()
    .x(x2)
    .y(y2)
    .on("brush", brush);

Это делает brush.extent() возвращением следующего многомерного массива: [ [x0, y0], [x1, y1] ] . Затем я использую эти данные в функции brush() , чтобы переопределить x- и y-домен для диаграммы фокуса:

function brush() {
  var extent = brush.extent();
  x.domain(brush.empty() ? x2.domain() : [ extent[0][0], extent[1][0] ]);
  y.domain(brush.empty() ? y2.domain() : [ extent[0][1], extent[1][1] ]);
  focus.select("path").attr("d", area);
  focus.select(".x.axis").call(xAxis);
  focus.select(".y.axis").call(yAxis);
}

Это работает, но, определяя масштаб y в переменной щетки, пользователь теперь может перетаскивать «квадратики» на диаграмме фокуса, а не только перетаскивать с запада на восток, как в исходной диаграмме.

По существу, мой вопрос: как мне получить диапазон значений, попадающих в область кисти, а не в область самой области кисти? Возможно ли это?

Документация щетки

d3 здесь .

    
задан Sam Selikoff 20.12.2012 в 16:19
источник

2 ответа

13

Я придумал решение.

Я использовал фильтр x.domain, отфильтрованный кистью, для фильтрации моего исходного набора данных. Этот новый фильтрованный набор данных имеет только значения, которые попадают в кисть:

// Use x.domain to filter the data, then find the max and min duration of this new set, then set y.domain to that
  x.domain(brush.empty() ? x2.domain() : brush.extent());
  var dataFiltered = data.filter(function(d, i) {
    if ( (d.date >= x.domain()[0]) && (d.date <= x.domain()[1]) ) {
      return d.duration;
    }
  })
  y.domain([0, d3.max(dataFiltered.map(function(d) { return d.duration; }))]);

Наконец, обязательно перерисуйте ось y, а также ось x:

focus.select("path").attr("d", area);
focus.select(".x.axis").call(xAxis);
focus.select(".y.axis").call(yAxis);
    
ответ дан Sam Selikoff 21.12.2012 в 01:06
  • Отличный ответ! Был в состоянии упасть прямо в код моей диаграммы, ура. –  fundead 23.08.2013 в 01:03
0

Более короткая возможность заключалась бы в использовании d3.scale.invert() на вашем brush.extent() :

var domainExtent = brush.extent().map(function(d){return scale.invert(d);});
var filteredData = data.filter(function(d){return ((d <= domainExtent[1]) && (d >= domainExtent[0]));});

Однако , к настоящему времени d3 получил d3.brushX() , что позволяет чистка в восточном / западном направлении по дизайну.

    
ответ дан nick 11.08.2017 в 14:35