Material UIを駆使して円グラフを描く #React

Material UIを駆使して円グラフを描く #React

Reactで Material UI を使って円グラフを実装する方法をご紹介します。
Clock Icon2021.07.08

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、クラスメソッドMAD事業部の岡です。
ちょっと遅れましたが、7月7日はクラメソ創立記念日なので久しぶりにブログを書きます。

こんな感じの円グラフを書きたい

上記の画像のような円グラフを書きたいと思います。頂点から時計回りにバロメーターが動くイメージです。

グラフライブラリを使えば効率的にいろいろなグラフの実装ができますが、グラフライブラリを使うとスタイルの調整が難しくなるため、 ここでは Material UI の CircularProgress を使って試してみました。

実際のコード

import { Box, CircularProgress, Grid, Typography } from '@material-ui/core'
import Battery80Icon from '@material-ui/icons/Battery80'
import React from 'react'
import styled from 'styled-components'

const CircularInternalContent = styled.div`
  left: 0;
  top: 16px;
  bottom: 0;
  right: 0;
  position: absolute;
`

const ProbabilitySuffix = styled(Typography)`
  margin-bottom: 4px;
`

const StyledCircularBackground = styled(CircularProgress)`
  color: #bfbfbf;
`

const StyledCircularBar = styled(CircularProgress)`
  position: absolute;
`

export const PieChart: React.VFC = () => {
  const value = 80
  return (
    <Box position="relative" display="inline-flex">
      {/* 背景用のCircularProgress */}
      <StyledCircularBackground variant="determinate" size={96} value={100} />
      {/* バロメーター用のCircularProgress */}
      <StyledCircularBar variant="determinate" size={96} value={value} />
      <CircularInternalContent>
        <Grid container justify="center">
          <Battery80Icon color="primary" fontSize="large" />
          <Grid
            container
            justify="center"
            alignItems="flex-end"
          >
            <Typography variant="h5">{value}</Typography>
            <ProbabilitySuffix variant="caption">%</ProbabilitySuffix>
          </Grid>
        </Grid>
      </CircularInternalContent>
    </Box>
  )
}

こんな感じになります。

便宜上 styled-components を使ってCSSを書いています。

やってることは CircularProgress を背景用とバロメーター用の2つを重ねて表示して、アイコンとパーセントの値を CircularProgress の内部に表示するようにしています。 シンプルに1つの値を表示するのであればこの方法でも良さそうでした。

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.