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个组件这里都能看到出处,那到这里,其实我们关心那部分代码,就可以具体看哪里了,源码在这里其实已经暴露无疑了。

这部分的结论:

  1. surface,shape,group,text都是原生组件,
  2. ClippingRectangle是封装的一层group,
  3. LinearGradient,RadialGradient,Pattern分别是3个func,
  4. 而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的不同

  1. 渐变色(安卓不能渐变)
  2. 画扇形图(安卓绘制方式不同)

这里说一下画扇形,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代码解析相关推荐

  1. php中高光显示的高数,[技术博客]React Native——HTML页面代码高亮数学公式解析...

    问题起源 原有博文显示时代码无法高亮,白底黑字的视觉效果不好. 原有博文中无法解析数学公式,导致页面会直接显示数学公式源码. 为了解决这两个问题,尝试了一些方法,最终利用开源类库实现了页面美化. (失 ...

  2. React Native动画入门全解析

    动画 React Native 提供了两个互补的动画系统: 用于创建精细的交互控制动画Animated 用于全局的布局动画LayoutAnimation Animated Animated通过 **. ...

  3. React Native App版本升级方案解析

    欢迎大家关注[跨平台开发那些事]公众号,定期推送跨平台开发技术实践. 源码已开源到Github,地址请点击:react-native-upgrade  欢迎大家star,fork..... App版本 ...

  4. React Native系列(6) - 编译安卓私有React-Native代码

    为何要自己编译React Native安卓私有代码 我们在开发中遇到一个HTTP2的问题,React Native安卓客户端在和HTTP2支持的服务器通讯的过程中会有crash,见 React-Nat ...

  5. Windows环境下搭建React Native

    随着移动开发越来越火热,前端开发也是有之前11年一直火热到现在,不过我发现从去年年底开发,Android和ios基本已经饱和了,特别是随着广大开源社区的中很多人贡献代码,开发已经不是什么问题了,所以现 ...

  6. 庖丁解牛!深入剖析React Native下一代架构重构

    Facebook在2018年6月官方宣布了大规模重构React Native的计划及重构路线图.目的是为了让React Native更加轻量化.更适应混合开发,接近甚至达到原生的体验.(也有可能是Re ...

  7. React Native 热更新方案

    转载: https://blog.csdn.net/xiangzhihong8/article/details/73201421 随着 React Native 的不断发展完善,越来越多的公司选择使用 ...

  8. React Native之原理浅析

    一.JavaScriptCore 讲React Native之前,了解JavaScriptCore会有帮助,也是必要的.React Native的核心驱动力就来自于JS Engine. 你写的所有JS ...

  9. GitChat · 移动开发 | 征服React Native—列表组件

    GitChat 作者:Li Luo 原文:征服React Native-列表组件 关注公众号:GitChat 技术杂谈,一本正经的讲技术 前言 移动应用往往受限于屏幕大小,而数据内容长度的不确定性,在 ...

最新文章

  1. java append concat_关于java:+ =比concat更有效吗?
  2. ERROR 2002 (HY000): Can‘t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock‘
  3. PyQt4重写事件处理方法
  4. hdu 5076 最小割灵活运用
  5. 我是如何晋升专家岗的
  6. 一套代码在不同的电脑执行快慢_电脑如何选配之硬盘篇
  7. 汇编语言答案-王爽第三版
  8. 简述中断和 DMA 的区别。
  9. Security+ 学习笔记45 移动设备安全
  10. getch方法_C语言中getch()函数详解及简单实例
  11. swfobject参数详解
  12. 计算机开机一直无法访问,电脑开机时显示:AutoIt 错误 不能打开脚本文件 如何处理...
  13. css 实现三维立体旋转效果
  14. 最新尚硅谷2018SpringBoot教学视频(内含Docker)
  15. 一份给艺术爱好者的书单
  16. 企业三层架构、冗余、STP生成树协议总结
  17. 2019最新《C++基础到实战开发附带课程源码》
  18. 写了一篇文章老是提示包含敏感词,修改了好多遍
  19. 《史蒂夫·乔布斯传》读书笔记
  20. 车联网智能终端T-Box车联网智能终端远程控制T-B0X配置4G LTE的0BD设备

热门文章

  1. 下载国外大数据库不用愁
  2. 哪款微信群管理软件好用?
  3. (附源码)php校园二手交易网站 附源码041148
  4. Xilinx FPGA 引脚功能详细介绍
  5. 如何成为资深软件工程师(JAVA方向)
  6. 路径追踪 SAH优化的Bvh
  7. HSWMS——库存管理
  8. 传奇私服服务器移动玩家位置,传奇私服服务端里面哪个是玩家数据文件文件
  9. docker-compose links depend on 使用的两种方式
  10. ios开发初级篇(上)