Material-UIでアニメーション

ReactのUIフレームワークとして有名な[Material-UI(v4)](https://material-ui.com/)でCSSアニメーションを行います。
withStyle内にクラスとしてcss transitionおよびcss animationを定義できます。

# css transition
参考：[Custom CSS transitions with React Material UI](https://medium.com/@octaviocoria/custom-css-transitions-with-react-material-ui-5d41cb2e7c5)

css transitionを定義するには`theme.transitions.create`を使います。
第一引数には変化するCSS属性を指定します。第二引数にはアニメーション時間を指定します。

```RainbowButton.jsx
import React from 'react'
import { withStyles } from '@material-ui/core'
import Button from '@material-ui/core/Button'

const RainbowButton = withStyles(theme => ({
  root: {
    color: theme.palette.common.white,
    fontWeight: 'bold',
    textShadow: `2px 2px 4px ${theme.palette.common.black}`,
    fontSize: 32,
    background: 'linear-gradient(100deg, red, yellow, lightgreen, aqua, blue, pink, magenta)',
    filter: 'saturate(90%)',
    transition: theme.transitions.create(
      ['opacity'],
      { duration: theme.transitions.duration.complex }
    ),
    '&:hover': {
      opacity: 0.7,
    },
  },
}))(({classes, className, ...props}) => <Button className={[classes.root, className].join(' ')} {...props} />)

export default RainbowButton
```

マウスオーバーすると半透明になります。

![画面収録-2019-08-18-20.10.05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55077/b139379c-c527-9b8e-4a57-7ba3585443fa.gif)


# css animation
`$アニメーション名`でアニメーション名を指定します。
[MUI-v4以前の場合は$をつけません。](https://material-ui.com/guides/migration-v3/#styles)

```New.jsx
import React from 'react'
import { withStyles } from '@material-ui/styles'
import { red } from '@material-ui/core/colors'

let New = ({children, classes}) => (
  <div className={classes.root}>
    <div className={classes.new}>New</div>
    {children}
  </div>
)

New = withStyles((theme) => ({
  root: {
    position: 'relative',
  },
  new: {
    position: 'absolute',
    top: -20,
    left: 0,
    color: red[500],
    fontSize: 24,
    fontWeight: 'bold',
    transform: 'rotateZ(15deg)',
    textShadow:
    `1px 1px 0.5px ${theme.palette.grey[300]},
    -1px 1px 0.5px ${theme.palette.grey[300]},
    1px -1px 0.5px ${theme.palette.grey[300]},
    -1px -1px 0.5px ${theme.palette.grey[300]}`,
    animation: '$newAnimation 1s ease infinite alternate',
  },
  '@keyframes newAnimation': {
    '0%': {transform: 'rotateZ(-15deg) scale(1.0)'},
    '100%': {transform: 'rotateZ(-15deg) scale(1.3)'},
  },
}))(New)

export default New
```

Newの文字がアニメーションします。

![画面収録-2019-08-18-20.11.31.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55077/f4cd04b0-efe5-652e-c87e-eeab8b34ab75.gif)


# withStyleにprops経由でパラメータを渡す
v4からpropsからの情報をwithStyleで参照できるようになりました。
次のようにアロー関数の戻り値形式で指定します。
`opacity: props => props.opacity || 0.8,`

```RainbowButton2.jsx
import React from 'react'
import { withStyles } from '@material-ui/core'
import Button from '@material-ui/core/Button'

const RainbowButton = withStyles(theme => ({
  root: {
    color: theme.palette.common.white,
    fontWeight: 'bold',
    textShadow: `2px 2px 4px ${theme.palette.common.black}`,
    fontSize: 32,
    background: 'linear-gradient(100deg, red, yellow, lightgreen, aqua, blue, pink, magenta)',
    filter: 'saturate(90%)',
    transition: theme.transitions.create(
      ['opacity'],
      { duration: theme.transitions.duration.complex }
    ),
    '&:hover': {
      opacity: props => props.opacity || 0.8,
    },
  },
}))(({classes, className, ...props}) => <Button className={[classes.root, className].join(' ')} {...props} />)

export default RainbowButton
```