d3.биссектриса в нисходящем массиве

#javascript #d3.js

#javascript #d3.js

Вопрос:

Я создаю простую линейную диаграмму D3, и у меня возникли проблемы с созданием всплывающей подсказки с d3.bisector() функцией. Я ищу, чтобы она переходила к осям Y и X для каждого значения. Функция bisector отлично работает для предоставления мне значения xData, соответствующего координатам мыши, но я продолжаю получать некоторые очень странные результаты для yData. Я подозреваю, что проблема заключается в нисходящем характере массива yData. Есть ли способ настроить bisector() функцию для обработки нисходящих массивов? Я ищу решение, которое работало бы с любым набором данных.

 //define the domain and range for the chart
var xScale =  d3.scaleLinear().domain([0,10]).range([0, width]);
var yScale =  d3.scaleLinear().domain([0,10]).range([height,0]);

//data for the line
var xData = [0,1,2,3,4,5,6,7,8,9,10];
var yData = [10,9,8,7,6,5,4,3,2,1,0];

//set up the  bisector function
var bisectData= d3.bisector(function(d){return d}).left;

 // get the x and y position of the cursor and put it into the Xscale/yScale function to get the correct X and Y values from the corresponding coordinates
var x0 = xScale.invert(d3.mouse(this)[0])
var y0 = yScale.invert(d3.mouse(this)[1])

//round the values to the nearest integer to match the original data
var x0 = Math.round(x0);
var y0 = Math.round(y0);

//get the correct index value of the relevant data array
var xIndex= bisectData(xData,x0,1);
//get the actual value from the original array using the correct index

//this work fine 
var x1 = xData[xIndex];

//this does not
var yIndex= bisectData(yData,y0,1);
var y1 = yData[yIndex];
  

Ответ №1:

В документации по d3.bisector() вы уже все рассмотрели (выделено мной):

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

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

 d3.bisector((d, x) => x - d).left
//              ^--- Search value
  

Взгляните на следующую рабочую демонстрацию:

 const yData = [10,9,8,7,6,5,4,3,2,1,0];

const descBisector = d3.bisector((d, x) => x - d).left;
const yIndex = descBisector(yData, 2);

console.log(yIndex);  
 <script src="https://d3js.org/d3.v5.js"></script>