You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
  });
}

排查方向

  1. Safari与Chrome的数值/日期解析差异:Safari对0值的运算、非标准日期格式的容错性更低,可能导致组件内部计算时生成NaN
  2. 混合数据格式的兼容性问题:points数组中同时存在对象格式和数组格式的元素,组件在Safari下无法正常解析这种混合格式
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 04:28:12