Search code examples
javascriptreact-nativevictory-chartsvictory-native

Victory Chart - How to create data gap in react native using Victory chart?


I have a data set with the structure

{"Text": "18.52", "Timestamp": 1677662169, "date": 2023-03-01T09:16:09.000Z, "max": 18.55, "min": 18.49, "y": 18.52} 

I want to display the blank data gap when there is no value, to show the device disconnected at that time period.

This is the graph I expected to see.(It is using another chart library)

But with the same data set using in Victory Chart, it will not show the timestamp with empty y-axis value but instead it will ignore the blank and form a linear graph. No data gap in Victory Chart

Therefore, I tried with adding null y values to manually create a data gap {"Text": "", "Timestamp": Last Reading Timestamp, "date": Last Date, "max": Last max, "min": Last min, "y": null} . But seems Victory chart will mess up the scaling when null values is received like the following.

Some of the Data Output

{"Text": "19.39", "Timestamp": 1677603631, "date": 2023-02-28T17:00:31.000Z, "max": 19.42, "min": 19.38, "y": 19.39}, {"Text": "", "Timestamp": 1677603931, "date": 2023-02-28T17:05:31.000Z, "max": null, "min": null, "y": null}, {"Text": "", "Timestamp": 1677604231, "date": 2023-02-28T17:10:31.000Z, "max": null, "min": null, "y": null}, {"Text": "", "Timestamp": 1677604531, "date": 2023-02-28T17:15:31.000Z, "max": null, "min": null, "y": null}

Output Graph which is in wrong scale

I have also tried undefined, NaN, the library does not accept these values. Do you have any ideas for me to achieve data gaps while keeping the normal graph scaling? Any help is appreciated.

Function for adding null values to form data gap

 var gapData2 = [];
      combinedData.map((data, index) => {
        if (combinedData[index + 1]) {
          let diffTime = combinedData[index + 1].Timestamp - data.Timestamp;
          if (diffTime > 350) {
            let timeToAdd = Math.floor(diffTime / 300);
            let currentTimeStamp = data.Timestamp;
            gapData2.push(data);
            for (let x = 0; x < timeToAdd; x++) {
              currentTimeStamp = currentTimeStamp + 300;
              gapData2.push({
                Timestamp: currentTimeStamp,
                min: null,
                date: new Date(currentTimeStamp * 1000),
                y: null,
                Text: "",
                max: null,
              });
            }
          } else {
            gapData2.push(data);
          }
        } else if (
          combinedData.length !== 0 &&
          index === combinedData.length - 1
        ) {
          gapData2.push(data);
        } else {
          return;
        }
      });

