Skip to content

Commit

Permalink
feat(axes): replace react-motion by react-spring
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Jun 26, 2020
1 parent 74001a6 commit 50c135d
Show file tree
Hide file tree
Showing 10 changed files with 448 additions and 477 deletions.
5 changes: 2 additions & 3 deletions packages/axes/package.json
Expand Up @@ -21,15 +21,14 @@
"dist/"
],
"dependencies": {
"@nivo/core": "0.62.0",
"@nivo/scales": "0.62.0",
"d3-format": "^1.4.4",
"d3-time": "^1.0.11",
"d3-time-format": "^2.1.3",
"lodash": "^4.17.11",
"react-motion": "^0.5.2"
"react-spring": "^8.0.27"
},
"peerDependencies": {
"@nivo/core": "0.62.0",
"prop-types": ">= 15.5.10 < 16.0.0",
"react": ">= 16.8.4 < 17.0.0"
},
Expand Down
151 changes: 62 additions & 89 deletions packages/axes/src/components/Axis.js
Expand Up @@ -6,28 +6,14 @@
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import React, { memo, Fragment, useMemo } from 'react'
import React, { memo, useMemo } from 'react'
import PropTypes from 'prop-types'
import { Motion, TransitionMotion, spring } from 'react-motion'
import { useSpring, useTransition, animated } from 'react-spring'
import { useTheme, useMotionConfig } from '@nivo/core'
import { computeCartesianTicks, getFormatter } from '../compute'
import { axisPropTypes } from '../props'
import AxisTick from './AxisTick'

const willEnter = () => ({
rotate: 0,
opacity: 0,
x: 0,
y: 0,
})

const willLeave = springConfig => ({ style: { x, y, rotate } }) => ({
rotate,
opacity: spring(0, springConfig),
x: spring(x.val, springConfig),
y: spring(y.val, springConfig),
})

const defaultTickRenderer = props => <AxisTick {...props} />

