mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-06 07:06:11 +00:00
perf: optimize extraction of fill, stroke, responder, matrix & display
potentially breaking change if any issues show up, then they'll be considered regressions should be resolved in ways which cause less traffic from js to native
This commit is contained in:
@@ -156,96 +156,17 @@ exports[`supports CSS in style element 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<RNSVGGroup
|
||||
fill={4278190080}
|
||||
fillOpacity={1}
|
||||
fillRule={1}
|
||||
font={Object {}}
|
||||
matrix={
|
||||
Array [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
}
|
||||
opacity={1}
|
||||
originX={0}
|
||||
originY={0}
|
||||
propList={Array []}
|
||||
rotation={0}
|
||||
scaleX={1}
|
||||
scaleY={1}
|
||||
skewX={0}
|
||||
skewY={0}
|
||||
stroke={null}
|
||||
strokeDasharray={null}
|
||||
strokeDashoffset={null}
|
||||
strokeLinecap={0}
|
||||
strokeLinejoin={0}
|
||||
strokeMiterlimit={4}
|
||||
strokeOpacity={1}
|
||||
strokeWidth={1}
|
||||
vectorEffect={0}
|
||||
x={0}
|
||||
y={0}
|
||||
>
|
||||
<RNSVGDefs />
|
||||
<RNSVGGroup
|
||||
fill={4278190080}
|
||||
fillOpacity={1}
|
||||
fillRule={1}
|
||||
font={Object {}}
|
||||
matrix={
|
||||
Array [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
}
|
||||
opacity={1}
|
||||
originX={0}
|
||||
originY={0}
|
||||
propList={Array []}
|
||||
rotation={0}
|
||||
scaleX={1}
|
||||
scaleY={1}
|
||||
skewX={0}
|
||||
skewY={0}
|
||||
stroke={null}
|
||||
strokeDasharray={null}
|
||||
strokeDashoffset={null}
|
||||
strokeLinecap={0}
|
||||
strokeLinejoin={0}
|
||||
strokeMiterlimit={4}
|
||||
strokeOpacity={1}
|
||||
strokeWidth={1}
|
||||
vectorEffect={0}
|
||||
x={0}
|
||||
y={0}
|
||||
>
|
||||
<RNSVGRect
|
||||
fill={4294901760}
|
||||
fillOpacity={1}
|
||||
fillRule={1}
|
||||
height={200}
|
||||
matrix={
|
||||
Array [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
}
|
||||
opacity={1}
|
||||
originX={0}
|
||||
originY={0}
|
||||
propList={
|
||||
Array [
|
||||
"fill",
|
||||
@@ -253,79 +174,21 @@ exports[`supports CSS in style element 1`] = `
|
||||
"strokeWidth",
|
||||
]
|
||||
}
|
||||
rotation={0}
|
||||
scaleX={1}
|
||||
scaleY={1}
|
||||
skewX={0}
|
||||
skewY={0}
|
||||
stroke={4278190335}
|
||||
strokeDasharray={null}
|
||||
strokeDashoffset={null}
|
||||
strokeLinecap={0}
|
||||
strokeLinejoin={0}
|
||||
strokeMiterlimit={4}
|
||||
strokeOpacity={1}
|
||||
strokeWidth="16"
|
||||
vectorEffect={0}
|
||||
width={1000}
|
||||
x={100}
|
||||
y={0}
|
||||
/>
|
||||
</RNSVGGroup>
|
||||
<RNSVGGroup
|
||||
fill={4278190080}
|
||||
fillOpacity={1}
|
||||
fillRule={1}
|
||||
font={Object {}}
|
||||
matrix={
|
||||
Array [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
}
|
||||
opacity={1}
|
||||
originX={0}
|
||||
originY={0}
|
||||
propList={Array []}
|
||||
rotation={0}
|
||||
scaleX={1}
|
||||
scaleY={1}
|
||||
skewX={0}
|
||||
skewY={0}
|
||||
stroke={null}
|
||||
strokeDasharray={null}
|
||||
strokeDashoffset={null}
|
||||
strokeLinecap={0}
|
||||
strokeLinejoin={0}
|
||||
strokeMiterlimit={4}
|
||||
strokeOpacity={1}
|
||||
strokeWidth={1}
|
||||
vectorEffect={0}
|
||||
x={0}
|
||||
y={0}
|
||||
>
|
||||
<RNSVGRect
|
||||
fill={4294901760}
|
||||
fillOpacity={0.3}
|
||||
fillRule={1}
|
||||
height={200}
|
||||
matrix={
|
||||
Array [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
]
|
||||
}
|
||||
opacity={1}
|
||||
originX={0}
|
||||
originY={0}
|
||||
propList={
|
||||
Array [
|
||||
"fill",
|
||||
@@ -334,20 +197,8 @@ exports[`supports CSS in style element 1`] = `
|
||||
"strokeWidth",
|
||||
]
|
||||
}
|
||||
rotation={0}
|
||||
scaleX={1}
|
||||
scaleY={1}
|
||||
skewX={0}
|
||||
skewY={0}
|
||||
stroke={4278190335}
|
||||
strokeDasharray={null}
|
||||
strokeDashoffset={null}
|
||||
strokeLinecap={0}
|
||||
strokeLinejoin={0}
|
||||
strokeMiterlimit={4}
|
||||
strokeOpacity={1}
|
||||
strokeWidth="16"
|
||||
vectorEffect={0}
|
||||
width={750}
|
||||
x={100}
|
||||
y={350}
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
ResponderProps,
|
||||
TransformProps,
|
||||
ResponderInstanceProps,
|
||||
extractedProps,
|
||||
} from '../lib/extract/types';
|
||||
import extractResponder from '../lib/extract/extractResponder';
|
||||
import extractViewBox from '../lib/extract/extractViewBox';
|
||||
@@ -153,6 +154,8 @@ export default class Svg extends Shape<
|
||||
: null;
|
||||
|
||||
const tint = extractColor(color);
|
||||
const responder: extractedProps = {};
|
||||
extractResponder(responder, props, this as ResponderInstanceProps);
|
||||
return (
|
||||
<RNSVGSvg
|
||||
{...props}
|
||||
@@ -164,8 +167,8 @@ export default class Svg extends Shape<
|
||||
ref={this.refMethod}
|
||||
style={[styles.svg, style, opacityStyle, dimensions]}
|
||||
focusable={Boolean(focusable) && focusable !== 'false'}
|
||||
{...extractResponder(props, this as ResponderInstanceProps)}
|
||||
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
||||
{...responder}
|
||||
>
|
||||
<G
|
||||
{...{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import extractBrush from './extractBrush';
|
||||
import extractOpacity from './extractOpacity';
|
||||
import { colorNames } from './extractColor';
|
||||
import { FillProps } from './types';
|
||||
import { extractedProps, FillProps } from './types';
|
||||
|
||||
const fillRules: { evenodd: number; nonzero: number } = {
|
||||
evenodd: 0,
|
||||
@@ -11,24 +11,22 @@ const fillRules: { evenodd: number; nonzero: number } = {
|
||||
const defaultFill = colorNames.black;
|
||||
|
||||
export default function extractFill(
|
||||
o: extractedProps,
|
||||
props: FillProps,
|
||||
styleProperties: string[],
|
||||
) {
|
||||
const { fill, fillRule, fillOpacity } = props;
|
||||
|
||||
if (fill != null) {
|
||||
styleProperties.push('fill');
|
||||
o.fill =
|
||||
!fill && typeof fill !== 'number' ? defaultFill : extractBrush(fill);
|
||||
}
|
||||
if (fillOpacity != null) {
|
||||
styleProperties.push('fillOpacity');
|
||||
o.fillOpacity = extractOpacity(fillOpacity);
|
||||
}
|
||||
if (fillRule != null) {
|
||||
styleProperties.push('fillRule');
|
||||
o.fillRule = fillRule && fillRules[fillRule] === 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
return {
|
||||
fill: !fill && typeof fill !== 'number' ? defaultFill : extractBrush(fill),
|
||||
fillRule: fillRule && fillRules[fillRule] === 0 ? 0 : 1,
|
||||
fillOpacity: extractOpacity(fillOpacity),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
import extractFill from './extractFill';
|
||||
import extractStroke from './extractStroke';
|
||||
import { transformToMatrix, props2transform } from './extractTransform';
|
||||
import { props2transform, transformToMatrix } from './extractTransform';
|
||||
import extractResponder from './extractResponder';
|
||||
import extractOpacity from './extractOpacity';
|
||||
import { idPattern } from '../util';
|
||||
import {
|
||||
ClipProps,
|
||||
extractedProps,
|
||||
FillProps,
|
||||
NumberProp,
|
||||
ResponderProps,
|
||||
StrokeProps,
|
||||
TransformProps,
|
||||
} from './types';
|
||||
import { Component } from 'react';
|
||||
|
||||
const clipRules: { evenodd: number; nonzero: number } = {
|
||||
evenodd: 0,
|
||||
@@ -74,30 +74,24 @@ export default function extractProps(
|
||||
const styleProperties: string[] = [];
|
||||
const transformProps = props2transform(props);
|
||||
const matrix = transformToMatrix(transformProps, transform);
|
||||
const extracted: {
|
||||
name?: string;
|
||||
mask?: string;
|
||||
opacity: number;
|
||||
matrix: number[];
|
||||
propList: string[];
|
||||
onLayout?: () => void;
|
||||
ref?: (instance: Component | null) => void;
|
||||
markerStart?: string;
|
||||
markerMid?: string;
|
||||
markerEnd?: string;
|
||||
clipPath?: string;
|
||||
clipRule?: number;
|
||||
display?: string;
|
||||
} = {
|
||||
matrix,
|
||||
...transformProps,
|
||||
const extracted: extractedProps = {
|
||||
propList: styleProperties,
|
||||
opacity: extractOpacity(opacity),
|
||||
...extractResponder(props, ref),
|
||||
...extractFill(props, styleProperties),
|
||||
...extractStroke(props, styleProperties),
|
||||
display: display === 'none' ? 'none' : undefined,
|
||||
};
|
||||
extractResponder(extracted, props, ref);
|
||||
extractFill(extracted, props, styleProperties);
|
||||
extractStroke(extracted, props, styleProperties);
|
||||
|
||||
if (matrix !== null) {
|
||||
extracted.matrix = matrix;
|
||||
}
|
||||
|
||||
if (opacity != null) {
|
||||
extracted.opacity = extractOpacity(opacity);
|
||||
}
|
||||
|
||||
if (display != null) {
|
||||
extracted.display = display === 'none' ? 'none' : undefined;
|
||||
}
|
||||
|
||||
if (onLayout) {
|
||||
extracted.onLayout = onLayout;
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import { PanResponder } from 'react-native';
|
||||
import { ResponderInstanceProps, ResponderProps } from './types';
|
||||
import {
|
||||
extractedProps,
|
||||
ResponderInstanceProps,
|
||||
ResponderProps,
|
||||
} from './types';
|
||||
|
||||
const responderKeys = Object.keys(PanResponder.create({}).panHandlers);
|
||||
const numResponderKeys = responderKeys.length;
|
||||
|
||||
export default function extractResponder(
|
||||
o: extractedProps,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
props: { [x: string]: any } & ResponderProps,
|
||||
ref: ResponderInstanceProps,
|
||||
@@ -20,9 +25,6 @@ export default function extractResponder(
|
||||
delayLongPress,
|
||||
pointerEvents,
|
||||
} = props;
|
||||
const o: {
|
||||
[touchableProperty: string]: unknown;
|
||||
} = {};
|
||||
|
||||
let responsible = false;
|
||||
for (let i = 0; i < numResponderKeys; i++) {
|
||||
@@ -62,6 +64,4 @@ export default function extractResponder(
|
||||
if (responsible) {
|
||||
o.responsible = true;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import extractBrush from './extractBrush';
|
||||
import extractOpacity from './extractOpacity';
|
||||
import extractLengthList from './extractLengthList';
|
||||
import { StrokeProps } from './types';
|
||||
import { extractedProps, StrokeProps } from './types';
|
||||
|
||||
const caps = {
|
||||
butt: 0,
|
||||
@@ -25,6 +25,7 @@ const vectorEffects = {
|
||||
};
|
||||
|
||||
export default function extractStroke(
|
||||
o: extractedProps,
|
||||
props: StrokeProps,
|
||||
styleProperties: string[],
|
||||
) {
|
||||
@@ -42,50 +43,48 @@ export default function extractStroke(
|
||||
|
||||
if (stroke != null) {
|
||||
styleProperties.push('stroke');
|
||||
o.stroke = extractBrush(stroke);
|
||||
}
|
||||
if (strokeWidth != null) {
|
||||
styleProperties.push('strokeWidth');
|
||||
o.strokeWidth = strokeWidth;
|
||||
}
|
||||
if (strokeOpacity != null) {
|
||||
styleProperties.push('strokeOpacity');
|
||||
o.strokeOpacity = extractOpacity(strokeOpacity);
|
||||
}
|
||||
if (strokeDasharray != null) {
|
||||
styleProperties.push('strokeDasharray');
|
||||
const strokeDash =
|
||||
!strokeDasharray || strokeDasharray === 'none'
|
||||
? null
|
||||
: extractLengthList(strokeDasharray);
|
||||
o.strokeDasharray =
|
||||
strokeDash && strokeDash.length % 2 === 1
|
||||
? strokeDash.concat(strokeDash)
|
||||
: strokeDash;
|
||||
}
|
||||
if (strokeDashoffset != null) {
|
||||
styleProperties.push('strokeDashoffset');
|
||||
o.strokeDashoffset =
|
||||
strokeDasharray && strokeDashoffset ? +strokeDashoffset || 0 : null;
|
||||
}
|
||||
if (strokeLinecap != null) {
|
||||
styleProperties.push('strokeLinecap');
|
||||
o.strokeLinecap = (strokeLinecap && caps[strokeLinecap]) || 0;
|
||||
}
|
||||
if (strokeLinejoin != null) {
|
||||
styleProperties.push('strokeLinejoin');
|
||||
o.strokeLinejoin = (strokeLinejoin && joins[strokeLinejoin]) || 0;
|
||||
}
|
||||
if (strokeMiterlimit != null) {
|
||||
styleProperties.push('strokeMiterlimit');
|
||||
}
|
||||
|
||||
const strokeDash =
|
||||
!strokeDasharray || strokeDasharray === 'none'
|
||||
? null
|
||||
: extractLengthList(strokeDasharray);
|
||||
|
||||
return {
|
||||
stroke: extractBrush(stroke),
|
||||
strokeOpacity: extractOpacity(strokeOpacity),
|
||||
strokeLinecap: (strokeLinecap && caps[strokeLinecap]) || 0,
|
||||
strokeLinejoin: (strokeLinejoin && joins[strokeLinejoin]) || 0,
|
||||
strokeDasharray:
|
||||
strokeDash && strokeDash.length % 2 === 1
|
||||
? strokeDash.concat(strokeDash)
|
||||
: strokeDash,
|
||||
strokeWidth: strokeWidth != null ? strokeWidth : 1,
|
||||
strokeDashoffset:
|
||||
strokeDasharray && strokeDashoffset ? +strokeDashoffset || 0 : null,
|
||||
strokeMiterlimit:
|
||||
o.strokeMiterlimit =
|
||||
(strokeMiterlimit && typeof strokeMiterlimit !== 'number'
|
||||
? parseFloat(strokeMiterlimit)
|
||||
: strokeMiterlimit) || 4,
|
||||
vectorEffect: (vectorEffect && vectorEffects[vectorEffect]) || 0,
|
||||
};
|
||||
: strokeMiterlimit) || 4;
|
||||
}
|
||||
if (vectorEffect != null) {
|
||||
o.vectorEffect = (vectorEffect && vectorEffects[vectorEffect]) || 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,9 +67,11 @@ function universal2axis(
|
||||
return [x || defaultValue || 0, y || defaultValue || 0];
|
||||
}
|
||||
|
||||
export function props2transform(props: TransformProps): TransformedProps {
|
||||
export function props2transform(
|
||||
props: TransformProps,
|
||||
): TransformedProps | null {
|
||||
const {
|
||||
rotation = 0,
|
||||
rotation,
|
||||
translate,
|
||||
translateX,
|
||||
translateY,
|
||||
@@ -85,6 +87,25 @@ export function props2transform(props: TransformProps): TransformedProps {
|
||||
x,
|
||||
y,
|
||||
} = props;
|
||||
if (
|
||||
rotation == null &&
|
||||
translate == null &&
|
||||
translateX == null &&
|
||||
translateY == null &&
|
||||
origin == null &&
|
||||
originX == null &&
|
||||
originY == null &&
|
||||
scale == null &&
|
||||
scaleX == null &&
|
||||
scaleY == null &&
|
||||
skew == null &&
|
||||
skewX == null &&
|
||||
skewY == null &&
|
||||
x == null &&
|
||||
y == null
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (Array.isArray(x) || Array.isArray(y)) {
|
||||
console.warn(
|
||||
@@ -101,7 +122,7 @@ export function props2transform(props: TransformProps): TransformedProps {
|
||||
const sk = universal2axis(skew, skewX, skewY);
|
||||
|
||||
return {
|
||||
rotation: +rotation || 0,
|
||||
rotation: rotation == null ? 0 : +rotation || 0,
|
||||
originX: or[0],
|
||||
originY: or[1],
|
||||
scaleX: sc[0],
|
||||
@@ -114,11 +135,14 @@ export function props2transform(props: TransformProps): TransformedProps {
|
||||
}
|
||||
|
||||
export function transformToMatrix(
|
||||
props: TransformedProps,
|
||||
transform: number[] | string | TransformProps | void | undefined,
|
||||
): [number, number, number, number, number, number] {
|
||||
props: TransformedProps | null,
|
||||
transform: number[] | string | TransformProps | void | null | undefined,
|
||||
): [number, number, number, number, number, number] | null {
|
||||
if (!props && !transform) {
|
||||
return null;
|
||||
}
|
||||
reset();
|
||||
appendTransformProps(props);
|
||||
props && appendTransformProps(props);
|
||||
|
||||
if (transform) {
|
||||
if (Array.isArray(transform)) {
|
||||
@@ -141,7 +165,8 @@ export function transformToMatrix(
|
||||
console.error(e);
|
||||
}
|
||||
} else {
|
||||
appendTransformProps(props2transform(transform));
|
||||
const transformProps = props2transform(transform);
|
||||
transformProps && appendTransformProps(transformProps);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Component } from 'react';
|
||||
import { GestureResponderEvent } from 'react-native';
|
||||
|
||||
export type NumberProp = string | number;
|
||||
@@ -93,3 +94,19 @@ export type ClipProps = {
|
||||
clipPath?: string;
|
||||
clipRule?: 'evenodd' | 'nonzero';
|
||||
};
|
||||
export type extractedProps = {
|
||||
name?: string;
|
||||
mask?: string;
|
||||
opacity?: number;
|
||||
matrix?: number[];
|
||||
propList?: string[];
|
||||
onLayout?: () => void;
|
||||
ref?: (instance: Component | null) => void;
|
||||
markerStart?: string;
|
||||
markerMid?: string;
|
||||
markerEnd?: string;
|
||||
clipPath?: string;
|
||||
clipRule?: number;
|
||||
display?: string;
|
||||
[touchableProperty: string]: unknown;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user