#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
.