- 绘制 直线
- 绘制 虚线
- 绘制 矩形
- 绘制 三角形
- 绘制 多边形
- 绘制 多边线
- 绘制 圆形
- 绘制 半圆
- 绘制 扇形
- 绘制 圆环
- 绘制 渐变色
- 图片填充绘制的形状(Pattern)
props
Pattern
- 使用图片填充
Surface
- width : 渲染区域的宽
- height : 定义渲染区域的高
Shape
- d : 定义绘制路径 (Path对象)
- stroke : 描边颜色
- strokeWidth : 描边宽度
- strokeDash : 定义虚线
- fill : 填充颜色
Path
-
moveTo(x,y) : 移动到坐标(x,y),设置初始点
-
lineTo(x,y) : 连线到(x,y)
image.png
Path().moveTo(20, 20).lineTo(10, 20) 得到的是一条(20, 20) 到(10, 20) 的线。
-
line(x,y): 相对于原来的偏移
image.png
Path().moveTo(20, 20).line(10, 20) 得到的是一条(20, 20) 到(30, 40) 的线。
-
arc() : 绘制弧线
image.png
Path().moveTo(150,50).arc(50, 100,50) 绘制一半圆弧(150,50)起点,(50, 100)偏移量(终点) 50 半径
Path().arc(30, 50, 70, 90, true, false, 1) 画一段圆弧(30, 50)起点,(70, 90)控制点 (true, false, 1)不知/逆时针/不知,另个一圆弧的点在视图的边缘
- close() : 封闭空间
使用
import {
ART
} from 'react-native';
var {
Surface, // 一个矩形可渲染的区域,是其他元素的容器
Group, // 可容纳多个形状、文本和其他的分组
Shape, // 形状定义,可填充
Path, // 路径
LinearGradient, // 渐变色
Pattern, // 填充图片
ClippingRectangle, // 剪辑
} = ART;
- 直接使用SVG
.svg 路径的文件用浏览器打开,一片空白是正常的,右键查看网页源代码,找到path字段
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-31.9 0-25.5 20.6-46.1 46-46.2 19.1 0 35.5 11.7 42.4 28.4C94.9 11 111.3-0.8 130.4-0.8"
<Surface width={300} height={300} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={HEART_SVG} stroke="#000000" strokeWidth={1} fill={'#892265'}/>
</Surface>
svg代码
- 绘制 直线
{/*绘制 直线*/}
let zhixian_path = Path()
.moveTo(0,5) // 改变起点为 0,5 。默认为0,0
.lineTo(300,5) // 目标点
<Surface width={300} height={10} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={zhixian_path} stroke="#000000" strokeWidth={1} />
</Surface>
黄色中间的直线
- 绘制 虚线
{/*绘制 虚线*/}
let xuxian_path = Path()
.moveTo(0,5) // 改变起点为 0,5 。默认为0,0
.lineTo(300,5) // 目标点
let xuxian_path1 = Path()
.moveTo(0,15) // 改变起点为 0,15 。默认为0,0
.lineTo(300,15) // 目标点
<Surface width={300} height={20} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Group>
{/*strokeDash={[5,20] 先是5像素的实线,再是20像素的空白,再是5像素的实线... 循环*/}
<Shape d={xuxian_path} stroke="#000000" strokeWidth={2} strokeDash={[5,20,]}/>
{/*strokeDash={[10,5,20,5] 先是10像素的实线,再是5像素的空白,再是20像素的实线, 再是5像素的空白... 循环*/}
<Shape d={xuxian_path1} stroke="#000000" strokeWidth={2} strokeDash={[10,5,20,5]}/>
</Group>
</Surface>
黄色中间两条虚线
- 绘制 矩形
let juxing_path = Path()
.moveTo(5,5)
.lineTo(295,5)
.lineTo(295,25)
.lineTo(5,25)
.close() // close 封闭
{/*绘制 矩形*/}
<Surface width={300} height={30} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={juxing_path} stroke="#000000" strokeWidth={1} fill="#892265"/>
</Surface>
黄色中间矩形
- 绘制 三角形
let sanjiaoxing_path = Path()
.moveTo(100,5)
.lineTo(200, 25)
.lineTo(30,10)
.close()
{/*绘制 三角形*/}
<Surface width={300} height={30} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={sanjiaoxing_path} stroke="#000000" strokeWidth={1} fill="#892265"/>
</Surface>
黄色中间三角形
- 绘制 多边形
let duobianxing_path = Path()
.moveTo(50, 10)
.lineTo(80, 0)
.lineTo(120, 60)
.lineTo(60, 90)
.lineTo(10, 30)
.lineTo(80, 70)
.close()
{/*绘制 多边形*/}
<Surface width={300} height={200} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={duobianxing_path} stroke="#000000" strokeWidth={1} fill="#892265"/>
</Surface>
黄色内部
- 绘制 多边线
let duobianxian_path = Path()
.moveTo(50, 10)
.lineTo(80, 0)
.lineTo(120, 60)
.lineTo(60, 90)
.lineTo(10, 30)
.lineTo(80, 70)
.close()
{/*绘制 多边线*/}
<Surface width={300} height={200} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={duobianxian_path} stroke="#000000" strokeWidth={1} />
</Surface>
黄色内部
- 绘制 圆形、半圆
// 正常情况下 arc()只用来画圆,想要花圆弧使用...
// 实际是由两条 圆弧 构成了一个圆(左右两半拼成一个圆)
let yuanxing_path = Path()
.moveTo(50, 0)// 起点位置
.arc(0,100,50) // 将 (50,0) 看成新的坐标系(0,0),由此进行 顺时针(100正) 的画半弧。
.arc(0,-100,50) // 将 (0,100) 看成新的坐标系(0,0),由此进行 逆时针(-100负) 的画半弧。
.close() // arc第一个参数为 0 是因为 终点的x和原点在一条直线上,确保画的是半圆弧
// arc 第一个参数不为0 的情况
let yuanxing_path2 = Path()
.moveTo(150,50)
.arc(50, 100,50) // 给定了终点的坐标,即可自动算出半径,第三个参数 的范围预估 不可大于 真正的半径 不可小于1
.close()
let yuanxing_path3 = Path()
.moveTo(100,120)
.arc(-50, 100,50) // 给定了终点的坐标,即可自动算出半径,第三个参数 的范围预估 不可大于 真正的半径 不可小于1
.close()
let yuanxing_path4 = Path().moveTo(50, 5)// 起点位置
.arc(0, 100, 50) // 将起点位置看成新的坐标系,(50, 5)为新的原点(0,0)。100为正值,顺时针方向画半圆,50 为半径,100为终点坐标
.arc(0, 80, 40) // 将(0,100)看成新的坐标系(0,0),80为正值,顺时针方向画半圆,40 为半径,80为终点坐标
.arc(0, 60, 30) // 将(0, 80)看成新的坐标系(0,0),60为正值,顺时针方向画半圆,30 为半径,60为终点坐标
.arc(0, -20, 10) // 将(0, 60)看成新的坐标系(0,0),20为负值,逆时针方向画半圆,10 为半径,-20为终点坐标
.close();
{/*绘制 圆形*/}
<Surface width={300} height={250} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Group>
<Shape d={yuanxing_path} stroke="#000000" strokeWidth={1} fill="#892265"/>
<Shape d={yuanxing_path2} stroke="#000000" strokeWidth={1} fill="#892265"/>
<Shape d={yuanxing_path3} stroke="#000000" strokeWidth={1} fill="#892265"/>
</Group>
</Surface>
<Surface width={300} height={300} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={yuanxing_path4} stroke="#000000" strokeWidth={1} fill="#892265"/>
</Surface>
黄色内部
- 扇形、圆环
需要一个绘制类
import React, { Component } from 'react';
import { ART } from 'react-native';
const { Shape, Path } = ART;
import PropTypes from 'prop-types'
/**
* 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> {
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(originX : number, originY : number, or : number, ir : number) : Path {
const path = new Path();
path.move(originX, or + originY)
.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(originX, originY) // 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(originX, originY, or, ir);
} else {
path = this._createArcPath(originX, originY, startAngle, endAngle, or, ir);
}
return <Shape {...this.props} d={path} />;
}
}
Wedge.propTypes = {
outerRadius: PropTypes.number.isRequired, // 圆弧半径
startAngle: PropTypes.number.isRequired, // 开始角度
endAngle: PropTypes.number.isRequired, // 结束角度
originX: PropTypes.number, // 左边的距离 不是圆心的X
originY: PropTypes.number, // 上部的距离 不是圆心的Y
innerRadius: PropTypes.number, //内部半径 用户画弧
}
Wedge.defaultProps = {
originX: 0,
originY: 0,
}
使用
<Surface width={300} height={400} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Wedge
outerRadius={100}
startAngle={0}
endAngle={160}
originX={80}
originY={50}
fill="blue" />
</Surface>
<Surface width={300} height={300} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Wedge
outerRadius={100}
innerRadius={90}
startAngle={0}
endAngle={40}
originX={80}
originY={50}
fill="purple" />
</Surface>
黄色内部
- 渐变色
// .5 颜色占比表示 50%, 那个颜色的占比大,在前;颜色比小,在后。不能大于1
// 同样的占比,后面的会把前面的替换掉
// 必须是 Int 类型, 不可以是float或其他
// x1,y1,x2,y2 x1,y1颜色的起点;x2,y2颜色的终点
// "0", "0", "300", "0" 300为组件的宽度、弧度的长度 此:表示 横向颜色渐变
// "0", "0", "0", "40" 40为组件的高度、弧度的高度 此:表示 纵向颜色渐变
// "0", "0", "300", "100" 300、100 渐变是横向 ///(渐变样式犹如斜杠) 渐变
var linearGradient = new LinearGradient({
'.4': 'green',
'.6': 'blue',
},
"0", "0", "300", "100"
);
<Surface width={300} height={300} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Wedge
outerRadius={100}
innerRadius={90}
startAngle={0}
endAngle={100}
originX={80}
originY={50}
fill={linearGradient}/>
</Surface>
<Surface width={300} height={100} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={juxing_jianbian_path} stroke="#000000" strokeWidth={1} fill={linearGradient}/>
</Surface>
image.png
- 图片填充绘制的形状(Pattern)
(resolveAssetSource(本地图片)
得到本地图片的url
let url = resolveAssetSource(require('./image.png'))
image.png
import resolveAssetSource from 'resolveAssetSource'
const pattern = new Pattern(resolveAssetSource(pengyouImage),90,90,5,5)
<Surface width={300} height={100} style={{backgroundColor: 'yellow', marginTop: 10}}>
<Shape d={juxing_jianbian_path} stroke="#000000" strokeWidth={1} fill={pattern}/>
</Surface>
image.png
<Surface width={300} height={200} style={{backgroundColor: 'yellow', marginTop: 10}}>
<ClippingRectangle
width={ 100 } //要剪辑的宽
height={ 50 } //要剪辑的高
x={ 40 } //要剪辑的left
y={ 0 }> //要剪辑的top
<Shape d={ new Path().moveTo(20,20).lineTo(100,20) } stroke="black" strokeWidth={50}/>
</ClippingRectangle>
<Shape d={ new Path().moveTo(20, 100).lineTo(100,100) } stroke="black" strokeWidth={50}/>
</Surface>
image.png