react-timeseries-charts仅在Safari无法绘图:d=xxxNaN解析错误
Safari下react-timeseries-charts图表空白且NaN错误排查与解决
问题现象
- 基于react-timeseries-charts开发的图表,在Chrome等浏览器正常渲染,Safari中柱状图、折线图完全空白
- 控制台报错:
react-dom.development.js: 无法解析:d=12345NaN, 45678NaN - DOM检查发现Safari中图表元素存在
x="NaN"属性,X轴未渲染 - 当数据点中
one/two/three/four任一值为0时,组件抛出NaN相关错误,但Chrome仍可正常渲染
相关代码片段
渲染代码
render() { return ( <div className="chart" id="chart" onTouchMove={this.handleTouchMove} onTouchStart={this.handleTouchStart} onTouchEnd={this.handleTouchEnd}> <ChartContainer timeRange={this.state.timerange} width={this.state.width} utc={true} format={this.formatTime} onBackgroundClick={() => this.setState({ selection: null })} onTimeRangeChanged={this.handleTimeRangeChange} timeAxisAngledLabels={false} timeAxisTickCount={this.state.tickCount} enablePanZoom={true} minDuration={this.state.minDuration} minTime={this.state.window_min} maxTime={this.state.window_max} paddingTop={this.state.paddingTop} paddingLeft={this.state.paddingLeft} paddingBottom={this.state.paddingBottom} paddingRight={this.state.paddingRight} timeAxisStyle={{ ticks: { stroke: "#000000", opacity: 1 }, values: { fill: "#000000", "font-size": "1.75vw" }, axis: { stroke: "#000000" } }}> <ChartRow height={this.state.height}> <YAxis id="axis" label="" min={0} max={this.state.y_max > this.state.rate ? this.state.y_max : (this.state.rate*1.1)} width="80" type="linear" labelOffset={2} style={{ label: { fill:"#000000" }, values: { fill: "#000000", "font-size": "1.75vw" }, ticks: { opacity: 1, stroke:"#000000" }, axis: { stroke: "#000000" } }} format={function (n){ return Number(n).toFixed(1)}} /> <Charts> <BarChart axis="axis" style={column_style} spacing={this.state.spacing} columns={this.state.active_columns} offset={3} series={this.state.Series} infoTimeFormat={(index) => ( <tspan style={{ fill: "black", fontSize: "0.8rem", fontWeight: "bold" }}> Hour: {moment(index.begin()).utc().format("HHmm")} </tspan> )} info={infoValues} infoWidth={130} infoHeight={40} infoStyle={{ label: { fill: "#000000", "font-size": "0.8rem" }, values: { fill: "#000000" }, box: { stroke: "#000000", opacity: 0.4 } }} infoOffsetY={150} stemStyle={{ stroke: "#000000", cursor: "crosshair" }} markerStyle={{ fill: "#000000" }} highlighted={ this.state.highlight } onHighlightChange={highlight => this.setState({ highlight })} /> </Charts> </ChartRow> </ChartContainer> </div> ); }
时间序列处理代码
let points = []; let one = 0, two = 0, three = 0, four = 0; for(let i in data){ if(some condition){ one++; }else if (some other condition){ two++; }else if (some other condition){ three++; }else{ four++; } } points.push({ "index": time, "one": one, "two": two, "three": three, "four": four }); for (let i in data) { const d = new Date(data[i].index); const index = Index.getIndexString(interval, d); points.push([index, data[i].one, data[i].two, data[i].three, data[i].four]); } if (points.length > 0) { const series = new TimeSeries({ name: "BarChart", columns: ["index", "one", "two", "three", "four"], points: points }); }
排查方向
- Safari与Chrome的数值/日期解析差异:Safari对0值的运算、非标准日期格式的容错性更低,可能导致组件内部计算时生成NaN
- 混合数据格式的兼容性问题:
points数组中同时存在对象格式和数组格式的元素,组件在Safari下无法正常解析这种混合格式 - Y轴max值的潜在NaN风险:Y轴max属性的计算依赖
this.state.rate,若rate为0或未定义,会导致rate*1.1变为NaN,进而破坏坐标计算逻辑
解决建议
1. 统一TimeSeries数据格式
确保points数组中所有元素格式一致,要么全为对象,要么全为数组。例如将第一个点改为数组格式:
// 替换原points.push({...}) points.push([time, one, two, three, four]);
2. 强制数值类型与边界处理
对生成的one/two/three/four强制转换为Number,并处理0值边界,避免组件计算时出现NaN:
points.push({ "index": time, "one": Number(one) || 0, "two": Number(two) || 0, "three": Number(three) || 0, "four": Number(four) || 0 });
3. 修复Y轴max值的安全计算
给this.state.rate添加默认值,避免0或未定义导致的NaN:
max={this.state.y_max > (this.state.rate || 0) ? this.state.y_max : ((this.state.rate || 0)*1.1)}
4. 统一日期解析逻辑
使用moment.js处理日期解析,避免Safari对非标准日期格式的解析错误:
// 替换原new Date(data[i].index) const d = moment(data[i].index).toDate();
5. 组件版本验证
检查react-timeseries-charts版本是否存在Safari兼容bug,尝试升级到最新稳定版,修复已知的跨浏览器兼容问题
内容的提问来源于stack exchange,提问作者squidmonkey
相关产品推荐
相关产品推荐

