react-native-Art动画基础

来源:互联网 发布:乐视vr 没数据 编辑:程序博客网 时间:2024/06/08 08:28

转载http://blog.csdn.net/tiem_erhu/article/details/53333670

一:基础: 
ART:暴露了七个组件: 
● Surface - 一个矩形可渲染的区域,是其他元素的容器! 
● Group - 可容纳多个形状、文本和其他的分组 
● Shape - 形状定义,可填充 
● Text - 文本形状定义 
props 
● Surface 
○ width : 渲染区域的宽 
○ height : 定义渲染区域的高 
● Shape 
○ d : 定义绘制路径 
○ stroke : 描边颜色 
○ strokeWidth : 描边宽度 
○ strokeDash : 定义虚线 
○ fill : 填充颜色 
● Text 
○ funt : 字体样式,定义字体、大小、是否加粗 如: bold 35px Heiti SC 
● Path 
○ moveTo(x,y) : 移动到坐标(x,y) 
○ lineTo(x,y) : 连线到(x,y) 
○ arc() : 绘制弧线 
○ close() : 封闭空间

二:实例 
● 绘制直线:

import  React,{Component} from 'react';import  { ART, View, StyleSheet,} from 'react-native';var {  Surface,  Group,  Shape,  Path} = ART;export default class  Note extends Component{    render(){         const path = Path()            .moveTo(1,1)//移动起始点            .lineTo(300,1);//绘制结束后的坐标点        return(            <View style={styles.container}>                <Surface width={300} height={2}>                    <Shape d={path} stroke="#000000" strokeWidth={1} />                </Surface>            </View>        )    }}var styles = StyleSheet.create({  container: {    paddingTop: 20,  }});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  注意Surface的宽高,就是视图能绘制的宽高

● 绘制虚线:

export default class  Note extends Component{    render(){         const path = Path()            .moveTo(1,1)//移动起始点            .lineTo(300,1);//绘制结束后的坐标点        return(           <View style={styles.container}>                <Surface width={300} height={2}>                    <Shape d={path} stroke="#000000" strokeWidth={2} strokeDash={[10,50]}/>                </Surface>            </View>        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
注意:strokeDash={[10,50]}表示:先绘制10像素的实线然后绘制50像素的虚线!

● 绘制矩形:

export default class  Note extends Component{    render(){         const path = new Path()            .moveTo(1,1)            .lineTo(1,99)            .lineTo(99,99)            .lineTo(99,1)            .close();        return(           <View style={styles.container}>                <Surface width={100} height={100}>                  <Shape d={path} stroke="#000000" fill="#892265" strokeWidth={1} />                </Surface>            </View>        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

注意:close的意思是创建一个密闭的路径,首先通过linrTo绘制三条边,然后使用close链接第四条边。使用fill设置里面的填充色。

● 绘制圆形:

export default class  Note extends Component{    render(){         const path = new Path()            .moveTo(50,1)            .arc(0,99,25)            .arc(0,-99,25)            .close();        return(           <View style={styles.container}>                <Surface width={100} height={100}>                 <Shape d={path} stroke="#000000" strokeWidth={1}/>                </Surface>            </View>        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  注意:acr(x,y,radius)终点坐标距离起始点的相对距离

● 绘制字体:

export default class  Note extends Component{    render(){        const   path=new Path()        .moveTo(40,40)        .lineTo(99,10);        return(           <View style={styles.container}>                <Surface width={100} height={100}>                   <Text strokeWidth={1} stroke="#000" font="bold 35px Heiti SC" path={path} >Swipe</Text>                </Surface>            </View>        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

注意:font的使用

● 绘制扇形:

const {Surface} = ART;import Wedge from './Wedge'export default class  Note extends Component{    render(){        const  path=new Path()        .moveTo(40,40)        .lineTo(99,10);        return(           <View style={styles.container}>                 <Surface width={100} height={100}>                    <Wedge                     outerRadius={50}                     startAngle={0}                     endAngle={60}                     originX={50}                     originY={50}                     fill="blue"/>                </Surface>            </View>        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
   注意:使用了一个React.art封装的一个组件Wedge;

● 图层叠加:

const {Surface, Shape,Text, Path,Group} = ART;export default class  Note extends Component{    render(){        const pathRect = new Path()            .moveTo(1,1)            .lineTo(1,99)            .lineTo(99,99)            .lineTo(99,1)            .close();        const pathCircle = new Path()            .moveTo(50,1)            .arc(0,99,25)            .arc(0,-99,25)            .close();        const pathText = new Path()            .moveTo(40,5)            .lineTo(40,99);        return(            <View style={styles.container}>                <Surface width={100} height={100}>                    <Group>                        <Shape d={pathRect} stroke="#000000" fill="#000000" strokeWidth={1}/>                        <Shape d={pathCircle} stroke="#FFFFFF" fill="#FFFFFF" strokeWidth={1}/>                        <Text strokeWidth={1} strokeDash={[2,1,2,1]} stroke="#000" font="bold 30px Heiti SC" path={pathText} >Swipe</Text>                    </Group>                </Surface>            </View>        )    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

注意:图层叠加,上一层的会覆盖下一层的,类似于安卓的帧布局!

三:高级例子: 
效果图:

这里写图片描述

import React ,{    Component}from 'react';import {  ART as Art,  StyleSheet,  View,  Dimensions,  TouchableWithoutFeedback,  Animated} from 'react-native';var HEART_SVG = "M130.4-0.8c25.4 0 46 20.6 46 46.1 0 13.1-5.5 24.9-14.2 33.3L88 153.6 12.5 77.3c-7.9-8.3-12.8-19.6-12.8-31.9 0-25.5 20.6-46.1 46-46.2 19.1 0 35.5 11.7 42.4 28.4C94.9 11 111.3-0.8 130.4-0.8"var HEART_COLOR = 'rgb(226,38,77,1)';var GRAY_HEART_COLOR = "rgb(204,204,204,1)";var FILL_COLORS = [   'rgba(221,70,136,1)',  'rgba(212,106,191,1)',  'rgba(204,142,245,1)',  'rgba(204,142,245,1)',  'rgba(204,142,245,1)',  'rgba(0,0,0,0)'];var PARTICLE_COLORS = [  'rgb(158, 202, 250)',  'rgb(161, 235, 206)',  'rgb(208, 148, 246)',  'rgb(244, 141, 166)',  'rgb(234, 171, 104)',  'rgb(170, 163, 186)'] getXYParticle=(total, i, radius)=> {  var angle = ( (2*Math.PI) / total ) * i;  var x = Math.round((radius*2) * Math.cos(angle - (Math.PI/2)));  var y = Math.round((radius*2) * Math.sin(angle - (Math.PI/2)));  return {    x: x,    y: y,  }} getRandomInt=(min, max)=> {  return Math.floor(Math.random() * (max - min)) + min;} shuffleArray=(array)=> {    for (var i = array.length - 1; i > 0; i--) {        var j = Math.floor(Math.random() * (i + 1));        var temp = array[i];        array[i] = array[j];        array[j] = temp;    }    return array;}var {  Surface,  Group,  Shape,  Path} = Art;//使用Animated.createAnimatedComponent对其他组件创建对话//创建一个灰色的新型图片var AnimatedShape = Animated.createAnimatedComponent(Shape);var {  width: deviceWidth,  height: deviceHeight} = Dimensions.get('window');export default  class Key extends  Component{  constructor(props) {    super(props);    this.state = {       animation: new Animated.Value(0)     };  }  explode=()=> {    Animated.timing(this.state.animation, {      duration: 1500,      toValue: 28    }).start(() => {      this.state.animation.setValue(0);      this.forceUpdate();    });  }  getSmallExplosions=(radius, offset)=> {    return [0,1,2,3,4,5,6].map((v, i, t) => {      var scaleOut = this.state.animation.interpolate({        inputRange: [0, 5.99, 6, 13.99, 14, 21],        outputRange: [0, 0, 1, 1, 1, 0],        extrapolate: 'clamp'      });      var moveUp = this.state.animation.interpolate({        inputRange: [0, 5.99, 14],        outputRange: [0, 0, -15],        extrapolate: 'clamp'      });      var moveDown = this.state.animation.interpolate({        inputRange: [0, 5.99, 14],        outputRange: [0, 0, 15],        extrapolate: 'clamp'      });      var color_top_particle = this.state.animation.interpolate({        inputRange: [6, 8, 10, 12, 17, 21],        outputRange: shuffleArray(PARTICLE_COLORS)      })      var color_bottom_particle = this.state.animation.interpolate({        inputRange: [6, 8, 10, 12, 17, 21],        outputRange: shuffleArray(PARTICLE_COLORS)      })      var position = getXYParticle(7, i, radius)      return (        <Group           x={position.x + offset.x }           y={position.y + offset.y}           rotation={getRandomInt(0, 40) * i}        >          <AnimatedCircle             x={moveUp}            y={moveUp}            radius={15}             scale={scaleOut}             fill={color_top_particle}           />          <AnimatedCircle             x={moveDown}            y={moveDown}            radius={8}             scale={scaleOut}             fill={color_bottom_particle}           />        </Group>      )    }, this)  }  render() {    var heart_scale = this.state.animation.interpolate({      inputRange: [0, .01, 6, 10, 12, 18, 28],      outputRange: [1, 0, .1, 1, 1.2, 1, 1],      extrapolate: 'clamp'    });    var heart_fill = this.state.animation.interpolate({      inputRange: [0, 2],      outputRange: [GRAY_HEART_COLOR, HEART_COLOR],      extrapolate: 'clamp'    })    var heart_x = heart_scale.interpolate({      inputRange: [0, 1],      outputRange: [90, 0],    })    var heart_y = heart_scale.interpolate({      inputRange: [0, 1],      outputRange: [75, 0],    })    var circle_scale = this.state.animation.interpolate({      inputRange: [0, 1, 4],      outputRange: [0, .3, 1],      extrapolate: 'clamp'    });    var circle_stroke_width = this.state.animation.interpolate({      inputRange: [0, 5.99, 6, 7, 10],      outputRange: [0, 0, 15, 8, 0],      extrapolate: 'clamp'    });    var circle_fill_colors = this.state.animation.interpolate({      inputRange: [1, 2, 3, 4, 4.99, 5],      outputRange: FILL_COLORS,      extrapolate: 'clamp'    })    var circle_opacity = this.state.animation.interpolate({      inputRange: [1,9.99, 10],      outputRange: [1, 1, 0],      extrapolate: 'clamp'    })    return (      <View style={styles.container}>        <TouchableWithoutFeedback onPress={this.explode} style={styles.container}>           <View style={{transform: [{scale: .8}]}}>            <Surface width={deviceWidth} height={deviceHeight}>              <Group x={75} y={200}>             //是一个心形的图像                <AnimatedShape                  d={HEART_SVG}                  x={heart_x}                  y={heart_y}                  scale={heart_scale}                  fill={heart_fill}                />                <AnimatedCircle                  x={89}                  y={75}                  radius={150}                  scale={circle_scale}                  strokeWidth={circle_stroke_width}                  stroke={FILL_COLORS[2]}                  fill={circle_fill_colors}                  opacity={circle_opacity}                />                {this.getSmallExplosions(75, {x:89, y:75})}              </Group>            </Surface>          </View>        </TouchableWithoutFeedback>      </View>    );  }};class  AnimatedCircle  extends  Component{  render(){     var radius = this.props.radius;    var path = Path().moveTo(0, -radius)        .arc(0, radius * 2, radius)        .arc(0, radius * -2, radius)        .close();    return  React.createElement(AnimatedShape, React.__spread({},  this.props, {d: path}));  }}var styles = StyleSheet.create({  container: {    flex: 1,  }});