react-native-art path代码解析
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 transformvar propsExcludingXAndY = merge(props);delete propsExcludingXAndY.x;delete propsExcludingXAndY.y;return (<NativeGroupclipping={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的实现的,
命令 | 名称 | 参数 |
---|---|---|
M | moveto | 移动到 (x y)+ |
Z | closepath | 关闭路径 (none) |
L | lineto | 画线到 (x y)+ |
H | horizontal lineto | 水平线到 x+ |
V | vertical lineto | 垂直线到 y+ |
C | curveto | 三次贝塞尔曲线到 (x1 y1 x2 y2 x y)+ |
S | smooth curveto | 光滑三次贝塞尔曲线到 (x2 y2 x y)+ |
Q | quadratic Bézier curveto | 二次贝塞尔曲线到 (x1 y1 x y)+ |
T | smooth quadratic Bézier curveto | 光滑二次贝塞尔曲线到 (x y)+ |
A | elliptical arc | 椭圆弧 (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+ |
R | Catmull-Rom curveto* | Catmull-Rom曲线 x1 y1 (x y)+ |
其实这里我有个疑虑,并不了解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代码解析相关推荐
- php中高光显示的高数,[技术博客]React Native——HTML页面代码高亮数学公式解析...
问题起源 原有博文显示时代码无法高亮,白底黑字的视觉效果不好. 原有博文中无法解析数学公式,导致页面会直接显示数学公式源码. 为了解决这两个问题,尝试了一些方法,最终利用开源类库实现了页面美化. (失 ...
- React Native动画入门全解析
动画 React Native 提供了两个互补的动画系统: 用于创建精细的交互控制动画Animated 用于全局的布局动画LayoutAnimation Animated Animated通过 **. ...
- React Native App版本升级方案解析
欢迎大家关注[跨平台开发那些事]公众号,定期推送跨平台开发技术实践. 源码已开源到Github,地址请点击:react-native-upgrade 欢迎大家star,fork..... App版本 ...
- React Native系列(6) - 编译安卓私有React-Native代码
为何要自己编译React Native安卓私有代码 我们在开发中遇到一个HTTP2的问题,React Native安卓客户端在和HTTP2支持的服务器通讯的过程中会有crash,见 React-Nat ...
- Windows环境下搭建React Native
随着移动开发越来越火热,前端开发也是有之前11年一直火热到现在,不过我发现从去年年底开发,Android和ios基本已经饱和了,特别是随着广大开源社区的中很多人贡献代码,开发已经不是什么问题了,所以现 ...
- 庖丁解牛!深入剖析React Native下一代架构重构
Facebook在2018年6月官方宣布了大规模重构React Native的计划及重构路线图.目的是为了让React Native更加轻量化.更适应混合开发,接近甚至达到原生的体验.(也有可能是Re ...
- React Native 热更新方案
转载: https://blog.csdn.net/xiangzhihong8/article/details/73201421 随着 React Native 的不断发展完善,越来越多的公司选择使用 ...
- React Native之原理浅析
一.JavaScriptCore 讲React Native之前,了解JavaScriptCore会有帮助,也是必要的.React Native的核心驱动力就来自于JS Engine. 你写的所有JS ...
- GitChat · 移动开发 | 征服React Native—列表组件
GitChat 作者:Li Luo 原文:征服React Native-列表组件 关注公众号:GitChat 技术杂谈,一本正经的讲技术 前言 移动应用往往受限于屏幕大小,而数据内容长度的不确定性,在 ...
最新文章
- java append concat_关于java:+ =比concat更有效吗?
- ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock‘
- PyQt4重写事件处理方法
- hdu 5076 最小割灵活运用
- 我是如何晋升专家岗的
- 一套代码在不同的电脑执行快慢_电脑如何选配之硬盘篇
- 汇编语言答案-王爽第三版
- 简述中断和 DMA 的区别。
- Security+ 学习笔记45 移动设备安全
- getch方法_C语言中getch()函数详解及简单实例
- swfobject参数详解
- 计算机开机一直无法访问,电脑开机时显示:AutoIt 错误 不能打开脚本文件 如何处理...
- css 实现三维立体旋转效果
- 最新尚硅谷2018SpringBoot教学视频(内含Docker)
- 一份给艺术爱好者的书单
- 企业三层架构、冗余、STP生成树协议总结
- 2019最新《C++基础到实战开发附带课程源码》
- 写了一篇文章老是提示包含敏感词,修改了好多遍
- 《史蒂夫·乔布斯传》读书笔记
- 车联网智能终端T-Box车联网智能终端远程控制T-B0X配置4G LTE的0BD设备