国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

react-native之ART繪圖方法詳解

來源:懂視網 責編:小采 時間:2020-11-27 22:33:04
文檔

react-native之ART繪圖方法詳解

react-native之ART繪圖方法詳解:背景 在移動應用的開發過程中,繪制基本的二維圖形或動畫是必不可少的。然而,考慮到Android和iOS均有一套各自的API方案,因此采用一種更普遍接受的技術方案,更有利于代碼的雙平臺兼容。 art是一個旨在多瀏覽器兼容的Node style CommonJS模塊。在它
推薦度:
導讀react-native之ART繪圖方法詳解:背景 在移動應用的開發過程中,繪制基本的二維圖形或動畫是必不可少的。然而,考慮到Android和iOS均有一套各自的API方案,因此采用一種更普遍接受的技術方案,更有利于代碼的雙平臺兼容。 art是一個旨在多瀏覽器兼容的Node style CommonJS模塊。在它

背景

在移動應用的開發過程中,繪制基本的二維圖形或動畫是必不可少的。然而,考慮到Android和iOS均有一套各自的API方案,因此采用一種更普遍接受的技術方案,更有利于代碼的雙平臺兼容。

art是一個旨在多瀏覽器兼容的Node style CommonJS模塊。在它的基礎上,Facebook又開發了React-art ,封裝art,使之可以被react.js所使用,即實現了前端的svg庫。然而,考慮到react.js的JSX語法,已經支持將 等等svg標簽直接插入到dom中(當然此時使用的就不是react-art庫了)此外還有HTML canvas的存在,因此,在前端上,react-art并非不可替代。

然而,在移動端,考慮到跨平臺的需求,加之web端的技術積累,react-art成為了現成的繪制圖形的解決方案。react-native分別在0.10.0和0.18.0上添加了ios和android平臺上對react-art的支持。

示例代碼

React.js和React-Native的區別,只在于下文所述的ART獲取上,然后該例子就可以同時應用在Web端和移動端上了。react-art自帶的官方例子:Vector-Widget

Vector-Widget額外實現了旋轉,以及鼠標點擊事件的旋轉加速響應。Web端可以看到點擊加速,但是在移動端無效,原因是React Native并未對Group中onMouseDown和onMouseUp屬性作處理。本文著重于靜態svg的實現,暫時無視動畫部分效果即可。

ART

在react native中ART是個非常重要的庫,它讓非常酷炫的繪圖及動畫變成了可能。需要注意的是,在React Native引入ART過程中,Android默認就包含ART庫,IOS需要單獨添加依賴庫。

ios添加依賴庫

1、使用xcode中打開React-native中的iOS項目,選中‘Libraries'目錄 ——> 右鍵選擇‘Add Files to 項目名稱' ——> ‘node_modules/react-native/Libraries/ART/ART.xcodeproj' 添加;

這里寫圖片描述

2、選中項目根目錄 ——> 點擊'Build Phases‘ ——> 點擊‘Link Binary With Libraries' ——> 點擊左下方‘+' ——> 選中‘libART.a'添加。

這里寫圖片描述

基礎組件

