react-native-Art动画基础

Posted time_iter

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react-native-Art动画基础相关的知识,希望对你有一定的参考价值。

一:基础:
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,
  
);
  注意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>
        )
    


注意: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>
        )
    

注意: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>
        )
    

  注意: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>
        )
    

注意: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>
        )
    

   注意:使用了一个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>
        )
    

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

三:高级例子:
效果图:

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,
  
);

以上是关于react-native-Art动画基础的主要内容,如果未能解决你的问题,请参考以下文章

H5扇形

圆弧和扇形的加载动画-遁地龙卷风

自定义UI 绘制饼图

自定义UI 绘制饼图

React Native SVG描边动画

扇形导航菜单