React Native で GitHub の草のような Contribution Graph を作成する

何かの継続のモチベーションを上げたいときに、GitHub の草のような画面は有効です。 react-native-chart-kitCongtibutionGraph というコンポーネントがあります。これを使えば、以下のような画面が作れます。

以下のコマンドで必要なライブラリをインストールします。

shell
npm i react-native-chart-kit react-native-svg

https://github.com/indiespirit/react-native-chart-kit

画面に表示しているソースコードは以下のとおりです。

AchivementScreen.tsx
import React from 'react';
import { Dimensions, SafeAreaView, StyleSheet } from 'react-native';
import { ContributionGraph } from 'react-native-chart-kit';
import { type AbstractChartConfig } from 'react-native-chart-kit/dist/AbstractChart';
import { type ContributionChartValue } from 'react-native-chart-kit/dist/contribution-graph/ContributionGraph';

const commitsData = [
  { date: '2023-06-15', count: 1 },
  { date: '2023-06-16', count: 2 },
  { date: '2023-06-17', count: 3 },
  { date: '2023-06-18', count: 4 },
  { date: '2023-06-19', count: 5 },
  { date: '2023-06-20', count: 2 },
  { date: '2023-06-21', count: 3 },
  { date: '2023-06-22', count: 2 },
  { date: '2023-06-27', count: 4 },
  { date: '2023-06-28', count: 1 },
  { date: '2023-06-30', count: 5 },
];

const chartConfig: AbstractChartConfig = {
  backgroundGradientFrom: '#EBEDF0',
  backgroundGradientTo: '#EBEDF0',
  decimalPlaces: 2,
  color: (opacity = 1) => `rgba(11, 156, 49, ${opacity})`,
  labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`,
  style: {
    borderRadius: 16,
  },
};
export default function AchievementScreen() {
  const screenWidth = Dimensions.get('window').width;
  const tooltipDataAttrs = ({ value }: ContributionChartValue) => {
    if (value >= 10) {
      return {
        fill: 'green',
      };
    }
    return {};
  };
  return (
    <SafeAreaView style={styles.container}>
      <ContributionGraph
        values={commitsData}
        endDate={new Date('2023-06-30')}
        numDays={105}
        width={screenWidth}
        height={220}
        chartConfig={chartConfig}
        tooltipDataAttrs={tooltipDataAttrs}
      />
    </SafeAreaView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fefefe',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

実際に使うときは、 commitsData の部分に「日付」と「日付に対応する値」を入れます。

chartConfigcolor の部分で、ドットの色を調整します。上の commitsData の最大値と最小値を自動で計算して、色の濃度を調整してくれるようです。

tooltipDataAttrs の使い方は正直よくわかりません。GitHubのイシューでも「意味不明である」と疑問を持つ人がいました。以下のような「何もしない」がソリューションとして上げられています。

Sample.tsx
  const handleToolTip: any = {}

  return (
      <ContributionGraph
        values={commitsData}
        endDate={new Date("2017-04-01")}
        numDays={105}
        width={screenWidth}
        height={220}
        chartConfig={chartConfig}
        tooltipDataAttrs={(value) => handleToolTip}
      />
  );

なお、 react-native-chart-kit は Expo のプロジェクトの実機でも動作しました。

なぜこんなことを書くかと言うと、 cartiful/react-native-charts を前に試していて、 chartiful/react-native-charts はシミュレーターではエラーを吐きながらも動いたのですが、実機で動かすとアプリがクラッシュする現象が起こったからです。

この記事を書いているときに作ったアプリ