mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-06 07:06:11 +00:00
fix: proper transform prop handling (#1895)
PR aligning handling of transform prop between web and native and adding proper handling of transform prop on web. origin prop is now treated as transform-origin since it seems like the current behavior of this prop on native platforms. transform prop cannot be an object with transform properties since it does not provide order of transformations which would lead to undefined behavior so this option has been removed. RN style of transform prop (array of rotation objects) can now be used font-size on web seems to be 16px by default and it is 12 in library - maybe we should align it somehow removed maskTransform prop since it does not exist in SVG standard and did nothing on native side fixed typo in Fabric Pattern updateProps method
This commit is contained in:
@@ -368,7 +368,34 @@ PODS:
|
||||
- React-jsi (= 0.70.0)
|
||||
- React-logger (= 0.70.0)
|
||||
- React-perflogger (= 0.70.0)
|
||||
- RNSVG (13.2.0):
|
||||
- RNReanimated (2.10.0):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
- glog
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
- React-callinvoker
|
||||
- React-Core
|
||||
- React-Core/DevSupport
|
||||
- React-Core/RCTWebSocket
|
||||
- React-CoreModules
|
||||
- React-cxxreact
|
||||
- React-jsi
|
||||
- React-jsiexecutor
|
||||
- React-jsinspector
|
||||
- React-RCTActionSheet
|
||||
- React-RCTAnimation
|
||||
- React-RCTBlob
|
||||
- React-RCTImage
|
||||
- React-RCTLinking
|
||||
- React-RCTNetwork
|
||||
- React-RCTSettings
|
||||
- React-RCTText
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNSVG (13.4.0):
|
||||
- React-Core
|
||||
- SocketRocket (0.6.0)
|
||||
- Yoga (1.14.0)
|
||||
@@ -434,6 +461,7 @@ DEPENDENCIES:
|
||||
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
|
||||
- React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
|
||||
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
|
||||
- RNReanimated (from `../node_modules/react-native-reanimated`)
|
||||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
@@ -522,6 +550,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
|
||||
ReactCommon:
|
||||
:path: "../node_modules/react-native/ReactCommon"
|
||||
RNReanimated:
|
||||
:path: "../node_modules/react-native-reanimated"
|
||||
RNSVG:
|
||||
:path: "../node_modules/react-native-svg"
|
||||
Yoga:
|
||||
@@ -530,7 +560,7 @@ EXTERNAL SOURCES:
|
||||
SPEC CHECKSUMS:
|
||||
boost: a7c83b31436843459a1961bfd74b96033dc77234
|
||||
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
|
||||
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
|
||||
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
|
||||
FBLazyVector: 6c76fe46345039d5cf0549e9ddaf5aa169630a4a
|
||||
FBReactNativeSpec: 1a270246542f5c52248cb26a96db119cfe3cb760
|
||||
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
|
||||
@@ -543,7 +573,7 @@ SPEC CHECKSUMS:
|
||||
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
|
||||
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86
|
||||
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
|
||||
glog: 476ee3e89abb49e07f822b48323c51c57124b572
|
||||
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
|
||||
hermes-engine: 8e84f1284180801c1a1b241f443ba64f931ff561
|
||||
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
|
||||
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
|
||||
@@ -574,7 +604,8 @@ SPEC CHECKSUMS:
|
||||
React-RCTVibration: 5499b77c0fd57f346a5f0b36bb79fdb020d17d3e
|
||||
React-runtimeexecutor: 80c195ffcafb190f531fdc849dc2d19cb4bb2b34
|
||||
ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b
|
||||
RNSVG: 07037623c36f12e41312730622d5f6b3656227ca
|
||||
RNReanimated: 60e291d42c77752a0f6d6f358387bdf225a87c6e
|
||||
RNSVG: 07dbd870b0dcdecc99b3a202fa37c8ca163caec2
|
||||
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
|
||||
Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9
|
||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||
|
||||
@@ -113,6 +113,7 @@ const names: (keyof typeof examples)[] = [
|
||||
'PanResponder',
|
||||
'Reusable',
|
||||
'Reanimated',
|
||||
'Transforms',
|
||||
];
|
||||
|
||||
const initialState = {
|
||||
|
||||
@@ -16,6 +16,7 @@ import * as Reusable from './examples/Reusable';
|
||||
import * as TouchEvents from './examples/TouchEvents';
|
||||
import * as PanResponder from './examples/PanResponder';
|
||||
import * as Reanimated from './examples/Reanimated';
|
||||
import * as Transforms from './examples/Transforms';
|
||||
|
||||
export {
|
||||
Svg,
|
||||
@@ -36,4 +37,5 @@ export {
|
||||
Reusable,
|
||||
PanResponder,
|
||||
Reanimated,
|
||||
Transforms,
|
||||
};
|
||||
|
||||
134
Example/src/examples/Transforms.tsx
Normal file
134
Example/src/examples/Transforms.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Platform} from 'react-native';
|
||||
|
||||
import {
|
||||
Svg,
|
||||
Circle,
|
||||
Rect,
|
||||
Pattern,
|
||||
RadialGradient,
|
||||
Stop,
|
||||
SvgXml,
|
||||
} from 'react-native-svg';
|
||||
|
||||
const patternXml = `
|
||||
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Apply a transform on the tile -->
|
||||
<pattern
|
||||
id="p1"
|
||||
width=".25"
|
||||
height=".25"
|
||||
patternTransform="rotate(20)
|
||||
skewX(30)
|
||||
scale(1 0.5)">
|
||||
<circle cx="10" cy="10" r="10" fill="black" />
|
||||
</pattern>
|
||||
|
||||
<rect x="10" y="10" width="80" height="80" fill="url(#p1)" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
class PatternTransformExample extends Component {
|
||||
static title = 'Pattern transform';
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Svg height="100" width="300" viewBox="0 0 200 100">
|
||||
<Pattern
|
||||
id="p1"
|
||||
width="0.25"
|
||||
height="0.25"
|
||||
patternTransform={[
|
||||
{rotate: '20'},
|
||||
{skewX: '30'},
|
||||
{scaleX: 1},
|
||||
{scaleY: 0.5},
|
||||
]}>
|
||||
<Circle fill="black" cx="10" cy="10" r="10" />
|
||||
</Pattern>
|
||||
<Pattern
|
||||
id="p2"
|
||||
width="0.25"
|
||||
height="0.25"
|
||||
patternTransform="rotate(20) skewX(30) scale(1 0.5)">
|
||||
<Circle fill="black" cx="10" cy="10" r="10" />
|
||||
</Pattern>
|
||||
<Rect x="10" y="10" width="80" height="80" fill="url(#p1)" />
|
||||
<Rect
|
||||
x="10"
|
||||
y="10"
|
||||
width="80"
|
||||
height="80"
|
||||
fill="url(#p2)"
|
||||
transform={[{translateX: 100}]}
|
||||
/>
|
||||
</Svg>
|
||||
{Platform.OS !== 'web' && (
|
||||
<SvgXml width="100" height="100" xml={patternXml} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GradientTransformExample extends Component {
|
||||
static title = 'Gradient transform';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="200" width="300" viewBox="0 0 420 200">
|
||||
<RadialGradient
|
||||
id="gradient1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="100"
|
||||
cy="100"
|
||||
r="100"
|
||||
fx="100"
|
||||
fy="100">
|
||||
<Stop offset="0%" stopColor="darkblue" />
|
||||
<Stop offset="50%" stopColor="skyblue" />
|
||||
<Stop offset="100%" stopColor="darkblue" />
|
||||
</RadialGradient>
|
||||
<RadialGradient
|
||||
id="gradient2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="100"
|
||||
cy="100"
|
||||
r="100"
|
||||
fx="100"
|
||||
fy="100"
|
||||
gradientTransform="skewX(20) translate(-35, 0)">
|
||||
<Stop offset="0%" stopColor="darkblue" />
|
||||
<Stop offset="50%" stopColor="skyblue" />
|
||||
<Stop offset="100%" stopColor="darkblue" />
|
||||
</RadialGradient>
|
||||
|
||||
<Rect x="0" y="0" width="200" height="200" fill="url(#gradient1)" />
|
||||
<Rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="200"
|
||||
height="200"
|
||||
fill="url(#gradient2)"
|
||||
transform="translate(220)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const icon = (
|
||||
<Svg height="30" width="30" viewBox="0 0 100 100">
|
||||
<Pattern
|
||||
id="p1"
|
||||
width="0.25"
|
||||
height="0.25"
|
||||
patternTransform="rotate(20) skewX(30) scale(1 0.5)">
|
||||
<Circle fill="black" cx="10" cy="10" r="10" />
|
||||
</Pattern>
|
||||
<Rect x="10" y="10" width="80" height="80" fill="url(#p1)" />
|
||||
</Svg>
|
||||
);
|
||||
|
||||
const samples = [PatternTransformExample, GradientTransformExample];
|
||||
|
||||
export {icon, samples};
|
||||
@@ -697,7 +697,7 @@ PODS:
|
||||
- React-jsi (= 0.70.0)
|
||||
- React-logger (= 0.70.0)
|
||||
- React-perflogger (= 0.70.0)
|
||||
- RNSVG (13.2.0):
|
||||
- RNSVG (13.4.0):
|
||||
- RCT-Folly
|
||||
- RCTRequired
|
||||
- RCTTypeSafety
|
||||
@@ -927,7 +927,7 @@ SPEC CHECKSUMS:
|
||||
React-rncore: 8858fe6b719170c20c197a8fd2dd53507bdae04b
|
||||
React-runtimeexecutor: 80c195ffcafb190f531fdc849dc2d19cb4bb2b34
|
||||
ReactCommon: de55f940495d7bf87b5d7bf55b5b15cdd50d7d7b
|
||||
RNSVG: fa7f6f437c90eea1fbc3d142a40365d561824ab3
|
||||
RNSVG: 8ef4c60d9378eab6996a3f006dfb5784e6dab302
|
||||
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
|
||||
Yoga: 82c9e8f652789f67d98bed5aef9d6653f71b04a9
|
||||
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
|
||||
|
||||
@@ -112,6 +112,7 @@ const names = [
|
||||
'TouchEvents',
|
||||
'PanResponder',
|
||||
'Reusable',
|
||||
'Transforms',
|
||||
];
|
||||
|
||||
const initialState = {
|
||||
|
||||
@@ -15,6 +15,7 @@ import * as Image from './examples/Image';
|
||||
import * as Reusable from './examples/Reusable';
|
||||
import * as TouchEvents from './examples/TouchEvents';
|
||||
import * as PanResponder from './examples/PanResponder';
|
||||
import * as Transforms from './examples/Transforms';
|
||||
|
||||
export {
|
||||
Svg,
|
||||
@@ -34,4 +35,5 @@ export {
|
||||
TouchEvents,
|
||||
Reusable,
|
||||
PanResponder,
|
||||
Transforms,
|
||||
};
|
||||
|
||||
134
FabricExample/src/examples/Transforms.tsx
Normal file
134
FabricExample/src/examples/Transforms.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
import React, {Component} from 'react';
|
||||
import {Platform} from 'react-native';
|
||||
|
||||
import {
|
||||
Svg,
|
||||
Circle,
|
||||
Rect,
|
||||
Pattern,
|
||||
RadialGradient,
|
||||
Stop,
|
||||
SvgXml,
|
||||
} from 'react-native-svg';
|
||||
|
||||
const patternXml = `
|
||||
<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||
<!-- Apply a transform on the tile -->
|
||||
<pattern
|
||||
id="p1"
|
||||
width=".25"
|
||||
height=".25"
|
||||
patternTransform="rotate(20)
|
||||
skewX(30)
|
||||
scale(1 0.5)">
|
||||
<circle cx="10" cy="10" r="10" fill="black" />
|
||||
</pattern>
|
||||
|
||||
<rect x="10" y="10" width="80" height="80" fill="url(#p1)" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
class PatternTransformExample extends Component {
|
||||
static title = 'Pattern transform';
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<Svg height="100" width="300" viewBox="0 0 200 100">
|
||||
<Pattern
|
||||
id="p1"
|
||||
width="0.25"
|
||||
height="0.25"
|
||||
patternTransform={[
|
||||
{rotate: '20'},
|
||||
{skewX: '30'},
|
||||
{scaleX: 1},
|
||||
{scaleY: 0.5},
|
||||
]}>
|
||||
<Circle fill="black" cx="10" cy="10" r="10" />
|
||||
</Pattern>
|
||||
<Pattern
|
||||
id="p2"
|
||||
width="0.25"
|
||||
height="0.25"
|
||||
patternTransform="rotate(20) skewX(30) scale(1 0.5)">
|
||||
<Circle fill="black" cx="10" cy="10" r="10" />
|
||||
</Pattern>
|
||||
<Rect x="10" y="10" width="80" height="80" fill="url(#p1)" />
|
||||
<Rect
|
||||
x="10"
|
||||
y="10"
|
||||
width="80"
|
||||
height="80"
|
||||
fill="url(#p2)"
|
||||
transform={[{translateX: 100}]}
|
||||
/>
|
||||
</Svg>
|
||||
{Platform.OS !== 'web' && (
|
||||
<SvgXml width="100" height="100" xml={patternXml} />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class GradientTransformExample extends Component {
|
||||
static title = 'Gradient transform';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="200" width="300" viewBox="0 0 420 200">
|
||||
<RadialGradient
|
||||
id="gradient1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="100"
|
||||
cy="100"
|
||||
r="100"
|
||||
fx="100"
|
||||
fy="100">
|
||||
<Stop offset="0%" stopColor="darkblue" />
|
||||
<Stop offset="50%" stopColor="skyblue" />
|
||||
<Stop offset="100%" stopColor="darkblue" />
|
||||
</RadialGradient>
|
||||
<RadialGradient
|
||||
id="gradient2"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
cx="100"
|
||||
cy="100"
|
||||
r="100"
|
||||
fx="100"
|
||||
fy="100"
|
||||
gradientTransform="skewX(20) translate(-35, 0)">
|
||||
<Stop offset="0%" stopColor="darkblue" />
|
||||
<Stop offset="50%" stopColor="skyblue" />
|
||||
<Stop offset="100%" stopColor="darkblue" />
|
||||
</RadialGradient>
|
||||
|
||||
<Rect x="0" y="0" width="200" height="200" fill="url(#gradient1)" />
|
||||
<Rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="200"
|
||||
height="200"
|
||||
fill="url(#gradient2)"
|
||||
transform="translate(220)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const icon = (
|
||||
<Svg height="30" width="30" viewBox="0 0 100 100">
|
||||
<Pattern
|
||||
id="p1"
|
||||
width="0.25"
|
||||
height="0.25"
|
||||
patternTransform="rotate(20) skewX(30) scale(1 0.5)">
|
||||
<Circle fill="black" cx="10" cy="10" r="10" />
|
||||
</Pattern>
|
||||
<Rect x="10" y="10" width="80" height="80" fill="url(#p1)" />
|
||||
</Svg>
|
||||
);
|
||||
|
||||
const samples = [PatternTransformExample, GradientTransformExample];
|
||||
|
||||
export {icon, samples};
|
||||
@@ -9,13 +9,8 @@
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Matrix;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressLint("ViewConstructor")
|
||||
class MaskView extends GroupView {
|
||||
@@ -32,14 +27,6 @@ class MaskView extends GroupView {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
private Brush.BrushUnits mMaskContentUnits;
|
||||
|
||||
private static final float[] sRawMatrix =
|
||||
new float[] {
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 0, 1
|
||||
};
|
||||
private Matrix mMatrix = null;
|
||||
|
||||
public MaskView(ReactContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
@@ -128,24 +115,6 @@ class MaskView extends GroupView {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setMaskTransform(@Nullable ReadableArray matrixArray) {
|
||||
if (matrixArray != null) {
|
||||
int matrixSize = PropHelper.toMatrixData(matrixArray, sRawMatrix, mScale);
|
||||
if (matrixSize == 6) {
|
||||
if (mMatrix == null) {
|
||||
mMatrix = new Matrix();
|
||||
}
|
||||
mMatrix.setValues(sRawMatrix);
|
||||
} else if (matrixSize != -1) {
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: Transform matrices must be of size 6");
|
||||
}
|
||||
} else {
|
||||
mMatrix = null;
|
||||
}
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
void saveDefinition() {
|
||||
if (mName != null) {
|
||||
|
||||
@@ -27,9 +27,8 @@ import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.bridge.ReadableType;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.touch.ReactHitSlopView;
|
||||
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -37,7 +36,7 @@ import java.util.regex.Pattern;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "RedundantSuppression"})
|
||||
abstract public class RenderableView extends VirtualView implements ReactHitSlopView {
|
||||
public abstract class RenderableView extends VirtualView implements ReactHitSlopView {
|
||||
|
||||
RenderableView(ReactContext reactContext) {
|
||||
super(reactContext);
|
||||
@@ -96,23 +95,23 @@ abstract public class RenderableView extends VirtualView implements ReactHitSlop
|
||||
|
||||
private static final Pattern regex = Pattern.compile("[0-9.-]+");
|
||||
|
||||
@Nullable
|
||||
public Rect getHitSlopRect() {
|
||||
/*
|
||||
* In order to make the isTouchPointInView fail we need to return a very improbable Rect for the View
|
||||
* This way an SVG with box_none carrying its last descendent with box_none will have the expected behavior of just having events on the actual painted area
|
||||
*/
|
||||
if (mPointerEvents == PointerEvents.BOX_NONE) {
|
||||
return new Rect(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||
}
|
||||
return null;
|
||||
@Nullable
|
||||
public Rect getHitSlopRect() {
|
||||
/*
|
||||
* In order to make the isTouchPointInView fail we need to return a very improbable Rect for the View
|
||||
* This way an SVG with box_none carrying its last descendent with box_none will have the expected behavior of just having events on the actual painted area
|
||||
*/
|
||||
if (mPointerEvents == PointerEvents.BOX_NONE) {
|
||||
return new Rect(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(int id) {
|
||||
super.setId(id);
|
||||
RenderableViewManager.setRenderableView(id, this);
|
||||
}
|
||||
@Override
|
||||
public void setId(int id) {
|
||||
super.setId(id);
|
||||
RenderableViewManager.setRenderableView(id, this);
|
||||
}
|
||||
|
||||
public void setVectorEffect(int vectorEffect) {
|
||||
this.vectorEffect = vectorEffect;
|
||||
|
||||
@@ -1714,11 +1714,6 @@ class RenderableViewManager<T extends RenderableView> extends VirtualViewManager
|
||||
public void setMaskContentUnits(MaskView node, int maskContentUnits) {
|
||||
node.setMaskContentUnits(maskContentUnits);
|
||||
}
|
||||
|
||||
@ReactProp(name = "maskTransform")
|
||||
public void setMaskTransform(MaskView node, @Nullable ReadableArray matrixArray) {
|
||||
node.setMaskTransform(matrixArray);
|
||||
}
|
||||
}
|
||||
|
||||
static class ForeignObjectManager extends GroupViewManagerAbstract<ForeignObjectView>
|
||||
|
||||
@@ -167,9 +167,6 @@ public class RNSVGMaskManagerDelegate<T extends View, U extends BaseViewManagerI
|
||||
case "maskContentUnits":
|
||||
mViewManager.setMaskContentUnits(view, value == null ? 0 : ((Double) value).intValue());
|
||||
break;
|
||||
case "maskTransform":
|
||||
mViewManager.setMaskTransform(view, (ReadableArray) value);
|
||||
break;
|
||||
default:
|
||||
super.setProperty(view, propName, value);
|
||||
}
|
||||
|
||||
@@ -56,5 +56,4 @@ public interface RNSVGMaskManagerInterface<T extends View> {
|
||||
void setWidth(T view, @Nullable Double value);
|
||||
void setMaskUnits(T view, int value);
|
||||
void setMaskContentUnits(T view, int value);
|
||||
void setMaskTransform(T view, @Nullable ReadableArray value);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,5 @@
|
||||
@property (nonatomic, strong) RNSVGLength *maskheight;
|
||||
@property (nonatomic, assign) RNSVGUnits maskUnits;
|
||||
@property (nonatomic, assign) RNSVGUnits maskContentUnits;
|
||||
@property (nonatomic, assign) CGAffineTransform maskTransform;
|
||||
|
||||
@end
|
||||
|
||||
@@ -53,15 +53,6 @@ using namespace facebook::react;
|
||||
}
|
||||
self.maskUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
|
||||
self.maskContentUnits = newProps.maskUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
|
||||
if (newProps.maskTransform.size() == 6) {
|
||||
self.maskTransform = CGAffineTransformMake(
|
||||
newProps.maskTransform.at(0),
|
||||
newProps.maskTransform.at(1),
|
||||
newProps.maskTransform.at(2),
|
||||
newProps.maskTransform.at(3),
|
||||
newProps.maskTransform.at(4),
|
||||
newProps.maskTransform.at(5));
|
||||
}
|
||||
|
||||
setCommonGroupProps(newProps, self);
|
||||
_props = std::static_pointer_cast<RNSVGMaskProps const>(props);
|
||||
@@ -76,7 +67,6 @@ using namespace facebook::react;
|
||||
_maskwidth = nil;
|
||||
_maskUnits = kRNSVGUnitsObjectBoundingBox;
|
||||
_maskContentUnits = kRNSVGUnitsObjectBoundingBox;
|
||||
_maskTransform = CGAffineTransformIdentity;
|
||||
}
|
||||
#endif // RN_FABRIC_ENABLED
|
||||
|
||||
@@ -151,12 +141,6 @@ using namespace facebook::react;
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
- (void)setMaskTransform:(CGAffineTransform)maskTransform
|
||||
{
|
||||
_maskTransform = maskTransform;
|
||||
[self invalidate];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#ifdef RN_FABRIC_ENABLED
|
||||
|
||||
@@ -52,7 +52,8 @@ using namespace facebook::react;
|
||||
self.patternwidth = [RNSVGLength lengthWithString:RCTNSStringFromString(newProps.width)];
|
||||
}
|
||||
self.patternUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
|
||||
self.patternContentUnits = newProps.patternUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
|
||||
self.patternContentUnits =
|
||||
newProps.patternContentUnits == 0 ? kRNSVGUnitsObjectBoundingBox : kRNSVGUnitsUserSpaceOnUse;
|
||||
if (newProps.patternTransform.size() == 6) {
|
||||
self.patternTransform = CGAffineTransformMake(
|
||||
newProps.patternTransform.at(0),
|
||||
|
||||
@@ -30,6 +30,5 @@ RCT_CUSTOM_VIEW_PROPERTY(width, id, RNSVGMask)
|
||||
}
|
||||
RCT_EXPORT_VIEW_PROPERTY(maskUnits, RNSVGUnits)
|
||||
RCT_EXPORT_VIEW_PROPERTY(maskContentUnits, RNSVGUnits)
|
||||
RCT_EXPORT_VIEW_PROPERTY(maskTransform, CGAffineTransform)
|
||||
|
||||
@end
|
||||
|
||||
@@ -1,20 +1,15 @@
|
||||
// @ts-ignore
|
||||
import * as React from 'react';
|
||||
import {
|
||||
GestureResponderEvent,
|
||||
// @ts-ignore
|
||||
unstable_createElement as ucE,
|
||||
// @ts-ignore
|
||||
createElement as cE,
|
||||
TransformsStyle,
|
||||
} from 'react-native';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberArray,
|
||||
NumberProp,
|
||||
TransformObject,
|
||||
} from './lib/extract/types';
|
||||
import { NumberArray, NumberProp, TransformProps } from './lib/extract/types';
|
||||
import SvgTouchableMixin from './lib/SvgTouchableMixin';
|
||||
import { resolve } from './lib/resolve';
|
||||
import { transformsArrayToProps } from './lib/extract/extractTransform';
|
||||
|
||||
const createElement = cE || ucE;
|
||||
|
||||
@@ -49,19 +44,19 @@ interface BaseProps {
|
||||
pressRetentionOffset?: EdgeInsetsProp;
|
||||
rejectResponderTermination?: boolean;
|
||||
|
||||
transform: ColumnMajorTransformMatrix | string | TransformObject;
|
||||
translate: NumberArray;
|
||||
translateX: NumberProp;
|
||||
translateY: NumberProp;
|
||||
scale: NumberArray;
|
||||
scaleX: NumberProp;
|
||||
scaleY: NumberProp;
|
||||
rotation: NumberArray;
|
||||
skewX: NumberProp;
|
||||
skewY: NumberProp;
|
||||
origin: NumberArray;
|
||||
originX: NumberProp;
|
||||
originY: NumberProp;
|
||||
transform?: TransformProps['transform'];
|
||||
translate?: NumberArray;
|
||||
translateX?: NumberProp;
|
||||
translateY?: NumberProp;
|
||||
scale?: NumberArray;
|
||||
scaleX?: NumberProp;
|
||||
scaleY?: NumberProp;
|
||||
rotation?: NumberProp;
|
||||
skewX?: NumberProp;
|
||||
skewY?: NumberProp;
|
||||
origin?: NumberArray;
|
||||
originX?: NumberProp;
|
||||
originY?: NumberProp;
|
||||
|
||||
fontStyle?: string;
|
||||
fontWeight?: NumberProp;
|
||||
@@ -71,6 +66,10 @@ interface BaseProps {
|
||||
| React.RefCallback<SVGElement>
|
||||
| React.MutableRefObject<SVGElement | null>;
|
||||
style: Iterable<{}>;
|
||||
|
||||
// different tranform props
|
||||
gradientTransform: TransformProps['transform'];
|
||||
patternTransform: TransformProps['transform'];
|
||||
}
|
||||
|
||||
const hasTouchableProperty = (props: BaseProps) =>
|
||||
@@ -80,6 +79,63 @@ const camelCaseToDashed = (camelCase: string) => {
|
||||
return camelCase.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
|
||||
};
|
||||
|
||||
function stringifyTransformProps(transformProps: TransformProps) {
|
||||
const transformArray = [];
|
||||
if (transformProps.translate != null) {
|
||||
transformArray.push(`translate(${transformProps.translate})`);
|
||||
}
|
||||
if (transformProps.translateX != null || transformProps.translateY != null) {
|
||||
transformArray.push(
|
||||
`translate(${transformProps.translateX || 0}, ${
|
||||
transformProps.translateY || 0
|
||||
})`,
|
||||
);
|
||||
}
|
||||
if (transformProps.scale != null) {
|
||||
transformArray.push(`scale(${transformProps.scale})`);
|
||||
}
|
||||
if (transformProps.scaleX != null || transformProps.scaleY != null) {
|
||||
transformArray.push(
|
||||
`scale(${transformProps.scaleX || 1}, ${transformProps.scaleY || 1})`,
|
||||
);
|
||||
}
|
||||
// rotation maps to rotate, not to collide with the text rotate attribute (which acts per glyph rather than block)
|
||||
if (transformProps.rotation != null) {
|
||||
transformArray.push(`rotate(${transformProps.rotation})`);
|
||||
}
|
||||
if (transformProps.skewX != null) {
|
||||
transformArray.push(`skewX(${transformProps.skewX})`);
|
||||
}
|
||||
if (transformProps.skewY != null) {
|
||||
transformArray.push(`skewY(${transformProps.skewY})`);
|
||||
}
|
||||
return transformArray;
|
||||
}
|
||||
|
||||
function parseTransformProp(
|
||||
transform: TransformProps['transform'],
|
||||
props?: BaseProps,
|
||||
) {
|
||||
const transformArray: string[] = [];
|
||||
|
||||
props && transformArray.push(...stringifyTransformProps(props));
|
||||
|
||||
if (Array.isArray(transform)) {
|
||||
if (typeof transform[0] === 'number') {
|
||||
transformArray.push(`matrix(${transform.join(' ')})`);
|
||||
} else {
|
||||
const stringifiedProps = transformsArrayToProps(
|
||||
transform as TransformsStyle['transform'],
|
||||
);
|
||||
transformArray.push(...stringifyTransformProps(stringifiedProps));
|
||||
}
|
||||
} else if (typeof transform === 'string') {
|
||||
transformArray.push(transform);
|
||||
}
|
||||
|
||||
return transformArray.length ? transformArray.join(' ') : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* `react-native-svg` supports additional props that aren't defined in the spec.
|
||||
* This function replaces them in a spec conforming manner.
|
||||
@@ -95,15 +151,6 @@ const prepare = <T extends BaseProps>(
|
||||
) => {
|
||||
const {
|
||||
transform,
|
||||
translate,
|
||||
translateX,
|
||||
translateY,
|
||||
scale,
|
||||
scaleX,
|
||||
scaleY,
|
||||
rotation,
|
||||
skewX,
|
||||
skewY,
|
||||
origin,
|
||||
originX,
|
||||
originY,
|
||||
@@ -113,7 +160,8 @@ const prepare = <T extends BaseProps>(
|
||||
fontStyle,
|
||||
style,
|
||||
forwardedRef,
|
||||
// @ts-ignore
|
||||
gradientTransform,
|
||||
patternTransform,
|
||||
...rest
|
||||
} = props;
|
||||
|
||||
@@ -124,7 +172,10 @@ const prepare = <T extends BaseProps>(
|
||||
onResponderRelease?: (e: GestureResponderEvent) => void;
|
||||
onResponderTerminate?: (e: GestureResponderEvent) => void;
|
||||
onResponderTerminationRequest?: (e: GestureResponderEvent) => boolean;
|
||||
transform?: ColumnMajorTransformMatrix | string | TransformObject;
|
||||
transform?: string;
|
||||
gradientTransform?: string;
|
||||
patternTransform?: string;
|
||||
'transform-origin'?: string;
|
||||
style?: {};
|
||||
ref?: {};
|
||||
} = {
|
||||
@@ -143,83 +194,15 @@ const prepare = <T extends BaseProps>(
|
||||
...rest,
|
||||
};
|
||||
|
||||
const transformArray = [];
|
||||
|
||||
if (Array.isArray(transform) && transform.length === 6) {
|
||||
transformArray.push(`matrix(${transform.join(' ')})`);
|
||||
} else if (typeof transform === 'object') {
|
||||
for (const key in transform) {
|
||||
const value = transform[key];
|
||||
// non standard SVG transforms
|
||||
if (key === 'translateX' || key === 'x') {
|
||||
transformArray.push(`translate(${value} 0)`);
|
||||
} else if (key === 'translateY' || key === 'y') {
|
||||
transformArray.push(`translate(0 ${value})`);
|
||||
} else if (key === 'originX') {
|
||||
transformArray.push(`translate(${-value} 0)`);
|
||||
} else if (key === 'originY') {
|
||||
transformArray.push(`translate(0 ${-value})`);
|
||||
} else if (key === 'origin') {
|
||||
if (Array.isArray(value)) {
|
||||
transformArray.push(`translate(${value.join(' ')})`);
|
||||
} else {
|
||||
transformArray.push(`translate(${value})`);
|
||||
}
|
||||
} else if (key === 'scaleX') {
|
||||
transformArray.push(`scaleX(${value} 1)`);
|
||||
} else if (key === 'scaleY') {
|
||||
transformArray.push(`scaleX(1 ${value})`);
|
||||
} else if (key === 'skew') {
|
||||
if (Array.isArray(value) && value.length === 2) {
|
||||
transformArray.push(`skewX(${value[0]})`);
|
||||
transformArray.push(`skewY(${value[1]})`);
|
||||
} else {
|
||||
throw new Error('Skew prop expect array of numbers');
|
||||
}
|
||||
} else {
|
||||
if (Array.isArray(value)) {
|
||||
transformArray.push(`${key}(${value.join(' ')})`);
|
||||
} else {
|
||||
transformArray.push(`${key}(${transform[key]})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
transformArray.push(transform);
|
||||
}
|
||||
|
||||
if (translate != null) {
|
||||
transformArray.push(`translate(${translate})`);
|
||||
}
|
||||
if (translateX != null || translateY != null) {
|
||||
transformArray.push(`translate(${translateX || 0}, ${translateY || 0})`);
|
||||
}
|
||||
if (scale != null) {
|
||||
transformArray.push(`scale(${scale})`);
|
||||
}
|
||||
if (scaleX != null || scaleY != null) {
|
||||
transformArray.push(`scale(${scaleX || 1}, ${scaleY || 1})`);
|
||||
}
|
||||
// rotation maps to rotate, not to collide with the text rotate attribute (which acts per glyph rather than block)
|
||||
if (rotation != null) {
|
||||
transformArray.push(`rotate(${rotation})`);
|
||||
}
|
||||
if (skewX != null) {
|
||||
transformArray.push(`skewX(${skewX})`);
|
||||
}
|
||||
if (skewY != null) {
|
||||
transformArray.push(`skewY(${skewY})`);
|
||||
}
|
||||
if (origin != null) {
|
||||
transformArray.push(`translate(${origin})`);
|
||||
}
|
||||
if (originX != null || originY != null) {
|
||||
transformArray.push(`translate(${-originX || 0}, ${-originY || 0})`);
|
||||
clean['transform-origin'] = origin.toString().replace(',', ' ');
|
||||
} else if (originX != null || originY != null) {
|
||||
clean['transform-origin'] = `${originX || 0} ${originY || 0}`;
|
||||
}
|
||||
|
||||
if (transformArray.length) {
|
||||
clean.transform = transformArray.join(' ');
|
||||
}
|
||||
clean.transform = parseTransformProp(transform, props);
|
||||
clean.gradientTransform = parseTransformProp(gradientTransform);
|
||||
clean.patternTransform = parseTransformProp(patternTransform);
|
||||
|
||||
clean.ref = (el: SVGElement | null) => {
|
||||
self.elementRef.current = el;
|
||||
@@ -249,7 +232,6 @@ const prepare = <T extends BaseProps>(
|
||||
if (fontStyle != null) {
|
||||
styles.fontStyle = fontStyle;
|
||||
}
|
||||
|
||||
clean.style = resolve(style, styles);
|
||||
|
||||
return clean;
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
import extractGradient from '../lib/extract/extractGradient';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberProp,
|
||||
Units,
|
||||
} from '../lib/extract/types';
|
||||
import { NumberProp, TransformProps, Units } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGLinearGradient } from './NativeComponents';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
@@ -16,7 +12,7 @@ export interface LinearGradientProps {
|
||||
y1?: NumberProp;
|
||||
y2?: NumberProp;
|
||||
gradientUnits?: Units;
|
||||
gradientTransform?: ColumnMajorTransformMatrix | string;
|
||||
gradientTransform?: TransformProps['transform'];
|
||||
id?: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import extractTransform from '../lib/extract/extractTransform';
|
||||
import {
|
||||
stringifyPropsForFabric,
|
||||
withoutXY,
|
||||
} from '../lib/extract/extractProps';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
CommonPathProps,
|
||||
NumberProp,
|
||||
} from '../lib/extract/types';
|
||||
import { CommonPathProps, NumberProp } from '../lib/extract/types';
|
||||
import units from '../lib/units';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGMask } from './NativeComponents';
|
||||
@@ -22,7 +17,6 @@ export interface MaskProps extends CommonPathProps {
|
||||
y?: NumberProp;
|
||||
width?: NumberProp;
|
||||
height?: NumberProp;
|
||||
maskTransform?: ColumnMajorTransformMatrix | string;
|
||||
maskUnits?: TMaskUnits;
|
||||
maskContentUnits?: TMaskUnits;
|
||||
}
|
||||
@@ -39,17 +33,8 @@ export default class Mask extends Shape<MaskProps> {
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const {
|
||||
maskTransform,
|
||||
transform,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
maskUnits,
|
||||
maskContentUnits,
|
||||
children,
|
||||
} = props;
|
||||
const { x, y, width, height, maskUnits, maskContentUnits, children } =
|
||||
props;
|
||||
const strigifiedMaskProps = stringifyPropsForFabric({
|
||||
x,
|
||||
y,
|
||||
@@ -57,7 +42,6 @@ export default class Mask extends Shape<MaskProps> {
|
||||
height,
|
||||
});
|
||||
const maskProps = {
|
||||
maskTransform: extractTransform(maskTransform || transform || props),
|
||||
maskUnits: maskUnits !== undefined ? units[maskUnits] : 0,
|
||||
maskContentUnits:
|
||||
maskContentUnits !== undefined ? units[maskContentUnits] : 1,
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
import extractTransform from '../lib/extract/extractTransform';
|
||||
import extractViewBox from '../lib/extract/extractViewBox';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberProp,
|
||||
TransformProps,
|
||||
Units,
|
||||
} from '../lib/extract/types';
|
||||
import { NumberProp, TransformProps, Units } from '../lib/extract/types';
|
||||
import units from '../lib/units';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGPattern } from './NativeComponents';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
|
||||
export interface PatternProps {
|
||||
export interface PatternProps extends TransformProps {
|
||||
children?: ReactNode;
|
||||
id?: string;
|
||||
x?: NumberProp;
|
||||
y?: NumberProp;
|
||||
width?: NumberProp;
|
||||
height?: NumberProp;
|
||||
patternTransform?: ColumnMajorTransformMatrix | string;
|
||||
patternTransform?: TransformProps['transform'];
|
||||
patternUnits?: Units;
|
||||
patternContentUnits?: Units;
|
||||
viewBox?: string;
|
||||
preserveAspectRatio?: string;
|
||||
transform?: ColumnMajorTransformMatrix | string | TransformProps;
|
||||
}
|
||||
|
||||
export default class Pattern extends Shape<PatternProps> {
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
import extractGradient from '../lib/extract/extractGradient';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberProp,
|
||||
Units,
|
||||
} from '../lib/extract/types';
|
||||
import { NumberProp, TransformProps, Units } from '../lib/extract/types';
|
||||
import Shape from './Shape';
|
||||
import { RNSVGRadialGradient } from './NativeComponents';
|
||||
import { stringifyPropsForFabric } from '../lib/extract/extractProps';
|
||||
@@ -19,7 +15,7 @@ export interface RadialGradientProps {
|
||||
cy?: NumberProp;
|
||||
r?: NumberProp;
|
||||
gradientUnits?: Units;
|
||||
gradientTransform?: ColumnMajorTransformMatrix | string;
|
||||
gradientTransform?: TransformProps['transform'];
|
||||
id?: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Component } from 'react';
|
||||
import SvgTouchableMixin from '../lib/SvgTouchableMixin';
|
||||
import { NativeModules, findNodeHandle, NativeMethods } from 'react-native';
|
||||
import { TransformProps } from '../lib/extract/types';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
TransformProps,
|
||||
} from '../lib/extract/types';
|
||||
const { RNSVGRenderableManager } = NativeModules;
|
||||
|
||||
export interface SVGBoundingBoxOptions {
|
||||
@@ -241,7 +244,7 @@ export default class Shape<P> extends Component<P> {
|
||||
};
|
||||
setNativeProps = (
|
||||
props: Object & {
|
||||
matrix?: [number, number, number, number, number, number];
|
||||
matrix?: ColumnMajorTransformMatrix;
|
||||
} & TransformProps,
|
||||
) => {
|
||||
this.root && this.root.setNativeProps(props);
|
||||
|
||||
@@ -5,6 +5,7 @@ import extractText, { setTSpan, TextChild } from '../lib/extract/extractText';
|
||||
import { pickNotNil } from '../lib/util';
|
||||
import Shape from './Shape';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
CommonPathProps,
|
||||
FontProps,
|
||||
NumberArray,
|
||||
@@ -28,7 +29,7 @@ export default class TSpan extends Shape<TSpanProps> {
|
||||
|
||||
setNativeProps = (
|
||||
props: Object & {
|
||||
matrix?: number[];
|
||||
matrix?: ColumnMajorTransformMatrix;
|
||||
style?: [] | {};
|
||||
} & TransformProps,
|
||||
) => {
|
||||
|
||||
@@ -3,6 +3,7 @@ import extractText from '../lib/extract/extractText';
|
||||
import extractProps, { propsAndStyles } from '../lib/extract/extractProps';
|
||||
import extractTransform from '../lib/extract/extractTransform';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberArray,
|
||||
NumberProp,
|
||||
TextSpecificProps,
|
||||
@@ -29,7 +30,7 @@ export default class Text extends Shape<TextProps> {
|
||||
|
||||
setNativeProps = (
|
||||
props: Object & {
|
||||
matrix?: number[];
|
||||
matrix?: ColumnMajorTransformMatrix;
|
||||
style?: [] | {};
|
||||
} & TransformProps,
|
||||
) => {
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { Component } from 'react';
|
||||
import extractTransform from '../lib/extract/extractTransform';
|
||||
import { withoutXY } from '../lib/extract/extractProps';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberProp,
|
||||
TextPathMethod,
|
||||
TextPathMidLine,
|
||||
@@ -31,7 +32,7 @@ export default class TextPath extends Shape<TextPathProps> {
|
||||
|
||||
setNativeProps = (
|
||||
props: Object & {
|
||||
matrix?: number[];
|
||||
matrix?: ColumnMajorTransformMatrix;
|
||||
style?: [] | {};
|
||||
} & TransformProps,
|
||||
) => {
|
||||
|
||||
@@ -78,7 +78,6 @@ interface NativeProps
|
||||
width?: string;
|
||||
maskUnits?: Int32;
|
||||
maskContentUnits?: Int32;
|
||||
maskTransform?: ReadonlyArray<Float>;
|
||||
}
|
||||
|
||||
export default codegenNativeComponent<NativeProps>('RNSVGMask');
|
||||
|
||||
@@ -442,7 +442,6 @@ export type MaskProps = {
|
||||
y?: NumberProp,
|
||||
width?: NumberProp,
|
||||
height?: NumberProp,
|
||||
maskTransform?: ColumnMajorTransformMatrix | string,
|
||||
maskUnits?: Units,
|
||||
maskContentUnits?: Units,
|
||||
...
|
||||
|
||||
@@ -41,8 +41,8 @@ export default function extractGradient(
|
||||
props: {
|
||||
id?: string;
|
||||
children?: ReactElement[];
|
||||
transform?: number[] | string | TransformProps;
|
||||
gradientTransform?: number[] | string | TransformProps;
|
||||
transform?: TransformProps['transform'];
|
||||
gradientTransform?: TransformProps['transform'];
|
||||
gradientUnits?: 'objectBoundingBox' | 'userSpaceOnUse';
|
||||
} & TransformProps,
|
||||
parent: {},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import extractFill from './extractFill';
|
||||
import extractStroke from './extractStroke';
|
||||
import { props2transform, transformToMatrix } from './extractTransform';
|
||||
import extractTransform from './extractTransform';
|
||||
import extractResponder from './extractResponder';
|
||||
import extractOpacity from './extractOpacity';
|
||||
import { idPattern } from '../util';
|
||||
@@ -49,7 +49,6 @@ export default function extractProps(
|
||||
display?: string;
|
||||
opacity?: NumberProp;
|
||||
onLayout?: () => void;
|
||||
transform?: number[] | string | TransformProps;
|
||||
} & TransformProps &
|
||||
ResponderProps &
|
||||
StrokeProps &
|
||||
@@ -69,7 +68,6 @@ export default function extractProps(
|
||||
markerStart = marker,
|
||||
markerMid = marker,
|
||||
markerEnd = marker,
|
||||
transform,
|
||||
} = props;
|
||||
const extracted: extractedProps = {};
|
||||
|
||||
@@ -82,8 +80,7 @@ export default function extractProps(
|
||||
extracted.propList = inherited;
|
||||
}
|
||||
|
||||
const transformProps = props2transform(props);
|
||||
const matrix = transformToMatrix(transformProps, transform);
|
||||
const matrix = extractTransform(props);
|
||||
if (matrix !== null) {
|
||||
extracted.matrix = matrix;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import { TransformsStyle } from 'react-native';
|
||||
import { append, appendTransform, identity, reset, toArray } from '../Matrix2D';
|
||||
import { parse } from './transform';
|
||||
import { NumberProp, TransformedProps, TransformProps } from './types';
|
||||
import {
|
||||
ColumnMajorTransformMatrix,
|
||||
NumberProp,
|
||||
TransformedProps,
|
||||
TransformProps,
|
||||
} from './types';
|
||||
|
||||
function appendTransformProps(props: TransformedProps) {
|
||||
const { x, y, originX, originY, scaleX, scaleY, rotation, skewX, skewY } =
|
||||
@@ -58,9 +64,33 @@ function universal2axis(
|
||||
return [x || defaultValue || 0, y || defaultValue || 0];
|
||||
}
|
||||
|
||||
export function transformsArrayToProps(
|
||||
transformObjectsArray: TransformsStyle['transform'],
|
||||
) {
|
||||
const props: TransformProps = {};
|
||||
transformObjectsArray?.forEach((transformObject) => {
|
||||
const keys = Object.keys(transformObject);
|
||||
if (keys.length !== 1) {
|
||||
console.error(
|
||||
'You must specify exactly one property per transform object.',
|
||||
);
|
||||
}
|
||||
const key = keys[0] as keyof TransformProps;
|
||||
const value = transformObject[key as keyof typeof transformObject];
|
||||
props[key] = value;
|
||||
});
|
||||
return props;
|
||||
}
|
||||
|
||||
export function props2transform(
|
||||
props: TransformProps,
|
||||
props: TransformProps | undefined,
|
||||
): TransformedProps | null {
|
||||
if (!props) {
|
||||
return null;
|
||||
}
|
||||
const extractedProps = Array.isArray(props)
|
||||
? transformsArrayToProps(props)
|
||||
: props;
|
||||
const {
|
||||
rotation,
|
||||
translate,
|
||||
@@ -77,7 +107,7 @@ export function props2transform(
|
||||
skewY,
|
||||
x,
|
||||
y,
|
||||
} = props;
|
||||
} = extractedProps;
|
||||
if (
|
||||
rotation == null &&
|
||||
translate == null &&
|
||||
@@ -127,8 +157,8 @@ export function props2transform(
|
||||
|
||||
export function transformToMatrix(
|
||||
props: TransformedProps | null,
|
||||
transform: number[] | string | TransformProps | void | null | undefined,
|
||||
): [number, number, number, number, number, number] | null {
|
||||
transform: TransformProps['transform'],
|
||||
): ColumnMajorTransformMatrix | null {
|
||||
if (!props && !transform) {
|
||||
return null;
|
||||
}
|
||||
@@ -138,16 +168,21 @@ export function transformToMatrix(
|
||||
if (transform) {
|
||||
if (Array.isArray(transform)) {
|
||||
if (typeof transform[0] === 'number') {
|
||||
const columnMatrix = transform as ColumnMajorTransformMatrix;
|
||||
append(
|
||||
transform[0],
|
||||
transform[1],
|
||||
transform[2],
|
||||
transform[3],
|
||||
transform[4],
|
||||
transform[5],
|
||||
columnMatrix[0],
|
||||
columnMatrix[1],
|
||||
columnMatrix[2],
|
||||
columnMatrix[3],
|
||||
columnMatrix[4],
|
||||
columnMatrix[5],
|
||||
);
|
||||
} else {
|
||||
const transformProps = props2transform(
|
||||
transformsArrayToProps(transform as TransformsStyle['transform']),
|
||||
);
|
||||
transformProps && appendTransformProps(transformProps);
|
||||
}
|
||||
// noop for react-native transform arrays, let animated handle them
|
||||
} else if (typeof transform === 'string') {
|
||||
try {
|
||||
const t = parse(transform);
|
||||
@@ -165,10 +200,10 @@ export function transformToMatrix(
|
||||
}
|
||||
|
||||
export default function extractTransform(
|
||||
props: number[] | string | TransformProps,
|
||||
) {
|
||||
if (Array.isArray(props)) {
|
||||
return props;
|
||||
props: TransformProps | TransformProps['transform'],
|
||||
): ColumnMajorTransformMatrix | null {
|
||||
if (Array.isArray(props) && typeof props[0] === 'number') {
|
||||
return props as ColumnMajorTransformMatrix;
|
||||
}
|
||||
if (typeof props === 'string') {
|
||||
try {
|
||||
@@ -179,5 +214,11 @@ export default function extractTransform(
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
return transformToMatrix(props2transform(props), props.transform);
|
||||
// this type is not correct since props can be of type TransformsStyle['transform'] too
|
||||
// but it satisfies TS and should not produce any type errors
|
||||
const transformProps = props as TransformProps;
|
||||
return transformToMatrix(
|
||||
props2transform(transformProps),
|
||||
transformProps?.transform,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
LayoutChangeEvent,
|
||||
} from 'react-native';
|
||||
import React from 'react';
|
||||
import type { TransformsStyle } from 'react-native';
|
||||
|
||||
export type NumberProp = string | number;
|
||||
export type NumberArray = NumberProp[] | NumberProp;
|
||||
@@ -162,24 +163,6 @@ export interface FontProps extends FontObject {
|
||||
font?: FontObject;
|
||||
}
|
||||
|
||||
export interface TransformObject {
|
||||
translate?: NumberArray;
|
||||
translateX?: NumberProp;
|
||||
translateY?: NumberProp;
|
||||
origin?: NumberArray;
|
||||
originX?: NumberProp;
|
||||
originY?: NumberProp;
|
||||
scale?: NumberArray;
|
||||
scaleX?: NumberProp;
|
||||
scaleY?: NumberProp;
|
||||
skew?: NumberArray;
|
||||
skewX?: NumberProp;
|
||||
skewY?: NumberProp;
|
||||
rotation?: NumberProp;
|
||||
x?: NumberArray;
|
||||
y?: NumberArray;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
ColumnMajorTransformMatrix
|
||||
@@ -204,9 +187,26 @@ export type ColumnMajorTransformMatrix = [
|
||||
number,
|
||||
];
|
||||
|
||||
export interface TransformProps extends TransformObject {
|
||||
transform?: ColumnMajorTransformMatrix | string | TransformObject;
|
||||
// | TransformsStyle['transform']; // not used since it causes type problems
|
||||
export interface TransformProps {
|
||||
translate?: NumberArray;
|
||||
translateX?: NumberProp;
|
||||
translateY?: NumberProp;
|
||||
origin?: NumberArray;
|
||||
originX?: NumberProp;
|
||||
originY?: NumberProp;
|
||||
scale?: NumberArray;
|
||||
scaleX?: NumberProp;
|
||||
scaleY?: NumberProp;
|
||||
skew?: NumberArray;
|
||||
skewX?: NumberProp;
|
||||
skewY?: NumberProp;
|
||||
rotation?: NumberProp;
|
||||
x?: NumberArray;
|
||||
y?: NumberArray;
|
||||
transform?:
|
||||
| ColumnMajorTransformMatrix
|
||||
| string
|
||||
| TransformsStyle['transform'];
|
||||
}
|
||||
|
||||
export interface TransformedProps {
|
||||
|
||||
Reference in New Issue
Block a user