├── .npmignroe ├── LICENSE ├── README.md ├── index.js ├── package.json └── showcase ├── wave-ball.gif └── wave-rect.gif /.npmignroe: -------------------------------------------------------------------------------- 1 | showcase -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jian Wei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WaveView for React-Native 2 | 3 | ![](https://img.shields.io/badge/license-MIT-000000.svg) 4 | [![npm](https://img.shields.io/npm/dm/react-native-waveview.svg)](https://www.npmjs.com/package/react-native-waveview) 5 | [![npm](https://img.shields.io/npm/v/react-native-waveview.svg)](https://www.npmjs.com/package/react-native-waveview) 6 | ![](https://img.shields.io/badge/platform-react--native-brightgreen.svg) 7 | 8 | ## SHOWCASE 9 | 10 | ![Ball](https://github.com/CubeSugar/react-native-waveview/blob/master/showcase/wave-ball.gif?raw=true) 11 | 12 | ![Rectangle](https://github.com/CubeSugar/react-native-waveview/blob/master/showcase/wave-rect.gif?raw=true) 13 | 14 | ## DEPENDENCIES 15 | 16 | - [React-Native-Svg](https://github.com/react-native-community/react-native-svg) 17 | 18 | ## INSTALL 19 | 20 | 1. Install react-native-svg, use 21 | 22 | `npm install --save react-native-svg` or 23 | 24 | `yarn add react-native-svg` 25 | 26 | 2. Link react-native-svg, check [here](https://github.com/react-native-community/react-native-svg) for help. 27 | 28 | 3. `npm install --save react-native-waveview` or `yarn add react-native-waveview` 29 | 30 | ## USAGE 31 | 32 | #### Props 33 | 34 | name | type | desc 35 | :-----------|:--------:|:---------------- 36 | H | number | BaseLine height 37 | animated | bool | animation when mounted 38 | waveParams | Array | [{ A, T, fill}, ...] 39 | easing | string | name of easing from ReactNative#Easing 40 | speed | number | base duration in ms of one wave cycle 41 | speedIncreasePerWave | number | increase in speed in ms per each wave 42 | 43 | ``` 44 | /** 45 | ---------+------------------------+ 46 | <-- P -->|<-- T -->| |______ 47 | | /\ | /\ | ^ 48 | | / \ | / \ | A 49 | | / \ | / \ | | 50 | |/ \ |/ \|__V___ 51 | | \ / | ^ 52 | | \ / | | 53 | | \ / | | 54 | | \/ | H 55 | | | | 56 | | fill | | 57 | ---------+------------------------+__V___ 58 | */ 59 | ``` 60 | 61 | #### Methods 62 | 63 | * setWaveParams(waveParams) 64 | 65 | * setWaterHeight(H) 66 | 67 | * startAnim 68 | 69 | * stopAnim 70 | 71 | #### Example 72 | 73 | ```JSX 74 | 75 | { 76 | // Stop Animation 77 | this._waveRect && this._waveRect.stopAnim(); 78 | 79 | // set water baseline height 80 | this._waveRect && this._waveRect.setWaterHeight(70); 81 | 82 | // reset wave effect 83 | this._waveRect && this._waveRect.setWaveParams([ 84 | {A: 10, T: 180, fill: '#FF9F2E'}, 85 | {A: 15, T: 140, fill: '#F08200'}, 86 | {A: 20, T: 100, fill: '#B36100'}, 87 | ]); 88 | }}> 89 | this._waveRect = ref} 91 | style={_styles.wave} 92 | H={30} 93 | waveParams={[ 94 | {A: 10, T: 180, fill: '#62c2ff'}, 95 | {A: 15, T: 140, fill: '#0087dc'}, 96 | {A: 20, T: 100, fill: '#1aa7ff'}, 97 | ]} 98 | animated={true} 99 | /> 100 | 101 | 102 | ``` 103 | 104 | ``` 105 | 106 | 116 | 117 | ``` 118 | 119 | ``` 120 | const _styles = StyleSheet.create({ 121 | container: { 122 | flex: 1, 123 | marginVertical: 10, 124 | marginHorizontal: 20, 125 | justifyContent: 'center', 126 | alignItems: 'center', 127 | borderWidth: StyleSheet.hairlineWidth, 128 | }, 129 | wave: { 130 | width: 100, 131 | aspectRatio: 1, 132 | overflow: 'hidden', 133 | backgroundColor: 'white', 134 | }, 135 | waveBall: { 136 | width: 100, 137 | aspectRatio: 1, 138 | borderRadius: 50, 139 | overflow: 'hidden', 140 | } 141 | }); 142 | ``` 143 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import React from 'react'; 4 | import { 5 | View, 6 | Animated, 7 | StyleSheet, 8 | Easing, 9 | } from 'react-native'; 10 | import Svg, { 11 | G, 12 | Path, 13 | } from 'react-native-svg'; 14 | 15 | const AnimatedSvg = Animated.createAnimatedComponent(Svg); 16 | 17 | /** 18 | * ---------+------------------------+ 19 | * <-- P -->|<-- T -->| |______ 20 | * | /\ | /\ | ^ 21 | * | / \ | / \ | A 22 | * | / \ | / \ | | 23 | * |/ \ |/ \|__V___ 24 | * | \ / | ^ 25 | * | \ / | | 26 | * | \ / | | 27 | * | \/ | H 28 | * | | | 29 | * | | | 30 | * ---------+------------------------+__V___ 31 | */ 32 | 33 | /** 34 | * @class Wave 35 | * 36 | * @prop {Number} H water level 37 | * @prop {Array} waveParams list of params: {A, T, fill} 38 | * @prop {bool} animated 39 | */ 40 | class Wave extends React.PureComponent { 41 | constructor(props) { 42 | super(props); 43 | 44 | let {H, waveParams, animated} = this.props; 45 | 46 | this.state = { 47 | H, 48 | waveParams, 49 | }; 50 | 51 | this._animValues = []; 52 | this._animations = []; 53 | this._animated = animated || false; 54 | 55 | for (let i = 0; i < this.state.waveParams.length; i++) { 56 | this._animValues.push(new Animated.Value(0)); 57 | } 58 | } 59 | 60 | componentDidMount() { 61 | this._animated && this.startAnim(); 62 | } 63 | 64 | componentWillUnmount() { 65 | this.stopAnim(); 66 | this._animValues = null; 67 | this._animations = null; 68 | } 69 | 70 | render() { 71 | let {style} = this.props; 72 | let {H, waveParams} = this.state; 73 | 74 | let waves = []; 75 | 76 | for (let i = 0; i < waveParams.length; i++) { 77 | let {A, T, fill} = waveParams[i]; 78 | let translateX = this._animValues[i].interpolate({ 79 | inputRange: [0, 1], 80 | outputRange: [0, -2 * T], 81 | }); 82 | let wave = ( 83 | 96 | 101 | 102 | ); 103 | waves.push(wave); 104 | } 105 | 106 | return ( 107 | 108 | {waves} 109 | 110 | ); 111 | } 112 | 113 | setWaveParams(waveParams) { 114 | if (!waveParams) return; 115 | 116 | let animated = this._animated; 117 | let newWaveCount = waveParams.length; 118 | let oldWaveCount = this.state.waveParams.length; 119 | if (animated) { 120 | this.stopAnim(); 121 | for (let v of this._animValues) { 122 | v.setValue(0); 123 | } 124 | } 125 | if (newWaveCount !== oldWaveCount) { 126 | this._animValues = []; 127 | for (let i = 0; i < waveParams.length; i++) { 128 | this._animValues.push(new Animated.Value(0)); 129 | } 130 | } 131 | 132 | this.setState({ 133 | waveParams, 134 | }, ()=>{ 135 | if (animated) { 136 | this.startAnim(); 137 | } 138 | }); 139 | } 140 | 141 | setWaterHeight(H) { 142 | this.setState({H}); 143 | } 144 | 145 | startAnim() { 146 | this.stopAnim(); 147 | 148 | const { 149 | speed = 5000, 150 | speedIncreasePerWave = 1000, 151 | easing = 'linear' 152 | } = this.props 153 | 154 | for (let i = 0; i < this._animValues.length; i++) { 155 | let anim = Animated.loop(Animated.timing(this._animValues[i], { 156 | toValue: 1, 157 | duration: speed + i * speedIncreasePerWave, 158 | easing: Easing[easing], 159 | useNativeDriver: true, 160 | })); 161 | this._animations.push(anim); 162 | anim.start(); 163 | } 164 | this._animated = true; 165 | } 166 | 167 | stopAnim() { 168 | for (let _anim of this._animations) { 169 | _anim.stop(); 170 | _anim = null; 171 | } 172 | this._animations = []; 173 | this._animated = false; 174 | } 175 | }; 176 | 177 | export default Wave; 178 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-waveview", 3 | "version": "1.1.0", 4 | "description": "WaveView for React-Native", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/CubeSugar/react-native-waveview.git" 12 | }, 13 | "keywords": [ 14 | "react-native", 15 | "wave", 16 | "waveview", 17 | "svg" 18 | ], 19 | "author": "Wei Jian", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/CubeSugar/react-native-waveview/issues" 23 | }, 24 | "homepage": "https://github.com/CubeSugar/react-native-waveview#readme" 25 | } 26 | -------------------------------------------------------------------------------- /showcase/wave-ball.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CubeSugar/react-native-waveview/fcce4f10545bc1286b47235f5d90b0c050ec310e/showcase/wave-ball.gif -------------------------------------------------------------------------------- /showcase/wave-rect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CubeSugar/react-native-waveview/fcce4f10545bc1286b47235f5d90b0c050ec310e/showcase/wave-rect.gif --------------------------------------------------------------------------------