Библиотека D3 неправильно преобразует значение (React Native)

#javascript #react-native #d3.js

#javascript #react-native #d3.js

Вопрос:

У меня есть гистограмма, которая отображает продолжительность времени, однако столбцы отображаются неточно. Например: общая продолжительность составляет 1 час 05 минут, что равно значению 1.0757. Когда я вызываю функцию d3 для общей продолжительности: d3.scaleLinear().range([0,height]).domain([min,max]) , она возвращает значение 31.8486, в результате чего линия гистограммы выглядит так, как будто она отображает 30 минут против более часа.

Что нужно переключить, чтобы убедиться, что гистограмма отображает данные правильно?

 let h = 200;
let y = this.getDomainAndRange(data, h);

let displayOrder = [
  0: {dayName: "Sunday", totalDuration: {value: 2.6707, display: "2h 40m"},
  1: {dayName: "Monday", totalDuration: {value: 1.0757, display: "1h 5m"},
  2: {dayName: "Tuesday", totalDuration: {value: 1.562, display: "1h 34m"}
]
// Once d3 is called on the totalDuration[value], it returns:
// 0: 200 (appears on the screen as 3h), 
// 1: 31.8486 (appears on the screen as 30m),
// 2: 83.116335 (appears on the screen as 1h 10m)

<Svg>
displayOrder.map((wd, idx) => {
   let barHeight = this.getDayDurationHeight(data, wd, y);
   let actualDuration = this.getActualDuration(data, wd)
   return (
    <G key={data["start"]   "g_"   idx}>
      <Rect key={data["start"]   "wdb_"   idx} id={actualDuration} x={(idx   1) * 45} width={bw} y={h - barHeight} height={barHeight} fill={purple} />
    </G>
   );
})
</Svg>
 
 getDomainAndRange(data, height) {
 //iterate through each day and find the min and max value...
 let days = data["days"];
 let min = Number.MAX_SAFE_INTEGER;
 let max = Number.MIN_SAFE_INTEGER;
 for (let i = 0; i < days.length; i  ) {
   let day = days[i];
   if (day["totalDuration"]["value"] > max) max = day["totalDuration"]["value"];
   if (day["totalDuration"]["value"] < min) min = day["totalDuration"]["value"];
 }
 if (max <= 0) max = 1;
 let x = d3.scaleLinear().range([0, height]).domain([min, max])
 return x;
}

getDayDurationHeight(data, dayName, dr) {
 //iterate through each day and find the bar height value...
 let days = data["days"];
 let duration = dr(0);

 for (let i = 0; i < days.length; i  ) {
   let day = days[i];
   if (day["dayName"] == dayName) {
    //this is where the d3 function is converting the value
    duration = dr(day["totalDuration"]["value"]);
   }
 }
 return duration;
}

getActualDuration(data, dayName){
  let days = data["days"];
  let duration = 0

  for (let i = 0; i < days.length; i  ) {
    let day = days[i];
    if (day["dayName"] == dayName) {
      duration = (day["totalDuration"]["display"]);
    }
  }
  return duration;
}
 

Комментарии:

1. Обычно .range([0,height]) должно быть .range([height, 0]) так, как SVG вверху слева равно 0, 0

Ответ №1:

Вот решение:

if (day["totalDuration"]["value"] > max) max = day["totalDuration"]["value"];

необходимо переключиться на

if (day["totalDuration"]["value"] > max) max = Math.ceil(day["totalDuration"]["value"]);

Кроме того, min в d3 функции должно быть установлено значение 0 .

оригинал: let x = d3.scaleLinear().range([0, height]).domain([min, max])

исправлено: let x = d3.scaleLinear().range([0, height]).domain([0, max])

Причина: для верхней строки устанавливается значение max , которое в настоящее время является точным номером строки. Добавление Math.ceil() переключает верхнюю строку на целое число. Кроме того, нижняя линия росла до min . Вместо этого он всегда должен быть 0 таким, а не переключаться в соответствии с min .