rechartsで微妙な差分を図示する
はじめに
小型ペットの体重記録アプリを開発中、体重の変化を可視化するために recharts
で折れ線グラフを実装しました。
体重が22g前後で、折れ線グラフのY軸を0〜30くらいにすると、小型ペットには比較的大きな変化である1、2gの変化がグラフ上でほとんど確認できませんでした。
そこで、微妙な体重変化を可視化するために以下の方法をとりました。
最終形
以下のように現在の体重データ周辺だけを表示するように。
工夫したこと
Y軸の範囲
まずは、データ周辺だけ表示するよう、domain
で範囲指定しました。
のちにY軸の目盛りを設定すると、このプラスマイナスの範囲は正確に反映されなくなりますが、一旦プラスマイナス2とします。
<YAxis
yAxisId={1}
domain={["dataMin - 2", "dataMax + 2"]} // ここ
tick={{
fontSize: 12,
fill: "#001858",
}}
/>
X軸の表示
Y軸が0から始まっていないので、詐欺グラフっぽくならないよう(そういう用途ではないので関係ないかもですが)はじめは <XAxis />
ごと削除してX軸を非表示にしていました。
しかし <XAxis />
をなくすとデータ点クリックでも日付が表示されなく不便なので、X軸の直線だけを非表示にして日付は表示することにしました。
<XAxis
dataKey="date"
tick={{
fontSize: 10,
fill: "#2f3138",
}}
axisLine={false} // ここ
/>
Y軸の目盛り
<YAxis />
でY軸の目盛りに数字を表示できますが、デフォルトでは小数点刻みの微妙な値になってしまいました。
5刻みくらいで表示したかったので、「平均値 - 5」「平均値」「平均値 + 5」の値を表示するよう、計算した値を ticks
パラメータにセットしました。
もっと幅広くデータが変化する場合は目盛りが足りないかもしれませんが、今回の用途ではこの範囲で十分でした。
また、avgWeightState
の値がセットされる前にグラフが表示されると、値がセットされた後に表示が更新されないため、avgWeightState
が確定してからグラフを表示するようにしました。
const [avgWeightState, setAvgWeightState] = useState<number>();
// データの平均値計算
useEffect(() => {
if (!data) return;
let totalWeight = 0;
let count = 0;
data.map((d: Weight) => {
totalWeight += d.weight;
if (d.weight) count++; // weightの値がある要素数をカウント
});
// truncではなくroundにすることでデータに近い値になる
setAvgWeightState(Math.round(totalWeight / count / 5) * 5);
}, [data]);
...
{avgWeightState && ( // 値が確定するまで表示しない
<YAxis
yAxisId={1}
domain={["dataMin - 2", "dataMax + 2"]}
ticks={[avgWeightState - 5, avgWeightState, avgWeightState + 5]} // 5刻みの値を表示
tick={{
fontSize: 12,
fill: "#001858",
}}
/>
)
おわりに
値の変化を自力で実装することなく、簡単に実現でき感謝です。
Discussion