Skip to content

Commit 05c33d3

Browse files
authored
chore: align examples (software-mansion#1914)
PR aligning example apps and fixing one bug. On web, if you don't pass a color to the elements, they are rendered with `black` fill. We recreate this behavior in examples, but maybe it should be the default behavior if `fill` is `undefined`. It would probably need to be changed on the native side somehow. Another fix is to parse `fill` prop in `setNativeProps` since Fabric support has been added and `fill` prop structure has been changed, it cannot be handled on the native side on `Android` due to complying to interfaces. Another fix is passing `transform` prop in `Svg` to `G` when it is not `react-native` style `transform` prop so it is always applied. It creates a problem mentioned in the comment in the code and should be addressed in later PRs.
1 parent 9c0fa78 commit 05c33d3

File tree

15 files changed

+103
-24
lines changed

15 files changed

+103
-24
lines changed

Diff for: Example/src/examples/Path.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class PathExample extends Component {
66
render() {
77
return (
88
<Svg height="100" width="100">
9-
<Path d="M50 0 L15 100 L85 100 Z" />
9+
<Path d="M50 0 L15 100 L85 100 Z" fill="black" />
1010
<Path
1111
fill="red"
1212
d="M38.459,1.66A0.884,0.884,0,0,1,39,2.5a0.7,0.7,0,0,1-.3.575L23.235,16.092,27.58,26.1a1.4,1.4,0,0,1,.148.3,1.3,1.3,0,0,1,0,.377,1.266,1.266,0,0,1-2.078.991L15.526,20.6l-7.58,4.35a1.255,1.255,0,0,1-.485,0,1.267,1.267,0,0,1-1.277-1.258q0-.01,0-0.02a1.429,1.429,0,0,1,0-.446C7.243,20.253,8.6,16.369,8.6,16.29L3.433,13.545A0.743,0.743,0,0,1,2.9,12.822a0.822,0.822,0,0,1,.623-0.773l8.164-2.972,3.018-8.5A0.822,0.822,0,0,1,15.427,0a0.752,0.752,0,0,1,.752.555l2.563,6.936S37.65,1.727,37.792,1.685A1.15,1.15,0,0,1,38.459,1.66Z"

Diff for: Example/src/examples/Reusable.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ class UseExample extends Component {
2121
<Svg height="100" width="300">
2222
<Defs>
2323
<G id="reuse-shape">
24-
<Circle cx="50" cy="50" r="50" />
25-
<Rect x="50" y="50" width="50" height="50" />
24+
<Circle cx="50" cy="50" r="50" fill="black" />
25+
<Rect x="50" y="50" width="50" height="50" fill="black" />
2626
<Circle cx="50" cy="50" r="5" fill="blue" />
2727
</G>
2828
</Defs>

Diff for: Example/src/examples/Text.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class TSpanExample extends Component {
144144
render() {
145145
return (
146146
<Svg height="160" width="200">
147-
<Text y="20" dx="5 5">
147+
<Text y="20" dx="5 5" fill="black">
148148
<TSpan x="10">tspan line 1</TSpan>
149149
<TSpan x="10" dy="15">
150150
tspan line 2
@@ -163,7 +163,7 @@ class TSpanExample extends Component {
163163
89a
164164
</TSpan>
165165
</Text>
166-
<Text y="140" dx="0 5 5" dy="0 -5 -5">
166+
<Text y="140" dx="0 5 5" dy="0 -5 -5" fill="black">
167167
delta on text
168168
</Text>
169169
</Svg>

Diff for: Example/src/examples/TouchEvents.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class GroupExample extends Component {
7979
<G onPress={() => Alert.alert('Pressed on G')} scale="1.4">
8080
<Circle cx="80" cy="80" r="30" fill="green" x="20" scale="1.2" />
8181
<Text
82+
fill="black"
8283
fontWeight="bold"
8384
fontSize="40"
8485
x="100"

Diff for: Example/src/examples/Transforms.tsx

+24
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
RadialGradient,
1010
Stop,
1111
SvgXml,
12+
Defs,
13+
G,
1214
} from 'react-native-svg';
1315

1416
const patternXml = `
@@ -63,6 +65,28 @@ class PatternTransformExample extends Component {
6365
transform={[{translateX: 100}]}
6466
/>
6567
</Svg>
68+
<Svg height="100" width="100" viewBox="0 0 100 100">
69+
<Defs>
70+
<Pattern
71+
id="stripe"
72+
patternUnits="userSpaceOnUse"
73+
patternContentUnits="userSpaceOnUse"
74+
width="8"
75+
height="12"
76+
patternTransform="rotate(45)">
77+
<Rect width="4" height="8" fill="white" x="0" y="0"></Rect>
78+
<Rect width="4" height="12" fill="black" x="4" y="0"></Rect>
79+
</Pattern>
80+
</Defs>
81+
<G transform="matrix(1 0 0 -1 0 140)">
82+
<Rect
83+
x="0"
84+
y="0"
85+
width="100"
86+
height="100"
87+
fill="url(#stripe)"></Rect>
88+
</G>
89+
</Svg>
6690
{Platform.OS !== 'web' && (
6791
<SvgXml width="100" height="100" xml={patternXml} />
6892
)}

Diff for: FabricExample/src/App.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import {
1414
TouchableHighlight,
1515
TouchableOpacity,
1616
} from 'react-native';
17-
import {Modal} from 'react-native';
1817
import {Svg, Circle, Line} from 'react-native-svg';
1918

2019
import * as examples from './examples';

Diff for: FabricExample/src/examples/PanResponder.tsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
import React, {PureComponent} from 'react';
22
import {
3-
PanResponder,
4-
View,
53
Animated,
4+
PanResponder,
65
TouchableWithoutFeedback,
6+
View,
77
} from 'react-native';
8-
import {Svg, G, Text, Path, Polyline, Line} from 'react-native-svg';
8+
import {G, Line, Path, Polyline, Svg, Text} from 'react-native-svg';
99

1010
const AnimatedSvg = Animated.createAnimatedComponent(Svg);
1111

1212
const zeroDelta = {x: 0, y: 0};
1313

1414
class PanExample extends PureComponent {
15-
static title = 'Bind PanResponder on the SVG Shape - It does not work on Fabric since it uses `setNativeProps`';
15+
static title = 'Bind PanResponder on the SVG Shape';
1616
panXY: any;
17-
constructor(props, context) {
17+
constructor(props: {}, context: {}) {
1818
super(props, context);
1919
const xy = new Animated.ValueXY();
2020
const {x: dx, y: dy} = xy;
@@ -29,7 +29,9 @@ class PanExample extends PureComponent {
2929
xy.setOffset(offset);
3030
xy.setValue(zeroDelta);
3131
},
32-
onPanResponderMove: Animated.event([null, {dx, dy}]),
32+
onPanResponderMove: Animated.event([null, {dx, dy}], {
33+
useNativeDriver: false,
34+
}),
3335
onPanResponderRelease: () => {
3436
xy.flattenOffset();
3537
},

Diff for: FabricExample/src/examples/Path.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class PathExample extends Component {
66
render() {
77
return (
88
<Svg height="100" width="100">
9-
<Path d="M50 0 L15 100 L85 100 Z" />
9+
<Path d="M50 0 L15 100 L85 100 Z" fill="black"/>
1010
<Path
1111
fill="red"
1212
d="M38.459,1.66A0.884,0.884,0,0,1,39,2.5a0.7,0.7,0,0,1-.3.575L23.235,16.092,27.58,26.1a1.4,1.4,0,0,1,.148.3,1.3,1.3,0,0,1,0,.377,1.266,1.266,0,0,1-2.078.991L15.526,20.6l-7.58,4.35a1.255,1.255,0,0,1-.485,0,1.267,1.267,0,0,1-1.277-1.258q0-.01,0-0.02a1.429,1.429,0,0,1,0-.446C7.243,20.253,8.6,16.369,8.6,16.29L3.433,13.545A0.743,0.743,0,0,1,2.9,12.822a0.822,0.822,0,0,1,.623-0.773l8.164-2.972,3.018-8.5A0.822,0.822,0,0,1,15.427,0a0.752,0.752,0,0,1,.752.555l2.563,6.936S37.65,1.727,37.792,1.685A1.15,1.15,0,0,1,38.459,1.66Z"

Diff for: FabricExample/src/examples/Text.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class TSpanExample extends Component {
144144
render() {
145145
return (
146146
<Svg height="160" width="200">
147-
<Text y="20" dx="5 5">
147+
<Text y="20" dx="5 5" fill="black">
148148
<TSpan x="10">tspan line 1</TSpan>
149149
<TSpan x="10" dy="15">
150150
tspan line 2
@@ -163,7 +163,7 @@ class TSpanExample extends Component {
163163
89a
164164
</TSpan>
165165
</Text>
166-
<Text y="140" dx="0 5 5" dy="0 -5 -5">
166+
<Text y="140" dx="0 5 5" dy="0 -5 -5" fill="black">
167167
delta on text
168168
</Text>
169169
</Svg>

Diff for: FabricExample/src/examples/TouchEvents.tsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
Defs,
1111
ClipPath,
1212
} from 'react-native-svg';
13+
import {Alert} from 'react-native';
1314

1415
class PressExample extends Component {
1516
static title =
@@ -22,15 +23,15 @@ class PressExample extends Component {
2223
cy="50%"
2324
r="38%"
2425
fill="red"
25-
onPress={() => alert('Press on Circle')}
26+
onPress={() => Alert.alert('Press on Circle')}
2627
/>
2728
<Rect
2829
x="20%"
2930
y="20%"
3031
width="60%"
3132
height="60%"
3233
fill="blue"
33-
onLongPress={() => alert('Long press on Rect')}
34+
onLongPress={() => Alert.alert('Long press on Rect')}
3435
/>
3536
<Path d="M50,5L20,99L95,39L5,39L80,99z" fill="pink" />
3637
</Svg>
@@ -75,14 +76,15 @@ class GroupExample extends Component {
7576
render() {
7677
return (
7778
<Svg height="120" width="120" viewBox="0 0 240 240">
78-
<G onPress={() => alert('Pressed on G')} scale="1.4">
79+
<G onPress={() => Alert.alert('Pressed on G')} scale="1.4">
7980
<Circle cx="80" cy="80" r="30" fill="green" x="20" scale="1.2" />
8081
<Text
82+
fill="black"
8183
fontWeight="bold"
8284
fontSize="40"
8385
x="100"
8486
y="40"
85-
onPress={() => alert('Pressed on Text')}>
87+
onPress={() => Alert.alert('Pressed on Text')}>
8688
H
8789
</Text>
8890
<Rect x="20" y="20" width="40" height="40" fill="yellow" />

Diff for: TestsExample/App.js

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import React from 'react';
33

44
import ColorTest from './src/ColorTest';
5+
import Test1374 from './src/Test1374';
56
import Test1718 from './src/Test1718';
67
import Test1813 from './src/Test1813';
78
import Test1845 from './src/Test1845';

Diff for: TestsExample/src/Test1374.tsx

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import * as React from 'react';
2+
import { View } from 'react-native';
3+
import Svg, {Circle, SvgXml} from 'react-native-svg';
4+
5+
export default function App() {
6+
const svgXmlWithTransform = `<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="100" height="300" viewBox="0 0 100 100" transform="scale(1 -1)">
7+
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
8+
</svg>`;
9+
const svgXmlWithEmptyStyle = `<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
10+
<circle style=" " cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
11+
</svg>`;
12+
13+
const svgg = `
14+
<svg width="400" height="200">
15+
<polygon points="100 100, 180 100, 140 180" fill="black"></polygon>
16+
<polygon points="100 100, 180 100, 140 180" fill="red" transform="translate(0, 280), scale(1, -1)"></polygon>
17+
</svg>
18+
`;
19+
20+
return (
21+
<View style={{flex: 1}}>
22+
<Svg
23+
width={100}
24+
height={100}
25+
viewBox="0 0 100 100"
26+
transform={[{scaleX: 1}, {scaleY: -1}]}
27+
>
28+
<Circle cx={50} cy={50} r={40} stroke="black" strokeWidth={3} fill="red" />
29+
</Svg>
30+
<SvgXml xml={svgXmlWithTransform}/>
31+
<SvgXml xml={svgXmlWithEmptyStyle}/>
32+
<SvgXml xml={svgg}/>
33+
</View>
34+
);
35+
}

Diff for: src/elements/Shape.tsx

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Component } from 'react';
22
import SvgTouchableMixin from '../lib/SvgTouchableMixin';
3-
import { findNodeHandle, NativeMethods } from 'react-native';
3+
import extractBrush from '../lib/extract/extractBrush';
4+
import { ColorValue, findNodeHandle, NativeMethods } from 'react-native';
45
import {
56
ColumnMajorTransformMatrix,
67
TransformProps,
@@ -249,8 +250,13 @@ export default class Shape<P> extends Component<P> {
249250
setNativeProps = (
250251
props: Object & {
251252
matrix?: ColumnMajorTransformMatrix;
253+
fill?: ColorValue;
252254
} & TransformProps,
253255
) => {
256+
if (props.fill) {
257+
// @ts-ignore TODO: native `fill` prop differs from the one passed in props
258+
props.fill = extractBrush(props.fill);
259+
}
254260
this.root?.setNativeProps(props);
255261
};
256262
/*

Diff for: src/elements/Svg.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export default class Svg extends Shape<SvgProps> {
115115
width,
116116
height,
117117
focusable,
118+
transform,
118119

119120
// Inherited G properties
120121
font,
@@ -182,10 +183,18 @@ export default class Svg extends Shape<SvgProps> {
182183
props.onLayout = onLayout;
183184
}
184185

185-
// transform should not be passed down since it is already used in svgView
186-
// and would be doubled in G causing double transformations
187186
const gStyle = Object.assign({}, style) as ViewStyle;
188-
gStyle.transform = undefined;
187+
// if transform prop is of RN style's kind, we want `SvgView` to handle it
188+
// since it can be done here. Otherwise, if transform is of `svg` kind, e.g. string,
189+
// we want G element to parse it since `Svg` does not include parsing of those custom transforms.
190+
// It is problematic due to fact that we either move the `Svg` or just its `G` child, and in the
191+
// second case, when the `G` leaves the area of `Svg`, it will just disappear.
192+
if (Array.isArray(transform) && typeof transform[0] === 'object') {
193+
gStyle.transform = undefined;
194+
} else {
195+
props.transform = undefined;
196+
gStyle.transform = transform;
197+
}
189198

190199
const RNSVGSvg = Platform.OS === 'android' ? RNSVGSvgAndroid : RNSVGSvgIOS;
191200

Diff for: src/lib/extract/extractFill.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const fillRules: { evenodd: number; nonzero: number } = {
88
nonzero: 1,
99
};
1010

11-
const defaultFill = processColor('black');
11+
const defaultFill = { type: 0, payload: processColor('black') };
1212

1313
export default function extractFill(
1414
o: extractedProps,

0 commit comments

Comments
 (0)