react-native-Art动画基础

    xiaoxiao2021-03-26  4

    react-native-Art动画基础

    作者:tiem_erhu

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

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

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

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

    三:高级例子:  效果图:

    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, } });
    转载请注明原文地址: https://ju.6miu.com/read-500369.html

    最新回复(0)