Victory chart code

 <View>
        <VictoryChart
          padding={{ top: 15, bottom: 5, right: 20, left: 20 }}
          style={{
            background: { fill: "#3a65aa" },
          }}
          containerComponent={
            <VictoryVoronoiContainer
              onActivated={(points) => {
                let pointIndex = points[0]._x;

                if (pointIndex <= graphX) {
                  setIndex(pointIndex);
                  onDataPointClick(points[0]);
                }
              }}
            />
          }
        >
          <VictoryArea
            style={{
              data: { fill: "#85a1d4" },
            }}
            data={[
              {
                x: 0,
                y: yMax,
                y0: yMin,
              },

              {
                x: graphX,
                y: yMax,
                y0: yMin,
              },
            ]}
          />

          <VictoryGroup domainPadding={{ y: 15 }}>
            <VictoryArea
              style={{
                data: { fill: "#C5CFE3" },
              }}
              data={[
                {
                  x: 0,
                  y: highAlarm || props.max,
                  y0: lowAlarm || yMin,
                },

                {
                  x: graphX,
                  y: highAlarm || props.max,
                  y0: lowAlarm || yMin,
                },
              ]}
            />
            {highAlarm && (
              <VictoryScatter
                standalone={false}
                data={[
                  {
                    x: graphX,
                    y: highAlarm,
                  },
                ]}
                dataComponent={
                  <AlarmPoint
                    label={"🔔↑" + highAlarmLabel + props.channelUnit}
                  />
                }
              />
            )}
            {lowAlarm && (
              <VictoryScatter
                standalone={false}
                data={[
                  {
                    x: graphX,
                    y: lowAlarm,
                  },
                ]}
                dataComponent={
                  <AlarmPoint
                    label={"🔔↓" + lowAlarmLabel + props.channelUnit}
                  />
                }
              />
            )}
            {
              <VictoryScatter
                standalone={false}
                data={[
                  {
                    x: 0,
                    y: props.min,
                  },
                ]}
                dataComponent={
                  <MinMax
                    padding={lowAlarm && props.min < lowAlarm ? 15 : 30}
                    label={props.min + props.channelUnit}
                  />
                }
              ></VictoryScatter>
            }
            {props.min != props.max && (
              <VictoryScatter
                standalone={false}
                data={[
                  {
                    x: 0,
                    y: props.max,
                  },
                ]}
                dataComponent={
                  <MinMax
                    padding={highAlarm && props.max > highAlarm ? 0 : 15}
                    label={props.max + props.channelUnit}
                  />
                }
              ></VictoryScatter>
            )}
            {
              <VictoryScatter
                standalone={false}
                data={[
                  {
                    x: index,
                    y: props.data[index].y,
                  },
                ]}
                size={8}
                color="#0F0873"
              ></VictoryScatter>
            }
          </VictoryGroup>
          <VictoryGroup
            domainPadding={{ y: 15 }}
            color="#0F0873"
            data={props.data}
          >
            <VictoryLine
              x="props.data.date"
              interpolation={"catmullRom"}
              standalone={false}
            />
            <VictoryAxis
              axisComponent={<LineSegment style={{ display: "none" }} />}
              tickFormat={() => ""}
            />
          </VictoryGroup>
          <VictoryGroup domainPadding={{ y: 15 }}>
            {lowAlarm && (
              <VictoryLine
                style={{
                  data: {
                    stroke: "#3a65aa",
                    strokeWidth: 1,
                    strokeLinecap: "round",
                    strokeDasharray: "2, 2",
                  },
                }}
                data={[
                  { x: 0, y: lowAlarm },
                  { x: graphX, y: lowAlarm },
                ]}
              />
            )}
            {highAlarm && (
              <VictoryLine
                style={{
                  data: {
                    stroke: "#3a65aa",
                    strokeWidth: 1,
                    strokeLinecap: "round",
                    strokeDasharray: "2, 2",
                  },
                }}
                data={[
                  { x: 0, y: highAlarm },
                  { x: graphX, y: highAlarm },
                ]}
              />
            )}
            <VictoryLine
              style={{
                data: {
                  stroke: "#3a65aa",
                  strokeWidth: 1,
                  strokeLinecap: "round",
                  strokeDasharray: "2, 2",
                },
              }}
              data={[
                { x: 0, y: props.min },
                { x: graphX, y: props.min },
              ]}
            />
            {props.min != props.max && (
              <VictoryLine
                style={{
                  data: {
                    stroke: "#3a65aa",
                    strokeWidth: 1,
                    strokeLinecap: "round",
                    strokeDasharray: "2, 2",
                  },
                }}
                data={[
                  { x: 0, y: props.max },
                  { x: graphX, y: props.max },
                ]}
              />
            )}
          </VictoryGroup>
        </VictoryChart>

        <View style={styles.hrStyle}>
          <View style={styles.axisLeftLayout}>
            <Text style={styles.axisLabel}>{props.timeTo}</Text>
          </View>
          <View style={styles.axisRightLayout}>
            <Text style={styles.axisLabel}>{props.timeFrom}</Text>
          </View>
        </View>
      </View>


Solution

  • Fixed by using minDomain and maxDomain.

    minDomain={{ y: yMin }}
    maxDomain={{ y: yMax }}
    

    Thank you @RubenSmn.Really appreciate your help.