javascriptchartsechartsapache-echarts

How does Apache ECharts handle bigint numbers when constructing a 'value' type X-axis?


I'm using Apache ECharts to visualize data with very large integer values (JavaScript bigint type) on the X-axis, configured as type: 'value'. However, I'm encountering unexpected behavior:

My data looks like this:

data: [
    { value: [12345678901234567890n, 10] },  // bigint X-value
    { value: [12345678901234567891n, 20] },
    // ...
]

Issue:

Expected Behavior:

Display the full precision of bigint values as readable labels (e.g., "12345678901234567890").

Attempted Solutions:

Tried setting axisLabel: { formatter: (value) => value.toString() }, but the original value is already rounded.

Question:

How can I configure ECharts to correctly handle and display bigint-scale integers on a 'value'-type X-axis without losing precision? Are there workarounds for axis formatting or data representation?


Solution

  • Echarts doesn't seem to support BigInt, this request for this feature is still pending.

    A search for BigInt in the source code doesn't produce any results.

    As for what's happening in the current version, all data points are passed through the function parseDataValue, (source code - dataValueHelper#L34) that applies Number constructor (called as function) to each numeric data value (see dataValueHelper#L80 in the same function), which casts the BigInts to number values, losing the precision, which appears in some cases as the values being "rounded" to a multiple of 10k, integer k > 1 (e.g., Number(12345678901234567890n) === 12345678901234567000).

    Also, if BigNums are given as values for some options, like if one sets the min or max of an axis to a BigInt, they will be passed (see scaleRawExtentInfo.ts#L205) through the global function isFinite, that doesn't accept BigInts as arguments, throwing the error Cannot convert a BigInt value to a number.

    A solution to avoid using BigNums can, of course, be improvised by anyone, tailored to the needs of their specific dataset; but since I put this as an answer rather than a comment, let me add a suggestion in this regard. One could choose any value of the BigInts, call it _bigNumZero, and extract it from each of the other values and convert that value to a number, presuming that the range of the BigNums is small enough to be covered without loss of precision by values of type number:

    let _bigNumZero = null;
    function resetBigNum(data){
       if(_bigNumZero === null){ // just for the first dataset
          _bigNumZero = data[0][0]; // the x value of the first point
       }
       for(const point of data){
          point[0] = Number(point[0] - _bigNumZero); // 0 for x dimension
       }
       return data;
    } 
    

    used in the chart configuration as:

    series: [
       {
          // ... other series options
          data: resetBigNum(.....)
       },
       // ... other series, similar treatment
    ]
    

    the argument of resetBigNum being a series' data as an array of [x, y] arrays, where x is always a BigInt.

    Then, formatters should be added everywhere the x value might be displayed, to add to the numeric value used by the chart, the "zero point" _bigNumZero. In the following echarts demo, I set formatters for the x axis and the tooltip.