mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 22:05:14 +00:00
Experiment to allow animating fillOpacity of Rect using native driver.
import React, { Component } from 'react';
import { StyleSheet, View, Dimensions, Animated } from 'react-native';
import { Svg, Rect } from 'react-native-svg';
const { width, height } = Dimensions.get('window');
const AnimatedRect = Animated.createAnimatedComponent(Rect);
export default class App extends Component {
state = {
anim: new Animated.Value(0),
};
componentDidMount() {
Animated.timing(this.state.anim, {
toValue: 1,
duration: 3000,
useNativeDriver: true,
}).start();
}
render() {
const { anim } = this.state;
return (
<View style={styles.container}>
<Svg width={width} height={height} viewBox="0 0 100 100">
<AnimatedRect
x="5"
y="5"
width="90"
height="90"
fill="green"
fillOpacity={anim}
/>
</Svg>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#ecf0f1',
},
});
This commit is contained in:
@@ -40,14 +40,14 @@ class RectShadowNode extends RenderableShadowNode {
|
|||||||
markUpdated();
|
markUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReactProp(name = "width")
|
@ReactProp(name = "rectwidth")
|
||||||
public void setWidth(String width) {
|
public void setWidth(String width) {
|
||||||
mW = width;
|
mW = width;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ReactProp(name = "height")
|
@ReactProp(name = "rectheight")
|
||||||
public void setHeight(String height) {
|
public void setHeight(String height) {
|
||||||
mH = height;
|
mH = height;
|
||||||
markUpdated();
|
markUpdated();
|
||||||
|
|||||||
@@ -9,18 +9,19 @@
|
|||||||
|
|
||||||
package com.horcrux.svg;
|
package com.horcrux.svg;
|
||||||
|
|
||||||
import android.view.View;
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||||
import com.facebook.react.uimanager.ThemedReactContext;
|
import com.facebook.react.uimanager.ThemedReactContext;
|
||||||
import com.facebook.react.uimanager.ViewManager;
|
import com.facebook.react.uimanager.ViewGroupManager;
|
||||||
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ViewManager for all shadowed RNSVG views: Group, Path and Text. Since these never get rendered
|
* ViewManager for all shadowed RNSVG views: Group, Path and Text. Since these never get rendered
|
||||||
* into native views and don't need any logic (all the logic is in {@link SvgView}), this
|
* into native views and don't need any logic (all the logic is in {@link SvgView}), this
|
||||||
* "stubbed" ViewManager is used for all of them.
|
* "stubbed" ViewManager is used for all of them.
|
||||||
*/
|
*/
|
||||||
class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
class RenderableViewManager extends ViewGroupManager<RenderableView> {
|
||||||
|
|
||||||
/* package */ private static final String CLASS_GROUP = "RNSVGGroup";
|
/* package */ private static final String CLASS_GROUP = "RNSVGGroup";
|
||||||
/* package */ private static final String CLASS_PATH = "RNSVGPath";
|
/* package */ private static final String CLASS_PATH = "RNSVGPath";
|
||||||
@@ -195,17 +196,43 @@ class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@ReactProp(name = "fillOpacity")
|
||||||
protected View createViewInstance(ThemedReactContext reactContext) {
|
public void setFillOpacity(RenderableView node, float opacity) {
|
||||||
throw new IllegalStateException("SVG elements does not map into a native view");
|
RenderableShadowNode shadow = ((RenderableShadowNode)mTagToShadowNode.get(node.getId()));
|
||||||
|
shadow.setFillOpacity(opacity);
|
||||||
|
SvgViewShadowNode view = shadow.getSvgShadowNode();
|
||||||
|
if (view != null ) view.queueDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateExtraData(View root, Object extraData) {
|
protected RenderableView createViewInstance(ThemedReactContext reactContext) {
|
||||||
throw new IllegalStateException("SVG elements does not map into a native view");
|
return new RenderableView(reactContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDropViewInstance(View view) {
|
public void updateExtraData(RenderableView root, Object extraData) {
|
||||||
|
throw new IllegalStateException("SVG elements does not map into a native view");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final SparseArray<VirtualNode> mTagToShadowNode = new SparseArray<>();
|
||||||
|
private static final SparseArray<RenderableView> mTagToSvgView = new SparseArray<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDropViewInstance(RenderableView view) {
|
||||||
|
int tag = view.getId();
|
||||||
|
mTagToShadowNode.remove(tag);
|
||||||
|
mTagToSvgView.remove(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setView(RenderableView renderableView) {
|
||||||
|
mTagToSvgView.put(renderableView.getId(), renderableView);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setShadowNode(VirtualNode virtualNode) {
|
||||||
|
mTagToShadowNode.put(virtualNode.getReactTag(), virtualNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static VirtualNode getShadowNodeByTag(int id) {
|
||||||
|
return mTagToShadowNode.get(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,12 @@ public class SvgView extends ViewGroup {
|
|||||||
mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addView(View child, int index, LayoutParams params) {
|
||||||
|
if (!(child instanceof RenderableView)) {
|
||||||
|
super.addView(child, index, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link TextureView.SurfaceTextureListener} used to listen to surface
|
* Sets the {@link TextureView.SurfaceTextureListener} used to listen to surface
|
||||||
* texture events.
|
* texture events.
|
||||||
@@ -111,9 +117,7 @@ public class SvgView extends ViewGroup {
|
|||||||
ReactShadowNodeImpl node = getShadowNode();
|
ReactShadowNodeImpl node = getShadowNode();
|
||||||
for (int i = 0; i < this.getChildCount(); i++) {
|
for (int i = 0; i < this.getChildCount(); i++) {
|
||||||
View child = this.getChildAt(i);
|
View child = this.getChildAt(i);
|
||||||
if (child instanceof TextureView) {
|
if (child instanceof ReactViewGroup) {
|
||||||
child.layout(l, t, r , b);
|
|
||||||
} else if (child instanceof ReactViewGroup) {
|
|
||||||
int id = child.getId();
|
int id = child.getId();
|
||||||
for (int j = 0; j < node.getChildCount(); j++) {
|
for (int j = 0; j < node.getChildCount(); j++) {
|
||||||
ReactShadowNodeImpl nodeChild = node.getChildAt(j);
|
ReactShadowNodeImpl nodeChild = node.getChildAt(j);
|
||||||
@@ -129,6 +133,8 @@ public class SvgView extends ViewGroup {
|
|||||||
child.layout(Math.round(x), Math.round(y), Math.round(nr), Math.round(nb));
|
child.layout(Math.round(x), Math.round(y), Math.round(nr), Math.round(nb));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
child.layout(l, t, r , b);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import android.graphics.RectF;
|
|||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
|
import android.view.Choreographer;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.TextureView;
|
import android.view.TextureView;
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ import javax.annotation.Nullable;
|
|||||||
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
|
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
|
||||||
*/
|
*/
|
||||||
public class SvgViewShadowNode extends LayoutShadowNode
|
public class SvgViewShadowNode extends LayoutShadowNode
|
||||||
implements TextureView.SurfaceTextureListener {
|
implements TextureView.SurfaceTextureListener, Choreographer.FrameCallback {
|
||||||
|
|
||||||
private @Nullable Surface mSurface;
|
private @Nullable Surface mSurface;
|
||||||
|
|
||||||
@@ -337,4 +338,21 @@ public class SvgViewShadowNode extends LayoutShadowNode
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
|
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
|
||||||
|
|
||||||
|
private boolean queued = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFrame(long frameTimeNanos) {
|
||||||
|
if (queued) {
|
||||||
|
queued = false;
|
||||||
|
drawOutput();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void queueDraw() {
|
||||||
|
if (!queued) {
|
||||||
|
queued = true;
|
||||||
|
Choreographer.getInstance().postFrameCallback(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
|
|
||||||
static final float MIN_OPACITY_FOR_DRAW = 0.01f;
|
static final float MIN_OPACITY_FOR_DRAW = 0.01f;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setReactTag(int reactTag) {
|
||||||
|
super.setReactTag(reactTag);
|
||||||
|
RenderableViewManager.setShadowNode(this);
|
||||||
|
}
|
||||||
|
|
||||||
private static final float[] sRawMatrix = new float[]{
|
private static final float[] sRawMatrix = new float[]{
|
||||||
1, 0, 0,
|
1, 0, 0,
|
||||||
0, 1, 0,
|
0, 1, 0,
|
||||||
@@ -72,18 +78,17 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
Path mClipRegionPath;
|
Path mClipRegionPath;
|
||||||
|
|
||||||
VirtualNode() {
|
VirtualNode() {
|
||||||
setIsLayoutOnly(true);
|
|
||||||
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVirtual() {
|
public boolean isVirtual() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVirtualAnchor() {
|
public boolean isVirtualAnchor() {
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ export default class extends Shape {
|
|||||||
}, this)}
|
}, this)}
|
||||||
x={props.x.toString()}
|
x={props.x.toString()}
|
||||||
y={props.y.toString()}
|
y={props.y.toString()}
|
||||||
width={props.width.toString()}
|
rectwidth={props.width.toString()}
|
||||||
height={props.height.toString()}
|
rectheight={props.height.toString()}
|
||||||
rx={props.rx.toString()}
|
rx={props.rx.toString()}
|
||||||
ry={props.ry.toString()}
|
ry={props.ry.toString()}
|
||||||
/>;
|
/>;
|
||||||
|
|||||||
@@ -14,8 +14,8 @@
|
|||||||
|
|
||||||
@property (nonatomic, strong) NSString* x;
|
@property (nonatomic, strong) NSString* x;
|
||||||
@property (nonatomic, strong) NSString* y;
|
@property (nonatomic, strong) NSString* y;
|
||||||
@property (nonatomic, strong) NSString* width;
|
@property (nonatomic, strong) NSString* rectwidth;
|
||||||
@property (nonatomic, strong) NSString* height;
|
@property (nonatomic, strong) NSString* rectheight;
|
||||||
@property (nonatomic, strong) NSString* rx;
|
@property (nonatomic, strong) NSString* rx;
|
||||||
@property (nonatomic, strong) NSString* ry;
|
@property (nonatomic, strong) NSString* ry;
|
||||||
|
|
||||||
|
|||||||
@@ -29,22 +29,22 @@
|
|||||||
_y = y;
|
_y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setWidth:(NSString *)width
|
- (void)setWidth:(NSString *)rectwidth
|
||||||
{
|
{
|
||||||
if (width == _width) {
|
if (rectwidth == _rectwidth) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
_width = width;
|
_rectwidth = rectwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setHeight:(NSString *)height
|
- (void)setHeight:(NSString *)rectheight
|
||||||
{
|
{
|
||||||
if (height == _height) {
|
if (rectheight == _rectheight) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[self invalidate];
|
[self invalidate];
|
||||||
_height = height;
|
_rectheight = rectheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setRx:(NSString *)rx
|
- (void)setRx:(NSString *)rx
|
||||||
@@ -70,8 +70,8 @@
|
|||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
CGFloat x = [self relativeOnWidth:self.x];
|
CGFloat x = [self relativeOnWidth:self.x];
|
||||||
CGFloat y = [self relativeOnHeight:self.y];
|
CGFloat y = [self relativeOnHeight:self.y];
|
||||||
CGFloat width = [self relativeOnWidth:self.width];
|
CGFloat width = [self relativeOnWidth:self.rectwidth];
|
||||||
CGFloat height = [self relativeOnHeight:self.height];
|
CGFloat height = [self relativeOnHeight:self.rectheight];
|
||||||
CGFloat rx = [self relativeOnWidth:self.rx];
|
CGFloat rx = [self relativeOnWidth:self.rx];
|
||||||
CGFloat ry = [self relativeOnHeight:self.ry];
|
CGFloat ry = [self relativeOnHeight:self.ry];
|
||||||
|
|
||||||
|
|||||||
@@ -24,11 +24,6 @@ RCT_EXPORT_MODULE()
|
|||||||
return [self node];
|
return [self node];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RCTShadowView *)shadowView
|
|
||||||
{
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(name, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(name, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
|
RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
|
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ RCT_EXPORT_MODULE()
|
|||||||
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(x, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(x, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(y, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(y, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(width, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(rectwidth, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(height, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(rectheight, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(rx, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(rx, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(ry, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(ry, NSString)
|
||||||
|
|
||||||
|
|||||||
@@ -220,8 +220,8 @@ const RectAttributes = {
|
|||||||
...RenderableAttributes,
|
...RenderableAttributes,
|
||||||
x: true,
|
x: true,
|
||||||
y: true,
|
y: true,
|
||||||
width: true,
|
rectwidth: true,
|
||||||
height: true,
|
rectheight: true,
|
||||||
rx: true,
|
rx: true,
|
||||||
ry: true,
|
ry: true,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user