const Axis = ({
Expand All @@ -49,7 +35,6 @@ const Axis = ({
onClick,
}) => {
const theme = useTheme()
const { animate, springConfig } = useMotionConfig()

const formatValue = useMemo(() => getFormatter(format, scale), [format, scale])

Expand Down Expand Up @@ -109,80 +94,68 @@ const Axis = ({
)
}

if (animate !== true) {
return (
<g transform={`translate(${x},${y})`}>
{ticks.map((tick, tickIndex) =>
React.createElement(renderTick, {
tickIndex,
format: formatValue,
rotate: tickRotation,
textBaseline,
textAnchor: textAlign,
...tick,
...(onClick ? { onClick } : {}),
})
)}
<line
style={theme.axis.domain.line}
x1={0}
x2={axis === 'x' ? length : 0}
y1={0}
y2={axis === 'x' ? 0 : length}
/>
{legendNode}
</g>
)
}
const { animate, config: springConfig } = useMotionConfig()

const animatedProps = useSpring({
transform: `translate(${x},${y})`,
lineX2: axis === 'x' ? length : 0,
lineY2: axis === 'x' ? 0 : length,
config: springConfig,
immediate: !animate,
})

const transitions = useTransition(ticks, tick => tick.key, {
initial: tick => ({
opacity: 1,
transform: `translate(${tick.x},${tick.y})`,
textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
}),
from: tick => ({
opacity: 0,
transform: `translate(${tick.x},${tick.y})`,
textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
}),
enter: tick => ({
opacity: 1,
transform: `translate(${tick.x},${tick.y})`,
textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
}),
update: tick => ({
opacity: 1,
transform: `translate(${tick.x},${tick.y})`,
textTransform: `translate(${tick.textX},${tick.textY}) rotate(${tickRotation})`,
}),
leave: {
opacity: 0,
},
config: springConfig,
immediate: !animate,
})

return (
<Motion style={{ x: spring(x, springConfig), y: spring(y, springConfig) }}>
{xy => (
<g transform={`translate(${xy.x},${xy.y})`}>
<TransitionMotion
willEnter={willEnter}
willLeave={willLeave(springConfig)}
styles={ticks.map(tick => ({
key: `${tick.key}`,
data: tick,
style: {
opacity: spring(1, springConfig),
x: spring(tick.x, springConfig),
y: spring(tick.y, springConfig),
rotate: spring(tickRotation, springConfig),
},
}))}
>
{interpolatedStyles => (
<Fragment>
{interpolatedStyles.map(({ style, data: tick }, tickIndex) =>
React.createElement(renderTick, {
tickIndex,
format: formatValue,
textBaseline,
textAnchor: textAlign,
...tick,
...style,
...(onClick ? { onClick } : {}),
})
)}
</Fragment>
)}
</TransitionMotion>
<Motion
style={{
x2: spring(axis === 'x' ? length : 0, springConfig),
y2: spring(axis === 'x' ? 0 : length, springConfig),
}}
>
{values => (
<line style={theme.axis.domain.line} x1={0} y1={0} {...values} />
)}
</Motion>
{legendNode}
</g>
)}
</Motion>
<animated.g transform={animatedProps.transform}>
{transitions.map(({ item: tick, props: transitionProps, key }, tickIndex) => {
return React.createElement(renderTick, {
tickIndex,
format: formatValue,
rotate: tickRotation,
textBaseline,
textAnchor: textAlign,
animatedProps: transitionProps,
...tick,
...(onClick ? { onClick } : {}),
key,
})
})}
<animated.line
style={theme.axis.domain.line}
x1={0}
x2={animatedProps.lineX2}
y1={0}
y2={animatedProps.lineY2}
/>
{legendNode}
</animated.g>
)
}

Expand Down
23 changes: 10 additions & 13 deletions packages/axes/src/components/AxisTick.js
Expand Up @@ -7,23 +7,19 @@
* file that was distributed with this source code.
*/
import React, { memo } from 'react'
import { animated } from 'react-spring'
import PropTypes from 'prop-types'
import { useTheme } from '@nivo/core'

const AxisTick = ({
value: _value,
x,
y,
opacity,
rotate,
format,
lineX,
lineY,
onClick,
textX,
textY,
textBaseline,
textAnchor,
animatedProps,
}) => {
const theme = useTheme()

Expand All @@ -32,27 +28,27 @@ const AxisTick = ({
value = format(value)
}

let gStyle = { opacity }
let gStyle = { opacity: animatedProps.opacity }
if (onClick) {
gStyle['cursor'] = 'pointer'
}

return (
<g
transform={`translate(${x},${y})`}
<animated.g
transform={animatedProps.transform}
{...(onClick ? { onClick: e => onClick(e, value) } : {})}
style={gStyle}
>
<line x1={0} x2={lineX} y1={0} y2={lineY} style={theme.axis.ticks.line} />
<text
<animated.text
dominantBaseline={textBaseline}
textAnchor={textAnchor}
transform={`translate(${textX},${textY}) rotate(${rotate})`}
transform={animatedProps.textTransform}
style={theme.axis.ticks.text}
>
{value}
</text>
</g>
</animated.text>
</animated.g>
)
}

Expand All @@ -71,6 +67,7 @@ AxisTick.propTypes = {
opacity: PropTypes.number.isRequired,
rotate: PropTypes.number.isRequired,
onClick: PropTypes.func,
animatedProps: PropTypes.object.isRequired,
}
AxisTick.defaultProps = {
opacity: 1,
Expand Down
9 changes: 8 additions & 1 deletion packages/axes/src/components/GridLine.js
Expand Up @@ -8,14 +8,21 @@
*/
import React, { memo } from 'react'
import PropTypes from 'prop-types'
import { animated } from 'react-spring'
import { useTheme } from '@nivo/core'

const GridLine = props => <line {...props} />
const GridLine = ({ animatedProps }) => {
const theme = useTheme()

return <animated.line {...animatedProps} {...theme.grid.line} />
}

GridLine.propTypes = {
x1: PropTypes.number.isRequired,
x2: PropTypes.number.isRequired,
y1: PropTypes.number.isRequired,
y2: PropTypes.number.isRequired,
animatedProps: PropTypes.object.isRequired,
}
GridLine.defaultProps = {
x1: 0,
Expand Down

0 comments on commit 50c135d

Please sign in to comment.