D3.js Элементы управления кистью: ширина эквалайзера, координаты

Я использую d3.js, и мне было интересно, как я могу получить стороны, ширину, координаты и т.д.; от степени. В примере, подобном этому http://bl.ocks.org/mbostock/1667367

Ответ 1

Brush.extent()

При использовании элемента управления щеткой вы получаете доступ к информации о состоянии кисти с помощью метода .extent() объекта щетки.

Информация, возвращаемая методом .extent(), зависит от того, какой масштаб вы подключили к объекту кисти.

Если у вас есть одна связанная шкала (либо шкала X, либо шкала Y, но не оба), метод степени возвращает двухэлементный массив формы [minimum, maximum].

Если у вас есть и масштаб X и Y, прикрепленный к объекту кисти, то метод степени возвращает вложенный массив формы [‍​[xMinimum, yMinimum], [xMaximum, yMaximum]​].

Но каковы эти минимальные и максимальные значения? Это также зависит от масштаба. Если масштаб имеет действительный метод .invert(value), минимальные и максимальные значения будут преобразованы в значения ваших данных. Для порядковых, пороговых и других шкал, которые не имеют простого метода invert, функция щетки возвращает значения в системе координат, действующей для элемента щетки.

1. Одномерная кисть

Чтобы ответить на ваш вопрос для конкретного примера, с которым вы связались, нам нужно посмотреть объект кисти и масштабировать объекты. В этом примере кисть подключается к горизонтальной шкале на более мелкой "контекстной" диаграмме (шкала x2):

var x = d3.time.scale().range([0, width]),
    x2 = d3.time.scale().range([0, width]),
    y = d3.scale.linear().range([height, 0]),
    y2 = d3.scale.linear().range([height2, 0]);

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

инициализация кисти

Созданный выше объект кисти существует только в Javascript, а не в документе. Тем не менее, объект также является функцией, которая может быть вызвана (подобно функциям оси), чтобы создать серию прямоугольников, которые будут реагировать на события мыши (они невидимы) и один прямоугольник "протяженность" (который в этом примере окрашен в серый цвет с белой рамкой).

context.append("g")
  .attr("class", "x brush")
  .call(brush)  //call the brush function, causing it to create the rectangles
.selectAll("rect") //select all the just-created rectangles
  .attr("y", -6)
  .attr("height", height2 + 7); //set their height

Размер невидимых прямоугольников по умолчанию основан на диапазоне выходных значений шкалы X и Y. Поскольку эта кисть не имеет шкалы Y, постоянная высота и вертикальное положение прямоугольников должны быть заданы явно.

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

взаимодействие с кистями

Когда пользователь взаимодействует с кистью на экране, объект щетки захватывает эти события и (1) обновляет ширину прямоугольника "степень", (2) вызывает функцию, связанную с событием "щетка" в line .on("brush", brushed).

Функция brushed():

function brushed() {
  x.domain(brush.empty() ? x2.domain() : brush.extent());
  focus.select(".area").attr("d", area);
  focus.select(".x.axis").call(xAxis);
}

Цель этой кисти - масштабировать основную диаграмму, и это делается путем установки домена основной шкалы X-шкалы. Если кисть имеет нулевую ширину, brush.empty() возвращает true, а основной X-домен диаграммы установлен в полный домен, показанный на небольшой диаграмме.

Однако, если кисть имеет допустимую ширину, пустой тест возвращает false, а для домена задаются результаты brush.extent(). Поскольку кисть привязана к линейной шкале X и не имеет шкалы Y, объем возвращается в форме [xMin, xMax] (в номерах данных), что является именно тем, что необходимо для настройки домена.

Извлечение значений из кисти

Если вам нужно знать ширину в значениях данных, это просто вопрос вычитания:

var extent = brush.extent(); //returns [xMin, xMax]
var width = extent[1] - extent[0]; //data-width = max - min

Однако, если вы рисуете другие элементы на экране, вы хотите знать фактические координаты в SVG, а не только значения данных. Чтобы сделать преобразование, вы используете ту же самую вещь, которую всегда используете для преобразования из данных в координаты SVG: ваша функция масштабирования. Помните, что использовать шкалу x2, которая управляет маленькой диаграммой, а не масштаб масштабирования основной диаграммы, которая будет выглядеть так:

var extent = brush.extent(); //returns [xMin, xMax]
var rangeExtent = [x2( extent[0] ), x2( extent[1] ) ]; //convert
var rangeWidth  = rangeExtent[1] - rangeExtent[0];

2. X и Y щетка

Для повторного подчеркивания этот пример предназначен для кисти с одной (горизонтальной/Х) шкалой, которая является линейной шкалой. Если вы использовали линейные шкалы X и Y, вам нужно было бы выделить значения степени X и Y с помощью кода следующим образом:

function brushed() {

  if (brush.empty()) {
      //either the height OR the width is empty
      x.domain( x2.domain() ); //reset X scale
      y.domain( y2.domain() ); //reset Y scale
  }

  var extent = brush.extent();
  x.domain( [extent[0][0] , extent[1][0] ] ); //min and max data X values
  y.domain( [extent[0][1] , extent[1][1] ] ); //min and max data Y values

  var rangeExtent = [
          [x2(extent[0][0]), y2(extent[0][1])],
          [x2(extent[1][0]), y2(extent[1][1])]
       ];
  var rangeWidth  = rangeExtent[1][0] - rangeExtent[0][0];
  var rangeHeight = rangeExtent[1][1] - rangeExtent[0][1];


  focus.select(".area").attr("d", area);
  focus.select(".x.axis").call(xAxis);
  focus.select(".y.axis").call(yAxis);
}

Извлечение значений из кисти

Если вы хотите знать координаты верхней левой части прямоугольника, вам также нужно знать, переключает ли ваша шкала Y минимальное значение сверху вниз.

В качестве альтернативы вы можете получить ширину, высоту и верхнюю левую координату из прямоугольника "экстент" на экране, который изменяет объект кисти:

function brushed() {

  //use the brush object values to set the data domains:
  if (brush.empty()) {
      //either the height OR the width is empty
      x.domain( x2.domain() ); //reset X scale
      y.domain( y2.domain() ); //reset Y scale
  }

  var extent = brush.extent();
  x.domain( [extent[0][0] , extent[1][0] ] ); //min and max data X values
  y.domain( [extent[0][1] , extent[1][1] ] ); //min and max data Y values

  //use the brush extent rectangle to get the SVG coordinates:
  var extentRect = d3.select("g.x.brush rect.extent");

  var rangeWidth  = extentRect.attr("width");
  var rangeHeight = extentRect.attr("height");
  var rangeLeft = extentRect.attr("x");
  var rangeTop = extentRect.attr("y");


  focus.select(".area").attr("d", area);
  focus.select(".x.axis").call(xAxis);
  focus.select(".y.axis").call(yAxis);
}

Если вы используете порядковые масштабы, это сложнее для масштабирования, но менее сложно найти координаты экрана. Этот ответ описывает, как использовать кисть с порядковой шкалой для масштабирования, Однако, поскольку значения, возвращаемые .extent(), уже находятся в координатах SVG, вам не нужно будет использовать сам масштаб для преобразования обратно, если вы хотите, чтобы координаты и ширина

Ссылки

Страница API для управления кистью содержит набор миниатюр в верхней части страницы; нажмите на любой из них, чтобы открыть рабочий пример. Для дальнейшего обсуждения вас может заинтересовать этот учебник с еще одним хорошим примером кистей в действии.