mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-05 07:59:28 +00:00
make reanimated work in web (#1886)
Up until now, trying to use reanimated with react-native-svg in react-native-web resulted in an error. This adds a setNativeProps function to the web implementation to directly modify the transform and style props on a SVGElement ref. Since there is a need to track the "last merged props" and those need to be reset on every render, the render method has been moved into the WebShape class and a tag string property has been added. As g had some extra handling for x and y, a prepareProps function was added as well.
This commit is contained in:
committed by
GitHub
parent
795bff5f37
commit
afaf500db9
@@ -1,3 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
presets: ['module:metro-react-native-babel-preset'],
|
presets: ['module:metro-react-native-babel-preset'],
|
||||||
|
plugins: [
|
||||||
|
'@babel/plugin-proposal-export-namespace-from',
|
||||||
|
'react-native-reanimated/plugin',
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
"react": "18.1.0",
|
"react": "18.1.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-native": "0.70.0",
|
"react-native": "0.70.0",
|
||||||
|
"react-native-reanimated": "^2.10.0",
|
||||||
"react-native-svg": "link:../",
|
"react-native-svg": "link:../",
|
||||||
"react-native-web": "^0.17.7"
|
"react-native-web": "^0.17.7"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -112,6 +112,7 @@ const names: (keyof typeof examples)[] = [
|
|||||||
'TouchEvents',
|
'TouchEvents',
|
||||||
'PanResponder',
|
'PanResponder',
|
||||||
'Reusable',
|
'Reusable',
|
||||||
|
'Reanimated',
|
||||||
];
|
];
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import * as Image from './examples/Image';
|
|||||||
import * as Reusable from './examples/Reusable';
|
import * as Reusable from './examples/Reusable';
|
||||||
import * as TouchEvents from './examples/TouchEvents';
|
import * as TouchEvents from './examples/TouchEvents';
|
||||||
import * as PanResponder from './examples/PanResponder';
|
import * as PanResponder from './examples/PanResponder';
|
||||||
|
import * as Reanimated from './examples/Reanimated';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Svg,
|
Svg,
|
||||||
@@ -34,4 +35,5 @@ export {
|
|||||||
TouchEvents,
|
TouchEvents,
|
||||||
Reusable,
|
Reusable,
|
||||||
PanResponder,
|
PanResponder,
|
||||||
|
Reanimated,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import React, {useEffect} from 'react';
|
||||||
|
import {StyleSheet, Text} from 'react-native';
|
||||||
|
import Reanimated, {
|
||||||
|
useAnimatedProps,
|
||||||
|
useSharedValue,
|
||||||
|
withRepeat,
|
||||||
|
withSpring,
|
||||||
|
withTiming,
|
||||||
|
} from 'react-native-reanimated';
|
||||||
|
import {Svg, Rect} from 'react-native-svg';
|
||||||
|
|
||||||
|
const ReanimatedRect = Reanimated.createAnimatedComponent(Rect);
|
||||||
|
|
||||||
|
function ReanimatedRectExample() {
|
||||||
|
const height = useSharedValue(10);
|
||||||
|
const position = useSharedValue(0);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
height.value = withRepeat(withSpring(100), -1, true);
|
||||||
|
position.value = withRepeat(withTiming(300, {duration: 5000}), -1);
|
||||||
|
});
|
||||||
|
const animatedProps = useAnimatedProps(() => ({
|
||||||
|
width: 30,
|
||||||
|
height: height.value,
|
||||||
|
x: position.value,
|
||||||
|
y: 20,
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Svg height="150" width="300">
|
||||||
|
<ReanimatedRect animatedProps={animatedProps} fill="red" />
|
||||||
|
</Svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ReanimatedRectExample.title = 'reanimated rectangle';
|
||||||
|
|
||||||
|
const samples = [ReanimatedRectExample];
|
||||||
|
|
||||||
|
const style = StyleSheet.create({text: {width: 30, height: 30}});
|
||||||
|
const icon = <Text style={style.text}>R</Text>;
|
||||||
|
|
||||||
|
export {icon, samples};
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"include": ["src/**/*"]
|
"include": ["src/**/*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"skipLibCheck": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ module.exports = {
|
|||||||
fromRoot('index.js'),
|
fromRoot('index.js'),
|
||||||
fromRoot('src'),
|
fromRoot('src'),
|
||||||
fromRoot('node_modules/react-native-svg'),
|
fromRoot('node_modules/react-native-svg'),
|
||||||
|
fromRoot('node_modules/react-native-reanimated'),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -52,4 +53,5 @@ module.exports = {
|
|||||||
'.jsx',
|
'.jsx',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
plugins: [new (require('webpack').DefinePlugin)({process: {env: {}}})],
|
||||||
};
|
};
|
||||||
|
|||||||
+36
-1
@@ -578,6 +578,13 @@
|
|||||||
"@babel/helper-create-regexp-features-plugin" "^7.19.0"
|
"@babel/helper-create-regexp-features-plugin" "^7.19.0"
|
||||||
"@babel/helper-plugin-utils" "^7.19.0"
|
"@babel/helper-plugin-utils" "^7.19.0"
|
||||||
|
|
||||||
|
"@babel/plugin-transform-object-assign@^7.16.7":
|
||||||
|
version "7.18.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-assign/-/plugin-transform-object-assign-7.18.6.tgz#7830b4b6f83e1374a5afb9f6111bcfaea872cdd2"
|
||||||
|
integrity sha512-mQisZ3JfqWh2gVXvfqYCAAyRs6+7oev+myBsTwW5RnPhYXOTuCEw2oe3YgxlXMViXUS53lG8koulI7mJ+8JE+A==
|
||||||
|
dependencies:
|
||||||
|
"@babel/helper-plugin-utils" "^7.18.6"
|
||||||
|
|
||||||
"@babel/plugin-transform-object-super@^7.0.0":
|
"@babel/plugin-transform-object-super@^7.0.0":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c"
|
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c"
|
||||||
@@ -699,7 +706,7 @@
|
|||||||
"@babel/helper-validator-option" "^7.18.6"
|
"@babel/helper-validator-option" "^7.18.6"
|
||||||
"@babel/plugin-transform-flow-strip-types" "^7.18.6"
|
"@babel/plugin-transform-flow-strip-types" "^7.18.6"
|
||||||
|
|
||||||
"@babel/preset-typescript@^7.13.0":
|
"@babel/preset-typescript@^7.13.0", "@babel/preset-typescript@^7.16.7":
|
||||||
version "7.18.6"
|
version "7.18.6"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399"
|
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399"
|
||||||
integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==
|
integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==
|
||||||
@@ -1440,6 +1447,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/invariant@^2.2.35":
|
||||||
|
version "2.2.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.35.tgz#cd3ebf581a6557452735688d8daba6cf0bd5a3be"
|
||||||
|
integrity sha512-DxX1V9P8zdJPYQat1gHyY0xj3efl8gnMVjiM9iCY6y27lj+PoQWkgjt8jDqmovPqULkKVpKRg8J36iQiA+EtEg==
|
||||||
|
|
||||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
|
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
|
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
|
||||||
@@ -5253,6 +5265,11 @@ lodash.debounce@^4.0.8:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||||
|
|
||||||
|
lodash.isequal@^4.5.0:
|
||||||
|
version "4.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
|
||||||
|
integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
|
||||||
|
|
||||||
lodash.merge@^4.6.2:
|
lodash.merge@^4.6.2:
|
||||||
version "4.6.2"
|
version "4.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
|
||||||
@@ -6544,6 +6561,19 @@ react-native-gradle-plugin@^0.70.2:
|
|||||||
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.2.tgz#b5130f2c196e27c4c5912706503d69b8790f1937"
|
resolved "https://registry.yarnpkg.com/react-native-gradle-plugin/-/react-native-gradle-plugin-0.70.2.tgz#b5130f2c196e27c4c5912706503d69b8790f1937"
|
||||||
integrity sha512-k7d+CVh0fs/VntA2WaKD58cFB2rtiSLBHYlciH18ncaT4N/B3A4qOGv9pSCEHfQikELm6vAf98KMbE3c8KnH1A==
|
integrity sha512-k7d+CVh0fs/VntA2WaKD58cFB2rtiSLBHYlciH18ncaT4N/B3A4qOGv9pSCEHfQikELm6vAf98KMbE3c8KnH1A==
|
||||||
|
|
||||||
|
react-native-reanimated@^2.10.0:
|
||||||
|
version "2.10.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-native-reanimated/-/react-native-reanimated-2.10.0.tgz#ed53be66bbb553b5b5e93e93ef4217c87b8c73db"
|
||||||
|
integrity sha512-jKm3xz5nX7ABtHzzuuLmawP0pFWP77lXNdIC6AWOceBs23OHUaJ29p4prxr/7Sb588GwTbkPsYkDqVFaE3ezNQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/plugin-transform-object-assign" "^7.16.7"
|
||||||
|
"@babel/preset-typescript" "^7.16.7"
|
||||||
|
"@types/invariant" "^2.2.35"
|
||||||
|
invariant "^2.2.4"
|
||||||
|
lodash.isequal "^4.5.0"
|
||||||
|
setimmediate "^1.0.5"
|
||||||
|
string-hash-64 "^1.0.3"
|
||||||
|
|
||||||
"react-native-svg@link:..":
|
"react-native-svg@link:..":
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
uid ""
|
uid ""
|
||||||
@@ -7353,6 +7383,11 @@ statuses@2.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||||
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
|
integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
|
||||||
|
|
||||||
|
string-hash-64@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-hash-64/-/string-hash-64-1.0.3.tgz#0deb56df58678640db5c479ccbbb597aaa0de322"
|
||||||
|
integrity sha512-D5OKWKvDhyVWWn2x5Y9b+37NUllks34q1dCDhk/vYcso9fmhs+Tl3KR/gE4v5UNj2UA35cnX4KdVVGkG1deKqw==
|
||||||
|
|
||||||
string-length@^4.0.1:
|
string-length@^4.0.1:
|
||||||
version "4.0.2"
|
version "4.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
|
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
|
||||||
|
|||||||
+108
-76
@@ -58,13 +58,19 @@ interface BaseProps {
|
|||||||
fontWeight?: NumberProp;
|
fontWeight?: NumberProp;
|
||||||
fontSize?: NumberProp;
|
fontSize?: NumberProp;
|
||||||
fontFamily?: string;
|
fontFamily?: string;
|
||||||
forwardedRef: {};
|
forwardedRef?:
|
||||||
|
| React.RefCallback<SVGElement>
|
||||||
|
| React.MutableRefObject<SVGElement | null>;
|
||||||
style: Iterable<{}>;
|
style: Iterable<{}>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasTouchableProperty = (props: BaseProps) =>
|
const hasTouchableProperty = (props: BaseProps) =>
|
||||||
props.onPress || props.onPressIn || props.onPressOut || props.onLongPress;
|
props.onPress || props.onPressIn || props.onPressOut || props.onLongPress;
|
||||||
|
|
||||||
|
const camelCaseToDashed = (camelCase: string) => {
|
||||||
|
return camelCase.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `react-native-svg` supports additional props that aren't defined in the spec.
|
* `react-native-svg` supports additional props that aren't defined in the spec.
|
||||||
* This function replaces them in a spec conforming manner.
|
* This function replaces them in a spec conforming manner.
|
||||||
@@ -156,9 +162,14 @@ const prepare = <T extends BaseProps>(
|
|||||||
clean.transform = transform.join(' ');
|
clean.transform = transform.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (forwardedRef) {
|
clean.ref = (el: SVGElement | null) => {
|
||||||
clean.ref = forwardedRef;
|
self.elementRef.current = el;
|
||||||
}
|
if (typeof forwardedRef === 'function') {
|
||||||
|
forwardedRef(el);
|
||||||
|
} else if (forwardedRef) {
|
||||||
|
forwardedRef.current = el;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const styles: {
|
const styles: {
|
||||||
fontStyle?: string;
|
fontStyle?: string;
|
||||||
@@ -237,6 +248,53 @@ export class WebShape<
|
|||||||
C = {},
|
C = {},
|
||||||
> extends React.Component<P, C> {
|
> extends React.Component<P, C> {
|
||||||
[x: string]: unknown;
|
[x: string]: unknown;
|
||||||
|
protected tag?: React.ElementType;
|
||||||
|
protected prepareProps(props: P) {
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
elementRef =
|
||||||
|
React.createRef<SVGElement>() as React.MutableRefObject<SVGElement | null>;
|
||||||
|
lastMergedProps: Partial<P> = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disclaimer: I am not sure why the props are wrapped in a `style` attribute here, but that's how reanimated calls it
|
||||||
|
*/
|
||||||
|
setNativeProps(props: { style: P }) {
|
||||||
|
const merged = Object.assign(
|
||||||
|
{},
|
||||||
|
this.props,
|
||||||
|
this.lastMergedProps,
|
||||||
|
props.style,
|
||||||
|
);
|
||||||
|
this.lastMergedProps = merged;
|
||||||
|
const clean = prepare(this, this.prepareProps(merged));
|
||||||
|
const current = this.elementRef.current;
|
||||||
|
if (current) {
|
||||||
|
for (const cleanAttribute of Object.keys(clean)) {
|
||||||
|
const cleanValue = clean[cleanAttribute as keyof typeof clean];
|
||||||
|
switch (cleanAttribute) {
|
||||||
|
case 'ref':
|
||||||
|
case 'children':
|
||||||
|
break;
|
||||||
|
case 'style':
|
||||||
|
// style can be an object here or an array, so we convert it to an array and assign each element
|
||||||
|
for (const partialStyle of ([] as {}[]).concat(clean.style ?? [])) {
|
||||||
|
// @ts-expect-error "DOM" is not part of `compilerOptions.lib`
|
||||||
|
Object.assign(current.style, partialStyle);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// apply all other incoming prop updates as attributes on the node
|
||||||
|
// same logic as in https://github.com/software-mansion/react-native-reanimated/blob/d04720c82f5941532991b235787285d36d717247/src/reanimated2/js-reanimated/index.ts#L38-L39
|
||||||
|
// @ts-expect-error "DOM" is not part of `compilerOptions.lib`
|
||||||
|
current.setAttribute(camelCaseToDashed(cleanAttribute), cleanValue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_remeasureMetricsOnActivation: () => void;
|
_remeasureMetricsOnActivation: () => void;
|
||||||
touchableHandleStartShouldSetResponder?: (
|
touchableHandleStartShouldSetResponder?: (
|
||||||
e: GestureResponderEvent,
|
e: GestureResponderEvent,
|
||||||
@@ -258,30 +316,35 @@ export class WebShape<
|
|||||||
|
|
||||||
this._remeasureMetricsOnActivation = remeasure.bind(this);
|
this._remeasureMetricsOnActivation = remeasure.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
render(): JSX.Element {
|
||||||
|
if (!this.tag) {
|
||||||
|
throw new Error(
|
||||||
|
'When extending `WebShape` you need to overwrite either `tag` or `render`!',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
this.lastMergedProps = {};
|
||||||
|
return createElement(
|
||||||
|
this.tag,
|
||||||
|
prepare(this, this.prepareProps(this.props)),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Circle extends WebShape {
|
export class Circle extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'circle' as const;
|
||||||
return createElement('circle', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ClipPath extends WebShape {
|
export class ClipPath extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'clipPath' as const;
|
||||||
return createElement('clipPath', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Defs extends WebShape {
|
export class Defs extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'defs' as const;
|
||||||
return createElement('defs', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Ellipse extends WebShape {
|
export class Ellipse extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'ellipse' as const;
|
||||||
return createElement('ellipse', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class G extends WebShape<
|
export class G extends WebShape<
|
||||||
@@ -291,129 +354,98 @@ export class G extends WebShape<
|
|||||||
translate?: string;
|
translate?: string;
|
||||||
}
|
}
|
||||||
> {
|
> {
|
||||||
render(): JSX.Element {
|
tag = 'g' as const;
|
||||||
const { x, y, ...rest } = this.props;
|
prepareProps(
|
||||||
|
props: BaseProps & {
|
||||||
|
x?: NumberProp;
|
||||||
|
y?: NumberProp;
|
||||||
|
translate?: string;
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const { x, y, ...rest } = props;
|
||||||
|
|
||||||
if ((x || y) && !rest.translate) {
|
if ((x || y) && !rest.translate) {
|
||||||
rest.translate = `${x || 0}, ${y || 0}`;
|
rest.translate = `${x || 0}, ${y || 0}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return createElement('g', prepare(this, rest));
|
return rest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Image extends WebShape {
|
export class Image extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'image' as const;
|
||||||
return createElement('image', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Line extends WebShape {
|
export class Line extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'line' as const;
|
||||||
return createElement('line', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LinearGradient extends WebShape {
|
export class LinearGradient extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'linearGradient' as const;
|
||||||
return createElement('linearGradient', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Path extends WebShape {
|
export class Path extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'path' as const;
|
||||||
return createElement('path', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Polygon extends WebShape {
|
export class Polygon extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'polygon' as const;
|
||||||
return createElement('polygon', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Polyline extends WebShape {
|
export class Polyline extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'polyline' as const;
|
||||||
return createElement('polyline', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class RadialGradient extends WebShape {
|
export class RadialGradient extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'radialGradient' as const;
|
||||||
return createElement('radialGradient', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Rect extends WebShape {
|
export class Rect extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'rect' as const;
|
||||||
return createElement('rect', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Stop extends WebShape {
|
export class Stop extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'stop' as const;
|
||||||
return createElement('stop', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Svg extends WebShape {
|
export class Svg extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'svg' as const;
|
||||||
return createElement('svg', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Symbol extends WebShape {
|
export class Symbol extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'symbol' as const;
|
||||||
return createElement('symbol', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Text extends WebShape {
|
export class Text extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'text' as const;
|
||||||
return createElement('text', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TSpan extends WebShape {
|
export class TSpan extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'tspan' as const;
|
||||||
return createElement('tspan', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TextPath extends WebShape {
|
export class TextPath extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'textPath' as const;
|
||||||
return createElement('textPath', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Use extends WebShape {
|
export class Use extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'use' as const;
|
||||||
return createElement('use', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Mask extends WebShape {
|
export class Mask extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'mask' as const;
|
||||||
return createElement('mask', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ForeignObject extends WebShape {
|
export class ForeignObject extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'foreignObject' as const;
|
||||||
return createElement('foreignObject', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Marker extends WebShape {
|
export class Marker extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'marker' as const;
|
||||||
return createElement('marker', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Pattern extends WebShape {
|
export class Pattern extends WebShape {
|
||||||
render(): JSX.Element {
|
tag = 'pattern' as const;
|
||||||
return createElement('pattern', prepare(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Svg;
|
export default Svg;
|
||||||
|
|||||||
Reference in New Issue
Block a user