#javascript #reactjs #svg #d3.js
#javascript #reactjs #svg #d3.js
Вопрос:
Я пытаюсь создать две линейные диаграммы с помощью d3 в react, но я продолжаю получать эту ошибку и не знаю, как ее решить. Предполагается, что линейные диаграммы должны быть составлены с указанием времени эпохи на оси X и значений работоспособности на оси yAxis(Disk_Free, Memory_Free).Я изменил значения набора данных на значения с плавающей запятой, но я думаю, что что-то не так со значениями времени. Я очень новичок в d3, поэтому любой совет был бы полезен.
Это мой набор данных
[
{
Health_id: 1,
Epoch_Time: 1603959168.903983,
Disk_Free: '86.2',
Memory_Free: '1555480576',
},
{
Health_id: 2,
Epoch_Time: 1603959183.331211,
Disk_Free: '86.2',
Memory_Free: '1552396288',
},
{
Health_id: 3,
Epoch_Time: 1603959197.5066514,
Disk_Free: '86.2',
Memory_Free: '1565560832',
},
{
Health_id: 4,
Epoch_Time: 1603959211.6641965,
Disk_Free: '86.2',
Memory_Free: '1602510848',
},
{
Health_id: 5,
Epoch_Time: 1603959225.8478744,
Disk_Free: '86.2',
Memory_Free: '1594617856',
},
]
Мой код d3 для генерации строки выглядит следующим образом
static getDerivedStateFromProps(nextProps, prevState){
const { data } = nextProps; //This is where I accept the above dataset and I try creating the line charts with it
if(!data){
return {};
}
const xScale = d3.scaleTime().range([margin.left,width-margin.right]);
const yScale = d3.scaleLinear().range([height-margin.botton,margin.top])
//Set Domains on Scales
const timeDomain = d3.extent(data, d=>(d.Epoch_Time*1000))
const healthID = d3.extent(data, d=>(d.Health_id))
xScale.domain(timeDomain)
yScale.domain(healthID)
//Create and use line generator to plot the line charts
const lineGenerator = d3.line().x(d=>xScale((d.Epoch_Time*1000)))
const lines = [
{
path:lineGenerator.y((d)=>yScale((d.Disk_Free)))(data)
},
{
path:lineGenerator.y((d)=>yScale((d.Memory_Free)))(data)
},
];
return {lines, xScale, yScale};
}
render(){
return(
<div className="main-body">
<h4 center>Line Chart Test</h4>
<svg>
<g>
{this.state.lines.map((d,i)=>{
if(i===0){
return <path d={d.path} fill="none" stroke="red" />
}
else{
return <path d={d.path} fill="none" stroke="blue" />
}
})}
</g>
</svg>
</div>
)
}}export default Chart;
Я не получаю никаких линейных диаграмм при запуске веб-сайта, и ошибка, которую он показывает, такова:
Error: <path> attribute d: Expected number,
"….00000665251144,NaNL35.097628459…".
мой путь svg выглядит следующим образом:
<path d="M35.00203802950035,NaNL102.09192541055444,NaNL168.70615737356852,NaNL235.2960961666892,NaNL301.9796416583058,NaNL368.6469772068924,NaNL435.1701408263458,NaNL01.790251499806,NaNL568.4943668788065,NaNL635.0026281969162,NaN" fill="none"stroke="red">
</path>
Комментарии:
1. У вашего yScale есть проблема — регистрация его домена и диапазона выявляет проблему. Диапазон
[NaN,someNumber]
— скорее всего, ваш объект margin не имеет свойства с именемbotton
:range([height-margin.botton,margin.top])
. Хотя, учитывая размер значений Memory_Free по сравнению с доменом, вы можете не получить искомую строку, как только диапазон масштаба будет фиксированным.2. не могли бы вы предложить какие-либо советы о том, как правильно сгенерировать строку? Как я уже сказал, я очень новичок в этом, поэтому я не могу придумать никакой альтернативы.
3. Ну, если вы исправите опечатку в диапазоне (и преобразуете строки в числа, как показано ниже), вы хотя бы получите правильную строку без
NaN
s? Если это так, то это просто вопрос установки правильного домена, который является чем-то отдельным от ошибки, которую вы получаете.4. Да, у меня есть допустимая строка, но домен не виден.
5. Хорошо — теперь мы можем посмотреть на домен. Домен равен [1,5] — значение 1 будет масштабироваться, чтобы быть равным первому значению в диапазоне, значение 5 будет масштабироваться, чтобы быть равным второму значению в диапазоне. Поскольку ваши данные находятся за пределами [1,5] для памяти и диска, ваша строка будет выведена за пределы вашего диапазона. Значительно, поскольку размер диска в ~ 16 раз превышает верхний предел диапазона шкалы, а объем памяти на порядки больше. Вероятно, вы захотите установить домен для каждой строки в своей настройке, используя разные масштабы, с доменом, равным
d3.extent(data, function(d) { return d.PropertyBeingScaled })
Ответ №1:
Ваши значения Y Disk_Free
и Memory_Free
являются строками. Сначала вам нужно преобразовать их в числа с помощью, например parseFloat
:
lineGenerator.y((d) => yScale(parseFloat(d.Disk_Free)))(data)
// ...
lineGenerator.y((d) => yScale(parseFloat(d.Memory_Free)))(data)