ART暴露的組件共有7個,本文介紹常用的四個組件:Surface、Group、Shape、Text。

  • Surface - 一個矩形可渲染的區域,是其他元素的容器
  • Group - 可容納多個形狀、文本和其他的分組
  • Shape - 形狀定義,可填充
  • Text - 文本形狀定義
  • 屬性

    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 from 'react'
    import {
     View,
     ART
    } from 'react-native'
    
    export default class Line extends React.Component{
    
     render(){
    
     const path = ART.Path();
     path.moveTo(1,1); //將起始點移動到(1,1) 默認(0,0)
     path.lineTo(300,1); //連線到目標點(300,1)
    
     return(
     <View style={this.props.style}>
     <ART.Surface width={300} height={2}>
     <ART.Shape d={path} stroke="#000000" strokeWidth={1} />
     </ART.Surface>
     </View>
     )
     }
    }
    
    

    繪制虛線

    了解strokeDash的參數,

    [10,5] : 表示繪10像素實線在繪5像素空白,如此循環

    [10,5,20,5] : 表示繪10像素實線在繪制5像素空白在繪20像素實線及5像素空白

    這里寫圖片描述

    import React from 'react'
    import {
     View,
     ART
    } from 'react-native'
    
    const {Surface, Shape, Path} = ART;
    
    export default class DashLine extends React.Component{
    
     render(){
    
     const path = Path()
     .moveTo(1,1)
     .lineTo(300,1);
    
     return(
     <View style={this.props.style}>
     <Surface width={300} height={2}>
     <Shape d={path} stroke="#000000" strokeWidth={2} strokeDash={[10,5]}/>
     </Surface>
     </View>
     )
     }
    }
    
    

    繪制矩形

    首先通過lineTo繪制三條邊,在使用close鏈接第四條邊。fill做顏色填充.

    這里寫圖片描述

    import React from 'react'
    import {
     View,
     ART
    } from 'react-native'
    
    const {Surface, Shape, Path} = ART;
    
    export default class Rect extends React.Component{
    
     render(){
    
     const path = new Path()
     .moveTo(1,1)
     .lineTo(1,99)
     .lineTo(99,99)
     .lineTo(99,1)
     .close();
    
     return(
     <View style={this.props.style}>
     <Surface width={100} height={100}>
     <Shape d={path} stroke="#000000" fill="#892265" strokeWidth={1} />
     </Surface>
     </View>
     )
     }
    }
    
    

    繪圓

    了解arc(x,y,radius)的使用, 終點坐標距離起點坐標的相對距離。

    這里寫圖片描述

    import React from 'react'
    import {
     View,
     ART
    } from 'react-native'
    
    const {Surface, Shape, Path} = ART;
    
    export default class Circle extends React.Component{
    
     render(){
    
     const path = new Path()
     .moveTo(50,1)
     .arc(0,99,25)
     .arc(0,-99,25)
     .close();
    
    
     return(
     <View style={this.props.style}>
     <Surface width={100} height={100}>
     <Shape d={path} stroke="#000000" strokeWidth={1}/>
     </Surface>
     </View>
     )
     }
    }
    
    

    繪制文字

    了解funt屬性的使用,規則是“粗細 字號 字體”

    注意: 字體應該是支持path屬性的,應該是實現bug并沒有不生效。 Android通過修改源碼是可以解決的,IOS沒看源碼。

    這里寫圖片描述

    import React, {Component} from 'react';
    import {
     AppRegistry,
     StyleSheet,
     ART,
     View
    } from 'react-native';
    
    const {Surface, Text, Path} = ART;
    
    export default class ArtTextView extends Component {
    
     render() {
    
     return (
     <View style={styles.container}>
     <Surface width={100} height={100}>
     <Text strokeWidth={1} stroke="#000" font="bold 35px Heiti SC" path={new Path().moveTo(40,40).lineTo(99,10)} >React</Text>
     </Surface>
    
     </View>
    
     );
     }
    }
    
    const styles = StyleSheet.create({
     container: {
     flex: 1,
     justifyContent: 'center',
     alignItems: 'center',
     backgroundColor: '#F5FCFF',
     },
    
    });
    
    

    繪制扇形

    這里寫圖片描述

    在這里需要使用arc做路徑繪制。

    Wedge.js

    import React, { Component, PropTypes } from 'react';
    import { ART } from 'react-native';
    const { Shape, Path } = ART;
    
    /**
     * Wedge is a React component for drawing circles, wedges and arcs. Like other
     * ReactART components, it must be used in a <Surface>.
     */
    export default class Wedge extends Component<void, any, any> {
    
     static propTypes = {
     outerRadius: PropTypes.number.isRequired,
     startAngle: PropTypes.number.isRequired,
     endAngle: PropTypes.number.isRequired,
     originX: PropTypes.number.isRequired,
     originY: PropTypes.number.isRequired,
     innerRadius: PropTypes.number,
     };
    
    
     constructor(props : any) {
     super(props);
     (this:any).circleRadians = Math.PI * 2;
     (this:any).radiansPerDegree = Math.PI / 180;
     (this:any)._degreesToRadians = this._degreesToRadians.bind(this);
     }
    
     /**
     * _degreesToRadians(degrees)
     *
     * Helper function to convert degrees to radians
     *
     * @param {number} degrees
     * @return {number}
     */
     _degreesToRadians(degrees : number) : number {
     if (degrees !== 0 && degrees % 360 === 0) { // 360, 720, etc.
     return (this:any).circleRadians;
     }
     return degrees * (this:any).radiansPerDegree % (this:any).circleRadians;
     }
    
     /**
     * _createCirclePath(or, ir)
     *
     * Creates the ReactART Path for a complete circle.
     *
     * @param {number} or The outer radius of the circle
     * @param {number} ir The inner radius, greater than zero for a ring
     * @return {object}
     */
     _createCirclePath(or : number, ir : number) : Path {
     const path = new Path();
    
     path.move(0, or)
     .arc(or * 2, 0, or)
     .arc(-or * 2, 0, or);
    
     if (ir) {
     path.move(or - ir, 0)
     .counterArc(ir * 2, 0, ir)
     .counterArc(-ir * 2, 0, ir);
     }
    
     path.close();
    
     return path;
     }
    
     /**
     * _createArcPath(sa, ea, ca, or, ir)
     *
     * Creates the ReactART Path for an arc or wedge.
     *
     * @param {number} startAngle The starting degrees relative to 12 o'clock
     * @param {number} endAngle The ending degrees relative to 12 o'clock
     * @param {number} or The outer radius in pixels
     * @param {number} ir The inner radius in pixels, greater than zero for an arc
     * @return {object}
     */
     _createArcPath(originX : number, originY : number, startAngle : number, endAngle : number, or : number, ir : number) : Path {
     const path = new Path();
    
     // angles in radians
     const sa = this._degreesToRadians(startAngle);
     const ea = this._degreesToRadians(endAngle);
    
     // central arc angle in radians
     const ca = sa > ea ? (this:any).circleRadians - sa + ea : ea - sa;
    
     // cached sine and cosine values
     const ss = Math.sin(sa);
     const es = Math.sin(ea);
     const sc = Math.cos(sa);
     const ec = Math.cos(ea);
    
     // cached differences
     const ds = es - ss;
     const dc = ec - sc;
     const dr = ir - or;
    
     // if the angle is over pi radians (180 degrees)
     // we will need to let the drawing method know.
     const large = ca > Math.PI;
    
     // TODO (sema) Please improve theses comments to make the math
     // more understandable.
     //
     // Formula for a point on a circle at a specific angle with a center
     // at (0, 0):
     // x = radius * Math.sin(radians)
     // y = radius * Math.cos(radians)
     //
     // For our starting point, we offset the formula using the outer
     // radius because our origin is at (top, left).
     // In typical web layout fashion, we are drawing in quadrant IV
     // (a.k.a. Southeast) where x is positive and y is negative.
     //
     // The arguments for path.arc and path.counterArc used below are:
     // (endX, endY, radiusX, radiusY, largeAngle)
    
     path.move(or + or * ss, or - or * sc) // move to starting point
     .arc(or * ds, or * -dc, or, or, large) // outer arc
     .line(dr * es, dr * -ec); // width of arc or wedge
    
     if (ir) {
     path.counterArc(ir * -ds, ir * dc, ir, ir, large); // inner arc
     }
    
     return path;
     }
    
     render() : any {
     // angles are provided in degrees
     const startAngle = this.props.startAngle;
     const endAngle = this.props.endAngle;
     // if (startAngle - endAngle === 0) {
     // return null;
     // }
    
     // radii are provided in pixels
     const innerRadius = this.props.innerRadius || 0;
     const outerRadius = this.props.outerRadius;
    
     const { originX, originY } = this.props;
    
     // sorted radii
     const ir = Math.min(innerRadius, outerRadius);
     const or = Math.max(innerRadius, outerRadius);
    
     let path;
     if (endAngle >= startAngle + 360) {
     path = this._createCirclePath(or, ir);
     } else {
     path = this._createArcPath(originX, originY, startAngle, endAngle, or, ir);
     }
    
     return <Shape {...this.props} d={path} />;
     }
    }
    
    

    示例代碼:

    import React from 'react'
    import {
     View,
     ART
    } from 'react-native'
    
    const {Surface} = ART;
    import Wedge from './Wedge'
    
    export default class Fan extends React.Component{
    
     render(){
    
     return(
     <View style={this.props.style}>
     <Surface width={100} height={100}>
     <Wedge
     outerRadius={50}
     startAngle={0}
     endAngle={60}
     originX={50}
     originY={50}
     fill="blue"/>
    
     </Surface>
     </View>
     )
     }
    }
    
    

    綜合示例

    這里寫圖片描述

    相關代碼:

    /**
     * Sample React Native App
     * https://github.com/facebook/react-native
     * @flow
     */
    
    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 ArtAnimView 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);
     }
    }
    
    var styles = StyleSheet.create({
     container: {
     flex: 1,
     }
    });
    
    

    聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文檔

    react-native之ART繪圖方法詳解

    react-native之ART繪圖方法詳解:背景 在移動應用的開發過程中,繪制基本的二維圖形或動畫是必不可少的。然而,考慮到Android和iOS均有一套各自的API方案,因此采用一種更普遍接受的技術方案,更有利于代碼的雙平臺兼容。 art是一個旨在多瀏覽器兼容的Node style CommonJS模塊。在它
    推薦度:
    標簽: 繪制 art 繪制圖形
    • 熱門焦點

    最新推薦

    猜你喜歡

    熱門推薦

    專題
    Top
    主站蜘蛛池模板: 国产成人精品三区 | 香蕉成人啪国产精品视频综合网 | 成人国产精品一区二区网站 | 国产亚洲精品成人婷婷久久小说 | 国产a毛片 | 成人精品视频在线 | 国产91精品黄网在线观看 | 国产大片91精品免费观看不卡 | 国产在线播放免费 | 国产亚洲欧美一区 | 欧美日韩一二区 | 黑丝白浆| 美女视频黄a视频免费全过程在线 | 九草伊人| 欧美一区二区在线播放 | 欧美亚洲另类综合 | 国产一区二区精品 | 国产日产欧美精品一区二区三区 | 欧美日韩一区二区三区四区 | 亚洲精品午夜国产va久久成人 | 国产成人精品一区二区三区 | 午夜日韩久久影院 | 不卡一区二区在线观看 | 国产亚洲午夜精品a一区二区 | 亚洲精品免费视频 | 日韩亚洲欧美在线 | 国产精品日韩精品 | 精品综合一区二区三区 | 国产中文在线观看 | 免费观看日韩大尺码观看 | 在线不欧美| 亚洲精品视频免费在线观看 | 国产激情一区二区三区在线观看 | 精品在线免费观看 | 国产一区 在线播放 | 国产精品亚洲综合一区 | 国产欧美日韩另类 | 国产一级α片 | 国产日产欧美精品一区二区三区 | 日韩在线视频在线观看 | 亚洲欧美日韩综合精品网 |