Http://bbs.reactnative.cn/topic/306/%E5%9C%A8react-native%E4%B8%AD%E4%BD%BF%E7%94%A8art
The first half month churn react Native ART
Now you're free to share your thoughts on art usage in react native
What exactly is React Native ART?
The so-called art, is a JS class library that draws vector graphics in react. This class library abstracts the Common interface of a system and unifies the writing format of vector graphics such as svg,canvas,vml in react. You can use art to get vector graphics from svg,canvas,vml to react, or you can reverse art back. (although there are many limitations, it will be discussed later)
React Native ART is a transplant version of React-art in React Native, with almost identical interfaces,
Art in React native has been open-source for iOS long ago, and has recently been open-source for Android in 0.18.0.
The lack of official documentation has never been known.
Why use ART in react native?
I like to use SVG when I slice the front page, I try to get the designer to make the AI design draft or the icon to SVG.
Because SVG and the picture, the advantages are too many: can code reuse, can be lossless amplification, through the reasonable export of SVG code than the equivalent compressed picture file size is much smaller, and the SVG code can also be compressed by gzip
Recently in a native embedded react native project, the designer is the standard of the original app to cut each icon 3 size to me, thanks to react native powerful packaging tools, you can easily use this write icon. So the project was not thinking about using SVG (then Android's art was not open source, which is also an important factor).
After the completion of the project, I looked at it, all the pictures were compressed and added up to more than 200 k, the size is acceptable.
However, during the post-project optimization process, it was found that a very deadly problem was the use of picture icons:
The <image/> element is not rendered synchronously under iOS, even if the local picture resource is used!
Even more than the same multiple images cansourcenot be rendered in the same frame, such as the next 5 icons, in iOS they will not be rendered at the same time, so the effect is to open a list, see these icons one after another disorderly jump out, This effect if look at iphone4s,5s under quite obvious, very disgusting, completely unbearable! Think of all kinds of methods can not go around.
The following several icons of the first screen and the return button and logo, as well as the Tabbar inside the icon in iOS are in the interface appear after a number of frames and then out of order, the effect is very bad, there is no native app feel, there is a kind of hybird sense of sight.
Later, when 0.18.0,android's art was open to the outside, I thought why not use the SVG icon to try it?
Then let the designer put this icon:
Re-cut into SVG for me and then turn SVG into art.
Perfect rendering under iOS! All icons and interface text appear together, whether it's 5 or 100. And there is no perceptible effect on the overall rendering speed of the interface.
The same is true for Android, and the art code generated is much smaller than the picture.
<Surface
width={50}
height={50}
>
<Group scale={0.23}>
<Shape
fill={`${this.props.active ? ‘#ff5942‘ : ‘#ccc‘}`}
d={`M46.31,0H3.69C1.63,0,0,1.63,0,3.69v42.63C0,48.37,1.63,50,3.69,50h42.63c2.05,0,3.69-1.63,3.69-3.69V3.69
C50,1.63,48.37,0,46.31,0z M44.5,22.92l-7.76,7.65l1.8,10.61c0.18,1.07-0.29,2.14-1.21,2.77c-0.51,0.34-1.1,0.52-1.69,0.52
c-0.49,0-0.98-0.12-1.42-0.35l-9.23-4.75l-9.23,4.75c-0.44,0.24-0.94,0.35-1.42,0.35c-0.6,0-1.19-0.17-1.69-0.52
c-0.92-0.63-1.38-1.69-1.21-2.77l1.8-10.61l-7.76-7.65c-0.77-0.76-1.04-1.86-0.69-2.87c0.35-1.01,1.25-1.73,2.34-1.9l10.6-1.55
l4.6-9.43c0.49-1,1.52-1.62,2.66-1.62c1.15,0,2.18,0.64,2.66,1.62l4.6,9.43l10.59,1.55c1.09,0.16,1.99,0.9,2.34,1.9
C45.53,21.06,45.27,22.16,44.5,22.92z`}
/>
</Group>
</Surface>
The path code in this is directly exported through the PS cc, without any optimization, if you can again optimize a little more than half. The SVG code optimization is described later.
Here's the official entry.
How do I use ART in react native? Install ART
Installing art is simple
Android does not have to install at all, 0.18.0 inside, directly in JS to introduce both
import React, {ART} from ‘react-native‘;const {Surface, Group, Shape} = ART;
Art in iOS is optional, you need to import the Xcodeproj file manually, and add a static link library
But it's also simple: tutorials
Using art
Please forgive me, in fact, I am the title party, I will not be here to explain the use of art in detail, but to talk about an art-based SVG library: react-native-art-svg
Why don't I talk about art here? The reasons are as follows
The code above is the art code and the designer gave me the SVG code in fact there are some differences, but also to convert SVG once, very unfriendly, because the elements of art and SVG element name and usage are not the same
In the SVG code, the canvas element is <svg> and art is <Surface>
The elements that draw the path are <path> in SVG, and the path in art is another thing that needs <Shape> in art
This is not the most troublesome place, some basic SVG graphics <circle>, <rect>, <polygon> And so on the element art is not supported.
Front-end cut-out, whether it's a Web page or a react native interface, design drafts and icons are for us (except for the great gods that have been designed together)
And the designer gave us the vector icon is either the AI original or SVG, but eventually into our hands, the export must be SVG.
So while art uses an abstract interface to unify the use of svg,canvas,vml in react, art provides interfaces that are rather unfriendly. And then I had an idea, why not put art in one layer, wrap the syntax into the syntax of SVG?
Then React-native-art-svg was born, support SVG all the common elements and attributes, SVG code can be used almost directly (will be added directly after the SVG code import function)
The preview image is as follows:
Installation is simple, because it is a class library of pure JavaScript, straight line
npm i react-native-art-svg --save
Introduced in JS by the following code
import Svg, {
Circle,
Ellipse,
G,
LinearGradient,
RadialGradient,
Line,
Path,
Polygon,
Polyline,
Rect,
Symbol,
Text,
Use,
Defs,
Stop
} from ‘react-native-art-svg‘;
The art code above is equivalent to the following code
<Svg
width={50}
height={50}
>
<G scale={0.23}>
<Path
fill={`${this.props.active ? ‘#ff5942‘ : ‘#ccc‘}`}
d={`M46.31,0H3.69C1.63,0,0,1.63,0,3.69v42.63C0,48.37,1.63,50,3.69,50h42.63c2.05,0,3.69-1.63,3.69-3.69V3.69
C50,1.63,48.37,0,46.31,0z M44.5,22.92l-7.76,7.65l1.8,10.61c0.18,1.07-0.29,2.14-1.21,2.77c-0.51,0.34-1.1,0.52-1.69,0.52
c-0.49,0-0.98-0.12-1.42-0.35l-9.23-4.75l-9.23,4.75c-0.44,0.24-0.94,0.35-1.42,0.35c-0.6,0-1.19-0.17-1.69-0.52
c-0.92-0.63-1.38-1.69-1.21-2.77l1.8-10.61l-7.76-7.65c-0.77-0.76-1.04-1.86-0.69-2.87c0.35-1.01,1.25-1.73,2.34-1.9l10.6-1.55
l4.6-9.43c0.49-1,1.52-1.62,2.66-1.62c1.15,0,2.18,0.64,2.66,1.62l4.6,9.43l10.59,1.55c1.09,0.16,1.99,0.9,2.34,1.9
C45.53,21.06,45.27,22.16,44.5,22.92z`}
/>
</G>
</Svg>
This code from the SVG turned to be much more worry, only need to change the case of the element, the element name to the beginning of the capital letter can be changed to the name of the camel-named style.
General Properties List:
Property name |
Default Value |
Description |
Fill |
' #000 ' |
Inner Fill rule (fill color, fill gradient shape) |
Fillopacity |
1 |
Transparency of fills |
Stroke |
' None ' |
Stroke color |
Strokewidth |
1 |
Width of stroke |
Strokeopacity |
1 |
The transparency of the stroke |
Strokelinecap |
' Square ' |
How to display the end of a stroke segment |
Strokelinejoin |
' Miter ' |
How the stroke segment is displayed at the connection |
Strokedasharray |
[] |
Stroke Segment Breakpoint Display rule |
X |
0 |
Current graph x-axis offset |
Y |
0 |
Current graph y-axis offset |
Rotate |
0 |
Current graph rotation value |
Scale |
1 |
Zoom value of the current drawing |
Origin |
0, 0 |
Deformation origin (X,y,rotate,scale's deformation origin coordinates) |
Originx |
0 |
Deformation origin x axis coordinate |
Originy |
0 |
Y-axis coordinates of the deformation origin |
As you can see, almost all of the common properties of SVG can support
FillRule is not supported because it is officially assumed that FillRule is not a property common to Svg,canvas and VML, and they do not support such unique properties
Clippath is not supported because art official is not yet complete.
List of supported elements:
Svg
SVG is the canvas element for all vector graphics, and all vector graphics within SVG are plotted inside the SVG
and SVG supports Viewbox and Preserveaspectratio attributes (a detailed explanation of these two properties)
<Svg
height="100"
width="100"
>
<Rect x="0" y="0" width="100" height="100" fill="black" />
<Circle cx="50" cy="50" r="30" fill="yellow" />
<Circle cx="40" cy="40" r="4" fill="black" />
<Circle cx="60" cy="40" r="4" fill="black" />
<Path d="M 40 60 A 10 10 0 0 0 60 60" stroke="black" />
</Svg>;
The above code will draw the following graphic
where height and width define the width height of the SVG element
Attention
In React-native-art-svg, the properties of the numeric type of all elements can be represented directly by a string, such as:
The following two-segment attribute declarations are used normally, which makes it easy to write.
height="100"
height={100}
Rectangle: Rect
<Rect> elements can draw a rectangle on the canvas, and the rectangle's position and size are defined together by the X,y,width,height property
<Svg
width="200"
height="60"
>
<Rect
x="25"
y="5"
width="150"
height="50"
fill="rgb(0,0,255)"
strokeWidth="3"
stroke="rgb(0,0,0)"
/>
</Svg>
The above code draws a rectangle at the top left corner on canvas 25, 5, Width 150, height 50
and fills the inner background with a blue (RGB (0,0,255)) Fill (fill)
Stroke (stroke) with Black (RGB (0,0,0)), stroke width (strokewidth) of 3
Round: Circle
The <Circle> element can draw a circle on the canvas, and the circle needs to cx,cy,r three properties, corresponding to the x-axis coordinates, the y-coordinate, and the radius
<Svg
height="100"
width="110"
>
<Circle
cx="50"
cy="50"
r="50"
fill="pink"
/>
</Svg>
Ellipse: Ellipse
The <Ellipse> element can draw an ellipse on the canvas, like an ellipse and a circle, just replace the circular R property with the Rx,ry attribute corresponding to the horizontal and vertical radii respectively, and the RX = = ry Ellipse is a circular
<Svg
height="100"
width="110"
>
<Ellipse
cx="55"
cy="55"
rx="50"
ry="30"
stroke="purple"
strokeWidth="2"
fill="yellow"
/>
</Svg>
Lines: Line
<Line> elements can draw a line from X1,y1 to x2,y2 on the canvas
<Svg
height="100"
width="100"
>
<Line
x1="0"
y1="0"
x2="100"
y2="100"
stroke="red"
strokeWidth="2"
/>
</Svg>
Polygon: Polygon
<Polygon> elements can draw a polygon on the canvas that is composed of multiple points ending together, and the coordinates of each point are defined in the points attribute separately by the spaces.
<Svg
height="100"
width="100"
>
<Polyline
points="10,10 20,12 30,20 40,60 60,70 95,90"
fill="none"
stroke="black"
strokeWidth="3"
/>
</Svg>
Multi-Edge: Polyline
<Polyline> element and polygon type, except that the last point of the polygon is connected to the first point, which is composed of a closed graph, the last point of the multilateral line and the first point are not connected
<Svg
height="100"
width="100"
>
<Polyline
points="10,10 20,12 30,20 40,60 60,70 95,90"
fill="none"
stroke="black"
strokeWidth="3"
/>
</Svg>
Paths: Path
The properties of <Path>ddefine a series of path coordinates and draw rule commands, all of which can be drawn from path
- M = Move the drawing point to a location
- L = Draw a line from the current drawing point to a coordinate
- H = Draw line horizontally along the x-axis from the current drawing point
- V = line is drawn vertically along the y-axis from the current drawing point
- C = Draw a curve from the current drawing point to a coordinate
- S = Draws a smooth curve from the current drawing point to a coordinate
- Q = Draw a Bezier curve from the current drawing point to a coordinate
- T = Draws a smooth Bezier curve from the current drawing point to a coordinate
- A = Draw an elliptical curve from the current drawing point to a point
- Z = Close current path
Note: All commands above can use lowercase letters, uppercase letters command is the coordinates of the use of absolute value, lowercase letters of the command coordinates are relative values
<Svg
height="100"
width="100"
>
<Path
d="M25 10 L98 65 L70 25 L16 77 L11 30 L0 4 L90 50 L50 10 L11 22 L77 95 L20 25"
fill="none"
stroke="red"
/>
</Svg>
Text: Text
<Text> elements can draw text graphics on the canvas
<Svg
height="60"
width="200"
>
<Text
fill="none"
stroke="purple"
fontSize="20"
fontWeight="bold"
x="100"
y="20"
textAnchor="center"
>STROKED TEXT</Text>
</Svg
SVG advanced Elements use Group: G
The <G> element can combine its inner sub-elements into a single grouping, and all child elements within the G element will inherit all attributes except (ID, deform attribute)
The following two generations are the same
<Svg
height="60"
width="200"
>
<G width="100" height="30" fill="blue" x="0">
<Rect y="0" />
<Rect y="30" />
</G>
</Svg>
<Svg
height="60"
width="200"
>
<G>
<Rect width="100" height="30" fill="blue" x="0" y="0" />
<Rect width="100" height="30" fill="blue" x="0" y="0" />
</G>
</Svg>
The Deform property of the G element is not inherited
<Svg
height="100"
width="200"
>
<G
rotate="50"
origin="100, 50"
>
<Line
x1="60"
y1="10"
x2="140"
y2="10"
stroke="#060"
/>
<Rect
x="60"
y="20"
height="50"
width="80"
stroke="#060"
fill="#060"
/>
<Text
x="100"
y="75"
stroke="#600"
fill="#600"
textAnchor="center"
>
Text grouped with shapes</Text>
</G>
</Svg>
Definition: Defs
All the shapes within the <Defs> element are not drawn on the canvas,<defs> elements are used to define some code reuse related elements, and the following uses other elements to explain the use of the <Defs> element
Reuse: Use
Using the <Use> element for code reuse, you can draw elements defined in the <Defs> element复制一份at the location of the current <Use> element
<Svg
height="100"
width="300"
>
<Defs>
<G id="shape">
<Circle cx="50" cy="50" r="50" />
<Rect x="50" y="50" width="50" height="50" />
<Circle cx="50" cy="50" r="5" fill="blue" />
</G>
</Defs>
<Use href="#shape" x="20" y="0"/>
<Use href="#shape" x="170"y="0" />
</Svg>
* Note: The *use element uses an href to specify the reusable object (the xlink:href= used in SVG), the value of the attribute is the#ID of the element that needs to be reused, or it can be reused <Defs> an element with an id attribute outside. Attributes on the use element override the properties of the reused element
Tags: symbol
Using the <Symbol> element to define elements more quickly, using the <Defs> element to define reusable elements, each child element corresponds to a reusable element, which is typically defined with a <Symbol> element if multiple elements of a drawing need to be reused. <Symbol> itself will not be drawn on the canvas, and the Symbol can be specified Viewbox and Preserveaspectratio properties, more convenient to scale the graphics
<Svg
height="150"
width="110"
>
<Symbol id="symbol" viewbox="0 0 150 110" width="100" height="50">
<Circle cx="50" cy="50" r="40" strokeWidth="8" stroke="red" fill="red"/>
<Circle cx="90" cy="60" r="40" strokeWidth="8" stroke="green" fill="white"/>
</Symbol>
<Use
href="#symbol"
x="0"
y="0"
/>
<Use
href="#symbol"
x="0"
y="50"
width="75"
height="38"
/>
<Use
href="#symbol"
x="0"
y="100"
width="50"
height="25"
/>
</Svg>
Gradient fill lineargradient: linear gradient
<LinearGradient> can define a fill rule for a linear gradient, and the element must be defined within the <Defs> element.
A linear gradient can be defined as a horizontal gradient, a vertical gradient, and a gradient with an angle
Set the gradient start point by adjusting x1,y1, X2,y2 set the gradient end point
Use the <Stop> element to define a gradient's discoloration point
<Svg
height="150"
width="300"
>
<Defs>
<LinearGradient id="grad" x1="0" y1="0" x2="170" y2="0">
<Stop offset="0" stopColor="rgb(255,255,0)" stopOpacity="0" />
<Stop offset="1" stopColor="red" stopOpacity="1" />
</LinearGradient>
</Defs>
<Ellipse cx="150" cy="75" rx="85" ry="55" fill="url(#grad)" />
</Svg>
Note The X1,y2,x2,y2 properties for both:<lineargradient> and <RadialGradient> can be used as percentages
The following <LinearGradient> draws the result equal to the drawing result of the above code
<LinearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="0%">
<Stop offset="0%" stopColor="rgb(255,255,0)" stopOpacity="0" />
<Stop offset="100%" stopColor="red" stopOpacity="1" />
</LinearGradient>
Radialgradient: Radial Gradient
<RadialGradient> You can define a fill rule for a linear gradient, and the same as <LinearGradient> change elements must be defined within <Defs> elements.
The Cx,cu,rx,ry property defines the position coordinates and size of the outermost gradient ellipse, and the FX and FY properties define the position coordinates of the most inner gradient ellipse
<Svg
height="150"
width="300"
>
<Defs>
<RadialGradient id="grad" cx="150" cy="75" rx="85" ry="55" fx="150" fy="75">
<Stop
offset="0"
stopColor="#ff0"
stopOpacity="1"
/>
<Stop
offset="1"
stopColor="#83a"
stopOpacity="1"
/>
</RadialGradient>
</Defs>
<Ellipse cx="150" cy="75" rx="85" ry="55" fill="url(#grad)" />
</Svg>
Summarize
Well, that's about it.
The above contains thereact-native-art-svguse of most class libraries, for more specific examples please fork and then run the example project below example.
Let's go back to the article at the beginning of the project, through a few toss, finally the project all the pictures are replaced with vector graphics, in iOS no longer appear flashing pictures or images can not be rendered with the interface at the same time.
And the SVG code after a further optimization, the more than 200 K of the picture into more than 30 K vector code. Perfect!
I'll talk about SVG code optimization in passing:
- Use basic graphics First!
Priority use of basic graphics such as <Rect><Circle><Line><Polygon><Polyline><Ellipse>
Graphics that can be drawn with these elements are used to draw as much as possible, because the same graph uses the <Path> command to generate more code than the other base elements.
- Let the designer use it all when drawing,局中描边because only the SVG code in the local stroke will retain the graphic information from the original design, and the SVG code generated with the outer or inner strokes is drawn through the <path> element, which multiplies the SVG code.
[Go] Use art in react native