├── .watchmanconfig
├── app.json
├── .babelrc
├── App.js
├── App.test.js
├── .gitignore
├── .eslintrc.js
├── src
├── Line.js
├── DashLine.js
├── Circle.js
├── Fan.js
├── FillRect.js
├── RadialGradientView.js
├── ArtText.js
├── Group.js
├── TransformView.js
├── LinearGradientView.js
├── index.js
└── Wedge.js
├── package.json
├── .flowconfig
└── README.md
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "expo": {
3 | "sdkVersion": "25.0.0"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["babel-preset-expo"],
3 | "env": {
4 | "development": {
5 | "plugins": ["transform-react-jsx-source"]
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Home from './src'
4 |
5 | export default class App extends React.Component {
6 | render() {
7 | return (
8 |
9 | );
10 | }
11 | }
--------------------------------------------------------------------------------
/App.test.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import App from './App';
3 |
4 | import renderer from 'react-test-renderer';
5 |
6 | it('renders without crashing', () => {
7 | const rendered = renderer.create().toJSON();
8 | expect(rendered).toBeTruthy();
9 | });
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # expo
4 | .expo/
5 | .idea/
6 |
7 | # dependencies
8 | /node_modules
9 |
10 | # misc
11 | .env.local
12 | .env.development.local
13 | .env.test.local
14 | .env.production.local
15 |
16 | npm-debug.log*
17 | yarn-debug.log*
18 | yarn-error.log*
19 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "env": {
3 | "node": true,
4 | "es6": true
5 | },
6 | "extends": "eslint:recommended",
7 | "parserOptions": {
8 | "ecmaFeatures": {
9 | "experimentalObjectRestSpread": true,
10 | "jsx": true
11 | },
12 | "sourceType": "module"
13 | },
14 | "plugins": [
15 | "react"
16 | ],
17 | "rules": {
18 | "indent": [
19 | "error",
20 | 4
21 | ],
22 | "linebreak-style": [
23 | "error",
24 | "unix"
25 | ],
26 | "quotes": [
27 | "error",
28 | "single"
29 | ],
30 | "semi": [
31 | "error",
32 | "always"
33 | ]
34 | }
35 | };
--------------------------------------------------------------------------------
/src/Line.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | export default class Line extends React.Component{
9 |
10 | static navigationOptions = {
11 | title: 'Line',
12 | };
13 |
14 | render(){
15 |
16 | const path = ART.Path();
17 | path.moveTo(1,1); //将起始点移动到(1,1) 默认(0,0)
18 | path.lineTo(300,1); //连线到目标点(300,1)
19 |
20 | return(
21 |
22 |
23 |
24 |
25 |
26 | )
27 | }
28 | }
29 |
30 | const styles = StyleSheet.create({
31 | container: {
32 | flex: 1,
33 | backgroundColor: '#fff',
34 | alignItems: 'center',
35 | justifyContent: 'center',
36 | },
37 | });
--------------------------------------------------------------------------------
/src/DashLine.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | const {Surface, Shape, Path} = ART;
9 |
10 | export default class DashLine extends React.Component{
11 |
12 | static navigationOptions = {
13 | title: 'DashLine',
14 | };
15 |
16 | render(){
17 |
18 | const path = Path()
19 | .moveTo(1,1)
20 | .lineTo(300,1);
21 |
22 | return(
23 |
24 |
25 |
26 |
27 |
28 | )
29 | }
30 | }
31 |
32 | const styles = StyleSheet.create({
33 | container: {
34 | flex: 1,
35 | backgroundColor: '#fff',
36 | alignItems: 'center',
37 | justifyContent: 'center',
38 | },
39 | });
--------------------------------------------------------------------------------
/src/Circle.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | const {Surface, Shape, Path} = ART;
9 |
10 | export default class Circle extends React.Component{
11 |
12 | static navigationOptions = {
13 | title: 'Circle',
14 | };
15 |
16 | render(){
17 |
18 | const path = new Path()
19 | .moveTo(50,1)
20 | .arc(0,99,25)
21 | .arc(0,-99,25)
22 | .close();
23 |
24 |
25 | return(
26 |
27 |
28 |
29 |
30 |
31 | )
32 | }
33 | }
34 |
35 | const styles = StyleSheet.create({
36 | container: {
37 | flex: 1,
38 | backgroundColor: '#fff',
39 | alignItems: 'center',
40 | justifyContent: 'center',
41 | },
42 | });
--------------------------------------------------------------------------------
/src/Fan.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | const {Surface} = ART;
9 | import Wedge from './Wedge'
10 |
11 | export default class Fan extends React.Component{
12 |
13 | static navigationOptions = {
14 | title: 'Fan',
15 | };
16 |
17 | render(){
18 |
19 | return(
20 |
21 |
22 |
29 |
30 |
31 |
32 | )
33 | }
34 | }
35 |
36 | const styles = StyleSheet.create({
37 | container: {
38 | flex: 1,
39 | backgroundColor: '#fff',
40 | alignItems: 'center',
41 | justifyContent: 'center',
42 | },
43 | });
--------------------------------------------------------------------------------
/src/FillRect.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | const {Surface, Shape, Path} = ART;
9 |
10 | export default class FillRect extends React.Component{
11 |
12 | static navigationOptions = {
13 | title: 'FillRect',
14 | };
15 |
16 | render(){
17 |
18 | const path = new Path()
19 | .moveTo(1,1)
20 | .lineTo(1,99)
21 | .lineTo(99,99)
22 | .lineTo(99,1)
23 | .close();
24 |
25 | return(
26 |
27 |
28 |
29 |
30 |
31 | )
32 | }
33 | }
34 |
35 | const styles = StyleSheet.create({
36 | container: {
37 | flex: 1,
38 | backgroundColor: '#fff',
39 | alignItems: 'center',
40 | justifyContent: 'center',
41 | },
42 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "React-Native-ART-Sample",
3 | "version": "0.1.0",
4 | "private": true,
5 | "devDependencies": {
6 | "eslint": "^4.18.1",
7 | "eslint-plugin-react": "^7.7.0",
8 | "eslint-plugin-react-native": "^3.2.1",
9 | "jest-expo": "25.0.0",
10 | "react-native-scripts": "1.11.1",
11 | "react-test-renderer": "16.2.0"
12 | },
13 | "main": "./node_modules/react-native-scripts/build/bin/crna-entry.js",
14 | "scripts": {
15 | "start": "react-native-scripts start",
16 | "eject": "react-native-scripts eject",
17 | "android": "react-native-scripts android",
18 | "ios": "react-native-scripts ios",
19 | "test": "node node_modules/jest/bin/jest.js",
20 | "lint": "eslint --ext .js ./src --fix"
21 | },
22 | "jest": {
23 | "preset": "jest-expo"
24 | },
25 | "dependencies": {
26 | "expo": "^25.0.0",
27 | "react": "16.2.0",
28 | "react-native": "0.52.0",
29 | "react-navigation": "^1.1.2"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/RadialGradientView.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | View,
4 | ART, StyleSheet
5 | } from 'react-native';
6 |
7 | const {Surface, Shape, Path,RadialGradient} = ART;
8 |
9 |
10 | export default class RadialGradientView extends React.Component{
11 |
12 | static navigationOptions = {
13 | title: 'Linear Gradient',
14 | };
15 |
16 | render(){
17 |
18 | const path = new Path()
19 | .moveTo(1,1)
20 | .lineTo(1,99)
21 | .lineTo(99,99)
22 | .lineTo(99,1)
23 | .close();
24 |
25 | return(
26 |
27 |
28 |
29 |
30 |
31 | )
32 | }
33 | }
34 |
35 | const styles = StyleSheet.create({
36 | container: {
37 | flex: 1,
38 | backgroundColor: '#fff',
39 | alignItems: 'center',
40 | justifyContent: 'center',
41 | },
42 | });
--------------------------------------------------------------------------------
/src/ArtText.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | const {Surface, Text, Path, LinearGradient} = ART;
9 |
10 | export default class ArtText extends React.Component{
11 |
12 | static navigationOptions = {
13 | title: 'ArtText',
14 | };
15 |
16 | render(){
17 |
18 | return(
19 |
20 |
21 | 虚线文字
22 |
23 |
24 |
25 | 渐变文字
26 |
27 |
28 | )
29 | }
30 |
31 | }
32 |
33 | const styles = StyleSheet.create({
34 | container: {
35 | flex: 1,
36 | backgroundColor: '#fff',
37 | alignItems: 'center',
38 | justifyContent: 'center',
39 | },
40 | });
--------------------------------------------------------------------------------
/src/Group.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet
6 | } from 'react-native'
7 |
8 | const {Surface, Shape,Text, Path,Group} = ART;
9 |
10 | export default class GroupView extends React.Component{
11 |
12 | static navigationOptions = {
13 | title: 'Group',
14 | };
15 |
16 | render(){
17 |
18 | const pathRect = new Path()
19 | .moveTo(1,1)
20 | .lineTo(1,99)
21 | .lineTo(99,99)
22 | .lineTo(99,1)
23 | .close();
24 |
25 | const pathCircle = new Path()
26 | .moveTo(50,1)
27 | .arc(0,99,25)
28 | .arc(0,-99,25)
29 | .close();
30 |
31 | const pathText = new Path()
32 | .moveTo(40,5)
33 | .lineTo(40,99);
34 |
35 |
36 | return(
37 |
38 |
39 |
40 |
41 |
42 | Swipe
43 |
44 |
45 |
46 | )
47 | }
48 | }
49 |
50 | const styles = StyleSheet.create({
51 | container: {
52 | flex: 1,
53 | backgroundColor: '#fff',
54 | alignItems: 'center',
55 | justifyContent: 'center',
56 | },
57 | });
--------------------------------------------------------------------------------
/src/TransformView.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import {
3 | View,
4 | ART,
5 | StyleSheet,
6 | Button
7 | } from 'react-native'
8 |
9 | const {Surface,Transform,Shape,Path} = ART;
10 |
11 | export default class TransformView extends React.Component{
12 |
13 | static navigationOptions = {
14 | title: 'Transform',
15 | };
16 |
17 |
18 | // 构造
19 | constructor(props) {
20 | super(props);
21 | // 初始状态
22 | this.state = {
23 | rotation : 0
24 | };
25 | }
26 |
27 | render(){
28 | const path = new Path()
29 | .moveTo(1,1)
30 | .lineTo(1,99)
31 | .lineTo(99,99)
32 | .lineTo(99,1)
33 | .close();
34 |
35 | const RING_TWO_ROTATE = new Transform().translate(50.000000, 89.000000).rotate(-240.000000).translate(-84.000000, -89.000000);
36 |
37 | return(
38 |
39 |
40 |
41 |
42 |
43 |
44 |
52 |
53 | )
54 | }
55 | }
56 |
57 | const styles = StyleSheet.create({
58 | container: {
59 | flex: 1,
60 | backgroundColor: '#fff',
61 | alignItems: 'center',
62 | justifyContent: 'center',
63 | },
64 | });
--------------------------------------------------------------------------------
/src/LinearGradientView.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | View,
4 | ART, StyleSheet,UIManager
5 | } from 'react-native';
6 |
7 | const {Surface, Shape, Path,LinearGradient} = ART;
8 |
9 | export default class LinearGradientView extends React.Component{
10 |
11 | constructor(props) {
12 | super(props);
13 | // 初始状态
14 | this.state = {
15 | container : {
16 | x:0,
17 | y:0,
18 | width:0,
19 | height:0,
20 | pageX:0,
21 | pageY:0
22 | }
23 | };
24 | }
25 |
26 | static navigationOptions = {
27 | title: 'Linear Gradient',
28 | };
29 |
30 |
31 | render(){
32 |
33 | const container = this.state.container
34 | const path = new Path()
35 | .move(0,0)
36 | .line(container.width,0)
37 | .line(container.width,container.height)
38 | .lineTo(0,container.height)
39 | .close();
40 |
41 | return(
42 |
43 | {
44 | UIManager.measure(e.target, (x, y, width, height, pageX, pageY) => {
45 | this.setState({
46 | container: {
47 | x,
48 | y,
49 | width,
50 | height,
51 | pageX,
52 | pageY
53 | }
54 | })
55 | })
56 | }}>
57 |
58 |
59 |
60 |
61 |
62 |
63 | )
64 | }
65 | }
66 |
67 | const styles = StyleSheet.create({
68 | container: {
69 | flex: 1,
70 | backgroundColor: '#fff'
71 | },
72 | });
--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | ; We fork some components by platform
3 | .*/*[.]android.js
4 |
5 | ; Ignore templates for 'react-native init'
6 | /node_modules/react-native/local-cli/templates/.*
7 |
8 | ; Ignore RN jest
9 | /node_modules/react-native/jest/.*
10 |
11 | ; Ignore RNTester
12 | /node_modules/react-native/RNTester/.*
13 |
14 | ; Ignore the website subdir
15 | /node_modules/react-native/website/.*
16 |
17 | ; Ignore the Dangerfile
18 | /node_modules/react-native/danger/dangerfile.js
19 |
20 | ; Ignore Fbemitter
21 | /node_modules/fbemitter/.*
22 |
23 | ; Ignore "BUCK" generated dirs
24 | /node_modules/react-native/\.buckd/
25 |
26 | ; Ignore unexpected extra "@providesModule"
27 | .*/node_modules/.*/node_modules/fbjs/.*
28 |
29 | ; Ignore polyfills
30 | /node_modules/react-native/Libraries/polyfills/.*
31 |
32 | ; Ignore various node_modules
33 | /node_modules/react-native-gesture-handler/.*
34 | /node_modules/expo/.*
35 | /node_modules/react-navigation/.*
36 | /node_modules/xdl/.*
37 | /node_modules/reqwest/.*
38 | /node_modules/metro-bundler/.*
39 |
40 | [include]
41 |
42 | [libs]
43 | node_modules/react-native/Libraries/react-native/react-native-interface.js
44 | node_modules/react-native/flow/
45 | node_modules/expo/flow/
46 |
47 | [options]
48 | emoji=true
49 |
50 | module.system=haste
51 |
52 | module.file_ext=.js
53 | module.file_ext=.jsx
54 | module.file_ext=.json
55 | module.file_ext=.ios.js
56 |
57 | munge_underscores=true
58 |
59 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub'
60 |
61 | suppress_type=$FlowIssue
62 | suppress_type=$FlowFixMe
63 | suppress_type=$FlowFixMeProps
64 | suppress_type=$FlowFixMeState
65 | suppress_type=$FixMe
66 |
67 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)
68 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(5[0-6]\\|[1-4][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native_oss[a-z,_]*\\)?)\\)?:? #[0-9]+
69 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy
70 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
71 |
72 | unsafe.enable_getters_and_setters=true
73 |
74 | [version]
75 | ^0.56.0
76 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | View,
4 | Button,
5 | StyleSheet
6 | } from 'react-native';
7 |
8 | import { StackNavigator } from 'react-navigation';
9 |
10 | import ArtText from './ArtText';
11 | import Circle from './Circle';
12 | import DashLine from './DashLine';
13 | import Fan from './Fan';
14 | import FillRect from './FillRect';
15 | import GroupView from './Group';
16 | import Line from './Line';
17 | import LinearGradientView from './LinearGradientView';
18 | import RadialGradientView from './RadialGradientView';
19 | import TransformView from './TransformView';
20 |
21 | class Home extends React.Component {
22 |
23 | render() {
24 | return (
25 |
26 |
27 |
33 |
34 |
35 |
41 |
42 |
48 |
49 |
50 |
56 |
57 |
58 |
64 |
65 |
66 |
72 |
73 |
79 |
80 |
86 |
87 |
93 |
94 |
100 |
101 |
102 | );
103 | }
104 | }
105 |
106 | const RootStack = StackNavigator({
107 | Home: {
108 | screen: Home,
109 | },
110 | ArtText: {
111 | screen: ArtText
112 | },
113 | Circle: {
114 | screen: Circle
115 | },
116 | DashLine: {
117 | screen: DashLine
118 | },
119 | Fan: {
120 | screen: Fan
121 | },
122 | FillRect: {
123 | screen: FillRect
124 | },
125 | GroupView: {
126 | screen: GroupView
127 | },
128 | Line: {
129 | screen: Line
130 | },
131 | LinearGradientView: {
132 | screen: LinearGradientView
133 | },
134 | RadialGradientView: {
135 | screen: RadialGradientView
136 | },
137 | TransformView: {
138 | screen: TransformView
139 | }
140 | },{initialRouteName: 'Home'});
141 |
142 | export default class App extends React.Component {
143 | render() {
144 | return ;
145 | }
146 | }
147 |
148 | const styles = StyleSheet.create({
149 | container: {
150 | flex: 1,
151 | backgroundColor: '#fff',
152 | padding: 20
153 | },
154 | button: {
155 | marginBottom: 10
156 | }
157 | });
--------------------------------------------------------------------------------
/src/Wedge.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Taken from react-art, changed for RN.
3 | * Copyright 2013-2014 Facebook, Inc.
4 | * All rights reserved.
5 | *
6 | * This source code is licensed under the BSD-style license found in the
7 | * LICENSE file in the root directory of this source tree. An additional grant
8 | * of patent rights can be found in the PATENTS file in the same directory.
9 | *
10 | * @providesModule Wedge.art
11 | * @typechecks
12 | *
13 | * Example usage:
14 | *
20 | *
21 | * Additional optional property:
22 | * (Int) innerRadius
23 | *
24 | */
25 |
26 | import React, { Component, PropTypes } from 'react';
27 | import { ART } from 'react-native';
28 | const { Shape, Path } = ART;
29 |
30 | /**
31 | * Wedge is a React component for drawing circles, wedges and arcs. Like other
32 | * ReactART components, it must be used in a .
33 | */
34 | export default class Wedge extends Component {
35 |
36 | constructor(props : any) {
37 | super(props);
38 | (this:any).circleRadians = Math.PI * 2;
39 | (this:any).radiansPerDegree = Math.PI / 180;
40 | (this:any)._degreesToRadians = this._degreesToRadians.bind(this);
41 | }
42 |
43 | /**
44 | * _degreesToRadians(degrees)
45 | *
46 | * Helper function to convert degrees to radians
47 | *
48 | * @param {number} degrees
49 | * @return {number}
50 | */
51 | _degreesToRadians(degrees : number) : number {
52 | if (degrees !== 0 && degrees % 360 === 0) { // 360, 720, etc.
53 | return (this:any).circleRadians;
54 | }
55 | return degrees * (this:any).radiansPerDegree % (this:any).circleRadians;
56 | }
57 |
58 | /**
59 | * _createCirclePath(or, ir)
60 | *
61 | * Creates the ReactART Path for a complete circle.
62 | *
63 | * @param {number} or The outer radius of the circle
64 | * @param {number} ir The inner radius, greater than zero for a ring
65 | * @return {object}
66 | */
67 | _createCirclePath(or : number, ir : number) : Path {
68 | const path = new Path();
69 |
70 | path.move(0, or)
71 | .arc(or * 2, 0, or)
72 | .arc(-or * 2, 0, or);
73 |
74 | if (ir) {
75 | path.move(or - ir, 0)
76 | .counterArc(ir * 2, 0, ir)
77 | .counterArc(-ir * 2, 0, ir);
78 | }
79 |
80 | path.close();
81 |
82 | return path;
83 | }
84 |
85 | /**
86 | * _createArcPath(sa, ea, ca, or, ir)
87 | *
88 | * Creates the ReactART Path for an arc or wedge.
89 | *
90 | * @param {number} startAngle The starting degrees relative to 12 o'clock
91 | * @param {number} endAngle The ending degrees relative to 12 o'clock
92 | * @param {number} or The outer radius in pixels
93 | * @param {number} ir The inner radius in pixels, greater than zero for an arc
94 | * @return {object}
95 | */
96 | _createArcPath(originX : number, originY : number, startAngle : number, endAngle : number, or : number, ir : number) : Path {
97 | const path = new Path();
98 |
99 | // angles in radians
100 | const sa = this._degreesToRadians(startAngle);
101 | const ea = this._degreesToRadians(endAngle);
102 |
103 | // central arc angle in radians
104 | const ca = sa > ea ? (this:any).circleRadians - sa + ea : ea - sa;
105 |
106 | // cached sine and cosine values
107 | const ss = Math.sin(sa);
108 | const es = Math.sin(ea);
109 | const sc = Math.cos(sa);
110 | const ec = Math.cos(ea);
111 |
112 | // cached differences
113 | const ds = es - ss;
114 | const dc = ec - sc;
115 | const dr = ir - or;
116 |
117 | // if the angle is over pi radians (180 degrees)
118 | // we will need to let the drawing method know.
119 | const large = ca > Math.PI;
120 |
121 | // TODO (sema) Please improve theses comments to make the math
122 | // more understandable.
123 | //
124 | // Formula for a point on a circle at a specific angle with a center
125 | // at (0, 0):
126 | // x = radius * Math.sin(radians)
127 | // y = radius * Math.cos(radians)
128 | //
129 | // For our starting point, we offset the formula using the outer
130 | // radius because our origin is at (top, left).
131 | // In typical web layout fashion, we are drawing in quadrant IV
132 | // (a.k.a. Southeast) where x is positive and y is negative.
133 | //
134 | // The arguments for path.arc and path.counterArc used below are:
135 | // (endX, endY, radiusX, radiusY, largeAngle)
136 |
137 | path.move(or + or * ss, or - or * sc) // move to starting point
138 | .arc(or * ds, or * -dc, or, or, large) // outer arc
139 | .line(dr * es, dr * -ec); // width of arc or wedge
140 |
141 | if (ir) {
142 | path.counterArc(ir * -ds, ir * dc, ir, ir, large); // inner arc
143 | }
144 |
145 | return path;
146 | }
147 |
148 | render() : any {
149 | // angles are provided in degrees
150 | const startAngle = this.props.startAngle;
151 | const endAngle = this.props.endAngle;
152 | // if (startAngle - endAngle === 0) {
153 | // return null;
154 | // }
155 |
156 | // radii are provided in pixels
157 | const innerRadius = this.props.innerRadius || 0;
158 | const outerRadius = this.props.outerRadius;
159 |
160 | const { originX, originY } = this.props;
161 |
162 | // sorted radii
163 | const ir = Math.min(innerRadius, outerRadius);
164 | const or = Math.max(innerRadius, outerRadius);
165 |
166 | let path;
167 | if (endAngle >= startAngle + 360) {
168 | path = this._createCirclePath(or, ir);
169 | } else {
170 | path = this._createArcPath(originX, originY, startAngle, endAngle, or, ir);
171 | }
172 |
173 | return ;
174 | }
175 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## User
2 | ```
3 | yarn
4 | yarn start
5 | ```
6 |
7 | # react native art绘图入门
8 | 在React Native中ART是个非常重要的库,它让非常酷炫的绘图及动画变成了可能。但是可能是知道的人真的不多导致文档及少中文更少。很多都是把英文的参数列表翻译过来,也没有案例。于是决定出这样一份入门文档及可能遇到的坑,希望能够帮助到大家。本文的示例工程[https://github.com/xu-duqing/React-Native-ART-Sample](https://github.com/xu-duqing/React-Native-ART-Sample)
9 |
10 | ## 添加依赖
11 | >Android默认就包含ART库,IOS需要单独添加依赖库。
12 |
13 | 1. 右键点击项目 -> ‘Add Files to ProjectName -> 选择 node_modules/react-native/React/Libraries/ART/ART.xcodeproj’
14 | 2. 将 libART.a 添加到 Linked Frameworks and Libraries
15 |
16 | ## 基础组件
17 | ART暴露的组件有7个,这篇用到的有五个。先介绍即将用到的四个组件,之后在介绍另外三个。
18 |
19 | - Surface - 一个矩形可渲染的区域,是其他元素的容器!
20 | - Group - 可容纳多个形状、文本和其他的分组
21 | - Shape - 形状定义,可填充
22 | - Text - 文本形状定义
23 |
24 | ## props
25 | * Surface
26 | - width : 渲染区域的宽
27 | - height : 定义渲染区域的高
28 | * Shape
29 | - d : 定义绘制路径
30 | - stroke : 描边颜色
31 | - strokeWidth : 描边宽度
32 | - strokeDash : 定义虚线
33 | - fill : 填充颜色
34 | * Text
35 | - funt : 字体样式,定义字体、大小、是否加粗 如: ```bold 35px Heiti SC```
36 | * Path
37 | - moveTo(x,y) : 移动到坐标(x,y)
38 | - lineTo(x,y) : 连线到(x,y)
39 | - arc() : 绘制弧线
40 | - close() : 封闭空间
41 |
42 |
43 | ## 绘制直线
44 |
45 | >了解Path的moveTo和LineTo的使用,注意Surface的高度和宽度,多数没有绘制出想要的都是因为渲染区域定义问题
46 |
47 | ### 示例
48 |
49 | ```
50 | import React from 'react'
51 | import {
52 | View,
53 | ART
54 | } from 'react-native'
55 |
56 | export default class Line extends React.Component{
57 |
58 | render(){
59 |
60 | const path = ART.Path();
61 | path.moveTo(1,1); //将起始点移动到(1,1) 默认(0,0)
62 | path.lineTo(300,1); //连线到目标点(300,1)
63 |
64 | return(
65 |
66 |
67 |
68 |
69 |
70 | )
71 | }
72 | }
73 | ```
74 |
75 | ## 绘制虚线
76 | >了解strokeDash的参数,
77 | [10,5] : 表示绘10像素实线在绘5像素空白,如此循环
78 | [10,5,20,5] : 表示绘10像素实线在绘制5像素空白在绘20像素实线及5像素空白
79 |
80 | ### 示例
81 | ```
82 |
83 | import React from 'react'
84 | import {
85 | View,
86 | ART
87 | } from 'react-native'
88 |
89 | const {Surface, Shape, Path} = ART;
90 |
91 | export default class DashLine extends React.Component{
92 |
93 | render(){
94 |
95 | const path = Path()
96 | .moveTo(1,1)
97 | .lineTo(300,1);
98 |
99 | return(
100 |
101 |
102 |
103 |
104 |
105 | )
106 | }
107 | }
108 | ```
109 |
110 | ## 绘制矩形
111 | >了解close()的使用,close的意思是创建一个密闭的路径。首先通过lineTo绘制三条边,在使用close链接第四条边。fill做颜色填充
112 |
113 | ### 示例
114 | ```
115 | import React from 'react'
116 | import {
117 | View,
118 | ART
119 | } from 'react-native'
120 |
121 | const {Surface, Shape, Path} = ART;
122 |
123 | export default class Rect extends React.Component{
124 |
125 | render(){
126 |
127 | const path = new Path()
128 | .moveTo(1,1)
129 | .lineTo(1,99)
130 | .lineTo(99,99)
131 | .lineTo(99,1)
132 | .close();
133 |
134 | return(
135 |
136 |
137 |
138 |
139 |
140 | )
141 | }
142 | }
143 | ```
144 |
145 | ## 绘圆
146 | >了解arc(x,y,radius)的使用, 终点坐标距离起点坐标的相对距离
147 |
148 | ### 示例
149 | ```
150 | import React from 'react'
151 | import {
152 | View,
153 | ART
154 | } from 'react-native'
155 |
156 | const {Surface, Shape, Path} = ART;
157 |
158 | export default class Circle extends React.Component{
159 |
160 | render(){
161 |
162 | const path = new Path()
163 | .moveTo(50,1)
164 | .arc(0,99,25)
165 | .arc(0,-99,25)
166 | .close();
167 |
168 |
169 | return(
170 |
171 |
172 |
173 |
174 |
175 | )
176 | }
177 | }
178 | ```
179 |
180 | ## 绘制文字
181 | >了解funt属性的使用,规则是```bold 35px Heiti SC```
182 | 注意: 字体应该是支持path属性的,应该是实现bug并没有不生效。 Android通过修改源码是可以解决的,IOS没看源码。
183 |
184 | ### 示例
185 | ```
186 | import React from 'react'
187 | import {
188 | View,
189 | ART
190 | } from 'react-native'
191 |
192 | const {Surface, Text, Path} = ART;
193 |
194 | export default class ArtText extends React.Component{
195 |
196 |
197 | render(){
198 |
199 | return(
200 |
201 |
202 | Swipe
203 |
204 |
205 | )
206 | }
207 |
208 | }
209 | ```
210 |
211 | ## 绘制扇形
212 | >这里使用的是react-art中封装的一个组件[地址](https://github.com/reactjs/react-art/blob/master/src/Wedge.art.js),内部还是使用arc做路径绘制,感兴趣的同学可以阅读一下代码
213 |
214 | ### 示例
215 | ```
216 | import React from 'react'
217 | import {
218 | View,
219 | ART
220 | } from 'react-native'
221 |
222 | const {Surface} = ART;
223 | import Wedge from './Wedge'
224 |
225 | export default class Fan extends React.Component{
226 |
227 | render(){
228 |
229 | return(
230 |
231 |
232 |
239 |
240 |
241 |
242 | )
243 | }
244 | }
245 | ```
246 |
247 | ## 图层叠加
248 | >了解Group的使用
249 |
250 | ### 示例
251 | ```
252 | "use strict";
253 |
254 | import React from 'react'
255 | import {
256 | View,
257 | ART
258 | } from 'react-native'
259 |
260 | const {Surface, Shape,Text, Path,Group} = ART;
261 |
262 | export default class GroupTest extends React.Component{
263 |
264 | render(){
265 |
266 | const pathRect = new Path()
267 | .moveTo(1,1)
268 | .lineTo(1,99)
269 | .lineTo(99,99)
270 | .lineTo(99,1)
271 | .close();
272 |
273 | const pathCircle = new Path()
274 | .moveTo(50,1)
275 | .arc(0,99,25)
276 | .arc(0,-99,25)
277 | .close();
278 |
279 | const pathText = new Path()
280 | .moveTo(40,5)
281 | .lineTo(40,99);
282 |
283 |
284 | return(
285 |
286 |
287 |
288 |
289 |
290 | Swipe
291 |
292 |
293 |
294 | )
295 | }
296 | }
297 | ```
298 |
--------------------------------------------------------------------------------