Detailed description of the react-native ART plotting method, react-nativeart

Source: Internet
Author: User

Detailed description of the react-native ART plotting method, react-nativeart

Background

During the development of mobile applications, it is essential to draw basic 2D images or animations. However, considering that both Android and iOS have their own set of API solutions, a more common technical solution is adopted, which is more conducive to the dual-platform compatibility of code.

Art is a Node style CommonJS module designed to be compatible with multiple browsers. Based on it, Facebook developed React-art, which encapsulates art so that it can be used by react. js, that is, it implements the front-end svg library. However, considering react. the JSX Syntax of js already supports inserting and so on svg tags directly into the dom (of course, this is not the react-art library). In addition, there is an HTML canvas. Therefore, on the front end, react-art is not irreplaceable.

However, on the Mobile End, considering the cross-platform requirements and the accumulation of web technology, react-art has become a ready-to-use solution for drawing graphics. React-native adds react-art support on ios and android platforms in 0.10.0 and 0.18.0 respectively.

Sample Code

The difference between React. js and React-Native lies only in the ART acquisition described below. Then, this example can be applied on both the Web and mobile terminals. Official example of react-art: Vector-Widget

The Vector-Widget achieves extra rotation and accelerates the response of Mouse clicking events. Click acceleration is displayed on the Web end, but it is invalid on the mobile end because React Native does not process the onMouseDown and onMouseUp attributes in the Group. This article focuses on the implementation of static svg, just ignore the animation effect for the moment.

ART

In react native, ART is a very important library that makes it very cool to draw and animation possible. It should be noted that, when React Native introduces ART, Android contains the ART library by default, and IOS needs to add a dependency library separately.

Add dependency library for ios

1. Use xcode to open the iOS project in React-native, right-click the 'libraries' directory and choose 'add Files to project name' --> 'node _ modules/react-native/Libraries/ART. xcodeproj' add;

2. Select the project root directory --> click 'build phases' --> click 'link Binary With Libraries' --> click '+' in the lower-left corner --> select 'libart. A' to add.

Basic Components

There are 7 components exposed by ART. This article describes four commonly used components: Surface, Group, Shape, and Text.

  • Surface-A rendered area of a rectangle, a container for other elements
  • Group-supports multiple shapes, text, and other groups
  • Shape-Shape Definition, can be filled
  • Text-Text Shape Definition

Attribute

Surface

  • Width: the width of the rendering area.
  • Height: defines the height of the rendering area.

Shape

  • D: Define the drawing path.
  • Stroke: stroke color
  • StrokeWidth: stroke width
  • StrokeDash: defines the dotted line
  • Fill: fill color

Text

  • Funt: font style, which defines the font, size, and whether to bold, for example, bold 35px Heiti SC

Path

  • MoveTo (x, y): Move to coordinates (x, y)
  • LineTo (x, y): connect to (x, y)
  • Arc (): draw an arc
  • Close (): closed space

Sample Code

Draw a straight line

Import React from 'react 'import {View, ART} from 'react-native' export default class Line extends react. component {render () {const path = ART. path (); path. moveTo (); // move the start point to the () default () path. lineTo (); // link to the target point (, 1) return (<View style = {this. props. style }>< ART. surface width = {300} height = {2 }> <ART. shape d = {path} stroke = "#000000" strokeWidth = {1}/> </ART. surface ></ View> )}}

Draw dotted lines

Understand strokeDash parameters,

[]: Indicates that the 10-pixel solid line is blank in 5 pixels.

[10, 5, 20, 5]: 10-pixel solid lines are painted. 5-pixel white spaces are painted. 20-pixel solid lines and 5-pixel white spaces are painted.

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>    )  }}

Draw a rectangle

First, draw three edges through lineTo and use close to link the fourth edge. Fill the fill color.

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>    )  }}

Circle

Measure the test taker's knowledge about the use of arc (x, y, radius) and the relative distance between the endpoint and the start point.

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>    )  }}

Draw text

Learn how to use the funt attribute. The rule is "font width and font size"

Note: The font should support the path attribute, but the implementation bug does not take effect. Android can solve this problem by modifying the source code. IOS does not look at the source code.

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

Draw slice

Here, we need to use arc to draw the path.

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} />;  }}

Sample Code:

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>    )  }}

Comprehensive example

Related code:

/*** 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 0-31.9 25.5-20.6 46-46.1 46.2 0 35.5 11.7 42.4 28.4C94.9 11 111.3-0.8 130.4-0.8 "var HEART_COLOR = 'rgb (, 38, 204,204,204) '; var GRAY_HEART_COLOR = "rgb (212,106,191, 1)"; var FILL_COLORS = ['rgba (,)', 'rgba (, 1 )', 'rgba (204,142,245, 1) ', 'rgba (204,142,245, 1)', 'rgba (204,142,245, 1) ', 'rgba (,)']; var participant _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; // use Animated. createAnimatedComponent creates a dialog for other components // creates a new gray image 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], extrapoate: 'clam'}); var moveUp = this. state. animation. interpolate ({inputRange: [0, 5.99, 14], outputRange: [0, 0,-15], extrapoate: 'clam'}); var moveDown = this. state. animation. interpolate ({inputRange: [0, 5.99, 14], outputRange: [0, 0, 15], extrapoate: 'clam'}); var color_top_particle = this. state. animation. interpolate ({inputRange: [6, 8, 10, 12, 17, 21], outputRange: shuffleArray (participant _colors)}) var color_bottom_particle = this. state. animation. interpolate ({inputRange: [6, 8, 10, 12, 17, 21], outputRange: shuffleArray (participant _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], extrapoate: 'clam'}); var heart_fill = this. state. animation. interpolate ({inputRange: [0, 2], outputRange: [GRAY_HEART_COLOR, HEART_COLOR], extrapoate: 'clam'}) var heart_x = partition ({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], extrapoate: 'clam'}); var circle_stroke_width = this. state. animation. interpolate ({inputRange: [0, 5.99, 6, 7, 10], outputRange: [0, 0, 15, 8, 0], extrapoate: 'clam '}); var circle_fill_colors = this. state. animation. interpolate ({inputRange: [1, 2, 3, 4, 4.99, 5], outputRange: FILL_COLORS, extrapoate: 'clam'}) var circle_opacity = this. state. animation. interpolate ({inputRange: [1, 9.99, 10], outputRange: [1, 1, 0], extrapoate: 'clam'}) 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 ,}});

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.