react-native-art path代码解析
来源:互联网 发布:锤子大爆炸软件下载 编辑:程序博客网 时间:2024/06/02 19:40
React-Native-ART代码解析
一、探寻源码
1.如何使用
安卓自己集成,不需要额外操作,iOS需要pod添加ART库,如下:
pod 'React', :path => '../rn-source', :subspecs => [ 'Core', 'RCTActionSheet', 'RCTText', 'RCTImage', 'ART', # needed for debugging # Add any other subspecs you want to use in your project ]
2.js中的使用
import { ART } from 'react-native'const { Surface, Shape, Path, Group } = ART;
这样我们就能够使用ART的组件,总共有10个。部分组件的具体使用方法可以参考我之前写的。
3.寻找ART的源码
首先我们知道ART是在react-native
中引用的,所以我们到node_modules下找到react-native
文件夹,如图:
到这里,我们首先要看一下package.json
文件,这是react-native
所用的组件列表,如图:
我们可以看到react-native引用了一个库叫做art,但这里是小写的,应该是ART所用的依赖,还不确定是我们要找到ART库在哪里,我们继续找。
接下来,我们来看看Libraries文件夹,这里通常放着组件,这里我们看到了大写的ART,如图:
在这里我们可以看到大多都是原生代码,在ReactNativeART.js
中export出了一个组件ReactART,这个是我们要找的ART吗?,现在还不能确定。
我们继续看,在Libraries下我们找到react-native文件夹,可以看到react-native.js就静静的躺在这里,这个应该就是整个react-native组件的入口位置,在这里我们看到:
get ART() { return require('ReactNativeART'); },
现在,我们可以确定ReactNativeART就是我们要找的ART。
二、ART库源码
让我们回过头来看看ReactNativeART的入口文件(也就是Libraries下的ART文件夹下的 ReactNativeART.js),拉到下面我们可以看到:
var ReactART = { LinearGradient: LinearGradient, RadialGradient: RadialGradient, Pattern: Pattern, Transform: Transform, Path: Path, Surface: Surface, Group: Group, ClippingRectangle: ClippingRectangle, Shape: Shape, Text: Text,};
这个就是ART库输出的所有组件了,我们就可以从这里开始阅读代码,我们可以看到:
var Path = require('ARTSerializablePath');var Transform = require('art/core/transform');
// Native Componentsvar NativeSurfaceView = createReactNativeComponentClass({ validAttributes: SurfaceViewAttributes, uiViewClassName: 'ARTSurfaceView',});var NativeGroup = createReactNativeComponentClass({ validAttributes: GroupAttributes, uiViewClassName: 'ARTGroup',});var NativeShape = createReactNativeComponentClass({ validAttributes: ShapeAttributes, uiViewClassName: 'ARTShape',});var NativeText = createReactNativeComponentClass({ validAttributes: TextAttributes, uiViewClassName: 'ARTText',});
function LinearGradient ...function RadialGradient ...function Pattern ...
class ClippingRectangle extends React.Component { render() { var props = this.props; var x = extractNumber(props.x, 0); var y = extractNumber(props.y, 0); var w = extractNumber(props.width, 0); var h = extractNumber(props.height, 0); var clipping = [x, y, w, h]; // The current clipping API requires x and y to be ignored in the transform var propsExcludingXAndY = merge(props); delete propsExcludingXAndY.x; delete propsExcludingXAndY.y; return ( <NativeGroup clipping={clipping} opacity={extractOpacity(props)} transform={extractTransform(propsExcludingXAndY)}> {this.props.children} </NativeGroup> ); }}
可以看到,输出的10个组件这里都能看到出处,那到这里,其实我们关心那部分代码,就可以具体看哪里了,源码在这里其实已经暴露无疑了。
这部分的结论:
- surface,shape,group,text都是原生组件,
- ClippingRectangle是封装的一层group,
- LinearGradient,RadialGradient,Pattern分别是3个func,
- 而path和Transform则是引用的art文件,在上面我们已经看到了react-native的package.json引用了art组件。
三、ART里的path源码
上面我们看到
var Path = require('ARTSerializablePath');
在ARTSerializablePath.js
中,我们又能看到
/** * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ARTSerializablePath */'use strict';// TODO: Move this into an ART mode called "serialized" or somethingvar Class = require('art/core/class.js');var Path = require('art/core/path.js');var MOVE_TO = 0;var CLOSE = 1;var LINE_TO = 2;var CURVE_TO = 3;var ARC = 4;var SerializablePath = Class(Path, { initialize: function(path) { this.reset(); if (path instanceof SerializablePath) { this.path = path.path.slice(0); } else if (path) { if (path.applyToPath) { path.applyToPath(this); } else { this.push(path); } } }, onReset: function() { this.path = []; }, onMove: function(sx, sy, x, y) { this.path.push(MOVE_TO, x, y); }, onLine: function(sx, sy, x, y) { this.path.push(LINE_TO, x, y); }, onBezierCurve: function(sx, sy, p1x, p1y, p2x, p2y, x, y) { this.path.push(CURVE_TO, p1x, p1y, p2x, p2y, x, y); }, _arcToBezier: Path.prototype.onArc, onArc: function(sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation) { if (rx !== ry || rotation) { return this._arcToBezier( sx, sy, ex, ey, cx, cy, rx, ry, sa, ea, ccw, rotation ); } this.path.push(ARC, cx, cy, rx, sa, ea, ccw ? 0 : 1); }, onClose: function() { this.path.push(CLOSE); }, toJSON: function() { return this.path; }});module.exports = SerializablePath;
说明我们的path直接就使用的art/core/path.js
文件,而看这里的实现,全部使用的是this.path.push()
+参数的方法,我们接下来去看下art/core/path.js
的push方法,如下:
push: function(){ var p = Array.prototype.join.call(arguments, ' ') .match(/[a-df-z]|[\-+]?(?:[\d\.]e[\-+]?|[^\s\-+,a-z])+/ig); if (!p) return this; var last, cmd = p[0], i = 1; while (cmd){ switch (cmd){ case 'm': this.move(p[i++], p[i++]); break; case 'l': this.line(p[i++], p[i++]); break; case 'c': this.curve(p[i++], p[i++], p[i++], p[i++], p[i++], p[i++]); break; case 's': this.curve(p[i++], p[i++], null, null, p[i++], p[i++]); break; case 'q': this.curve(p[i++], p[i++], p[i++], p[i++]); break; case 't': this.curve(p[i++], p[i++]); break; case 'a': this.arc(p[i+5], p[i+6], p[i], p[i+1], p[i+3], !+p[i+4], p[i+2]); i += 7; break; case 'h': this.line(p[i++], 0); break; case 'v': this.line(0, p[i++]); break; case 'M': this.moveTo(p[i++], p[i++]); break; case 'L': this.lineTo(p[i++], p[i++]); break; case 'C': this.curveTo(p[i++], p[i++], p[i++], p[i++], p[i++], p[i++]); break; case 'S': this.curveTo(p[i++], p[i++], null, null, p[i++], p[i++]); break; case 'Q': this.curveTo(p[i++], p[i++], p[i++], p[i++]); break; case 'T': this.curveTo(p[i++], p[i++]); break; case 'A': this.arcTo(p[i+5], p[i+6], p[i], p[i+1], p[i+3], !+p[i+4], p[i+2]); i += 7; break; case 'H': this.lineTo(p[i++], this.penY); break; case 'V': this.lineTo(this.penX, p[i++]); break; case 'Z': case 'z': this.close(); break; default: cmd = last; i--; continue; } last = cmd; if (last == 'm') last = 'l'; else if (last == 'M') last = 'L'; cmd = p[i++]; } return this; },
可以看到svg的方法,说明我们其实是可以直接使用push做svg的实现的,
其实这里我有个疑虑,并不了解ARTSerializablePath.js
中调用push的原理,貌似指定了0-4的参数,
var MOVE_TO = 0;var CLOSE = 1;var LINE_TO = 2;var CURVE_TO = 3;var ARC = 4;
就可以调用相应的方法函数,还望看的懂的同学说明一下,
这里我们发现ART是可以使用SVG函数的,所以SVG的能力,我们在这里可以直接使用,比如画内塞尔曲线等等,例如:
_path = new Path("M0 0 Q5 20……");
四、Android与iOS使用ART的不同
- 渐变色(安卓不能渐变)
- 画扇形图(安卓绘制方式不同)
这里说一下画扇形,iOS直接使用ART提供的path根据我之前写的使用方法就可以画出来想要的图案,但是安卓却不能,这里可以使用更底层的push方法代替,例如画扇形:
if (Platform.OS === 'ios') {
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
} else {
path.path.push(ARC, CIRCLE_X, CIRCLE_Y, RX, startAngle / 360 * TwoPI, (startAngle / 360 * TwoPI) - ((endAngle - startAngle) / 360 * TwoPI), 0)
}
通过区分平台,再具体实现上使用不同的方法,达到相同的效果。
- react-native-art path代码解析
- react-native-art-绘图入门
- react-native-Art动画基础
- react-native-Art动画基础
- react-native-art-绘图入门
- react-native-Art动画基础
- react-native之ART绘图详解
- react-native之ART绘图详解
- 技术文章|react-native之ART绘图详解
- react-native之ART绘图详解
- react-native之ART绘图详解
- React-Native ART 绘图简析
- React Native打包代码解析与拆分Bundle做法
- React Native 代码规范
- React Native 代码片段
- react-native 代码片段
- react-native-art画二次贝塞尔曲线实现
- react-native for mac path setting
- Git学习笔记与IntelliJ IDEA整合
- SpringMVC整合DWR时出现这样的错误Multiple annotations found at this line:
- 笔记-NopCommerce系统架构分析-Ef数据访问
- js通用监听函数
- jvm知识点粘贴
- react-native-art path代码解析
- Netflix Conductor流程系统(二):官方样例搭建
- 修改VideoPlayManager
- 强化学习,深度学习,深度强化学习
- 我的第一个hbulider项目
- hadoop集群小项目实践及遇到问题解决办法
- Systemd 入门教程:命令篇
- Virtualbox虚拟机Linux Guest的Additions安装方法
- 学习RGB配色,灰度图