UNPKG

react-svg-morph

Version:

morph your svg component one into another other

109 lines (96 loc) 3.08 kB
import React from 'react'; import normalizeSvg from './utils/normalizeSvg'; import { normalizePaths, getProgress } from './utils/morph'; import renderToJson from 'react-render-to-json'; export default class MorphTransition extends React.Component { constructor(props) { super(props); this.progress = 0; this.state = { current: [], viewBox: props.viewBox || [0, 0, props.width, props.height].join(' '), }; this.svgCache = {}; this.reset = true; } componentWillMount() { this.update(1); } componentWillReceiveProps(nextProps) { this.update(nextProps.progress / 100); } update(progress) { this.setChildren(); this.normalize(); let current = getProgress(this.from, this.to, progress); this.setState({current: current}); } render() { var width = this.props.width; var height = this.props.height; return ( <svg viewBox={this.viewBox} preserveAspectRatio="xMidYMid meet" fit width={width} height={height}> {this.state.current.map((item, index) => { return (<path d={item.path} key={index} {...item.attrs} style={item.style} transform={item.transStr} />); })} </svg> ); } normalize() { if (!this.reset) { return; } this.reset = false; let paths = normalizePaths(this.fromSvg.paths, this.toSvg.paths, {rotation: this.props.rotation}); this.from = paths.from; this.to = paths.to; } setChild(type, child) { var key = child.key; // it's not changed if (this[type + 'Child'] && key === this[type + 'Child'].key) { return false; } this.reset = true; this[type + 'Child'] = child; this[type + 'Svg'] = this.getSvgInfo(child); } setChildren() { if (!this.props.children.from || !this.props.children.to) { throw new Error("Please provide `from` and `to` React elements"); } this.setChild('from', this.props.children.from); this.setChild('to', this.props.children.to); } getSvgInfo(child) { let key = child.key; if (this.svgCache[key]) { return this.svgCache[key]; } let json = renderToJson(child); let svg = normalizeSvg(json); if (svg.viewBox) { this.viewBox = svg.viewBox; } this.svgCache[key] = svg; return svg; } } MorphTransition.propTypes = { rotation: React.PropTypes.oneOf(['clockwise', 'counterclock', 'none']), width: React.PropTypes.number, height: React.PropTypes.number, duration: React.PropTypes.number, progress: React.PropTypes.number, children: React.PropTypes.object, viewBox: React.PropTypes.string }; MorphTransition.defaultProps = { width: 40, height: 40, duration: 350, rotation: 'clockwise', progress: 0, easing: function(t) { return t; } };