mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +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();
|
||||
}
|
||||
|
||||
@ReactProp(name = "width")
|
||||
@ReactProp(name = "rectwidth")
|
||||
public void setWidth(String width) {
|
||||
mW = width;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
|
||||
@ReactProp(name = "height")
|
||||
@ReactProp(name = "rectheight")
|
||||
public void setHeight(String height) {
|
||||
mH = height;
|
||||
markUpdated();
|
||||
|
||||
@@ -9,18 +9,19 @@
|
||||
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.view.View;
|
||||
import android.util.SparseArray;
|
||||
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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_PATH = "RNSVGPath";
|
||||
@@ -195,17 +196,43 @@ class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View createViewInstance(ThemedReactContext reactContext) {
|
||||
throw new IllegalStateException("SVG elements does not map into a native view");
|
||||
@ReactProp(name = "fillOpacity")
|
||||
public void setFillOpacity(RenderableView node, float opacity) {
|
||||
RenderableShadowNode shadow = ((RenderableShadowNode)mTagToShadowNode.get(node.getId()));
|
||||
shadow.setFillOpacity(opacity);
|
||||
SvgViewShadowNode view = shadow.getSvgShadowNode();
|
||||
if (view != null ) view.queueDraw();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateExtraData(View root, Object extraData) {
|
||||
throw new IllegalStateException("SVG elements does not map into a native view");
|
||||
protected RenderableView createViewInstance(ThemedReactContext reactContext) {
|
||||
return new RenderableView(reactContext);
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
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
|
||||
* texture events.
|
||||
@@ -111,9 +117,7 @@ public class SvgView extends ViewGroup {
|
||||
ReactShadowNodeImpl node = getShadowNode();
|
||||
for (int i = 0; i < this.getChildCount(); i++) {
|
||||
View child = this.getChildAt(i);
|
||||
if (child instanceof TextureView) {
|
||||
child.layout(l, t, r , b);
|
||||
} else if (child instanceof ReactViewGroup) {
|
||||
if (child instanceof ReactViewGroup) {
|
||||
int id = child.getId();
|
||||
for (int j = 0; j < node.getChildCount(); 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));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
child.layout(l, t, r , b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.graphics.RectF;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.graphics.Typeface;
|
||||
import android.util.Base64;
|
||||
import android.view.Choreographer;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
|
||||
@@ -43,7 +44,7 @@ import javax.annotation.Nullable;
|
||||
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
|
||||
*/
|
||||
public class SvgViewShadowNode extends LayoutShadowNode
|
||||
implements TextureView.SurfaceTextureListener {
|
||||
implements TextureView.SurfaceTextureListener, Choreographer.FrameCallback {
|
||||
|
||||
private @Nullable Surface mSurface;
|
||||
|
||||
@@ -337,4 +338,21 @@ public class SvgViewShadowNode extends LayoutShadowNode
|
||||
|
||||
@Override
|
||||
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;
|
||||
|
||||
@Override
|
||||
public void setReactTag(int reactTag) {
|
||||
super.setReactTag(reactTag);
|
||||
RenderableViewManager.setShadowNode(this);
|
||||
}
|
||||
|
||||
private static final float[] sRawMatrix = new float[]{
|
||||
1, 0, 0,
|
||||
0, 1, 0,
|
||||
@@ -72,18 +78,17 @@ abstract class VirtualNode extends LayoutShadowNode {
|
||||
Path mClipRegionPath;
|
||||
|
||||
VirtualNode() {
|
||||
setIsLayoutOnly(true);
|
||||
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtualAnchor() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -44,8 +44,8 @@ export default class extends Shape {
|
||||
}, this)}
|
||||
x={props.x.toString()}
|
||||
y={props.y.toString()}
|
||||
width={props.width.toString()}
|
||||
height={props.height.toString()}
|
||||
rectwidth={props.width.toString()}
|
||||
rectheight={props.height.toString()}
|
||||
rx={props.rx.toString()}
|
||||
ry={props.ry.toString()}
|
||||
/>;
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
@property (nonatomic, strong) NSString* x;
|
||||
@property (nonatomic, strong) NSString* y;
|
||||
@property (nonatomic, strong) NSString* width;
|
||||
@property (nonatomic, strong) NSString* height;
|
||||
@property (nonatomic, strong) NSString* rectwidth;
|
||||
@property (nonatomic, strong) NSString* rectheight;
|
||||
@property (nonatomic, strong) NSString* rx;
|
||||
@property (nonatomic, strong) NSString* ry;
|
||||
|
||||
|
||||
@@ -29,22 +29,22 @@
|
||||
_y = y;
|
||||
}
|
||||
|
||||
- (void)setWidth:(NSString *)width
|
||||
- (void)setWidth:(NSString *)rectwidth
|
||||
{
|
||||
if (width == _width) {
|
||||
if (rectwidth == _rectwidth) {
|
||||
return;
|
||||
}
|
||||
[self invalidate];
|
||||
_width = width;
|
||||
_rectwidth = rectwidth;
|
||||
}
|
||||
|
||||
- (void)setHeight:(NSString *)height
|
||||
- (void)setHeight:(NSString *)rectheight
|
||||
{
|
||||
if (height == _height) {
|
||||
if (rectheight == _rectheight) {
|
||||
return;
|
||||
}
|
||||
[self invalidate];
|
||||
_height = height;
|
||||
_rectheight = rectheight;
|
||||
}
|
||||
|
||||
- (void)setRx:(NSString *)rx
|
||||
@@ -70,8 +70,8 @@
|
||||
CGMutablePathRef path = CGPathCreateMutable();
|
||||
CGFloat x = [self relativeOnWidth:self.x];
|
||||
CGFloat y = [self relativeOnHeight:self.y];
|
||||
CGFloat width = [self relativeOnWidth:self.width];
|
||||
CGFloat height = [self relativeOnHeight:self.height];
|
||||
CGFloat width = [self relativeOnWidth:self.rectwidth];
|
||||
CGFloat height = [self relativeOnHeight:self.rectheight];
|
||||
CGFloat rx = [self relativeOnWidth:self.rx];
|
||||
CGFloat ry = [self relativeOnHeight:self.ry];
|
||||
|
||||
|
||||
@@ -24,11 +24,6 @@ RCT_EXPORT_MODULE()
|
||||
return [self node];
|
||||
}
|
||||
|
||||
- (RCTShadowView *)shadowView
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(name, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(opacity, CGFloat)
|
||||
RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
|
||||
|
||||
@@ -22,8 +22,8 @@ RCT_EXPORT_MODULE()
|
||||
|
||||
RCT_EXPORT_VIEW_PROPERTY(x, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(y, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(width, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(height, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(rectwidth, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(rectheight, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(rx, NSString)
|
||||
RCT_EXPORT_VIEW_PROPERTY(ry, NSString)
|
||||
|
||||
|
||||
@@ -220,8 +220,8 @@ const RectAttributes = {
|
||||
...RenderableAttributes,
|
||||
x: true,
|
||||
y: true,
|
||||
width: true,
|
||||
height: true,
|
||||
rectwidth: true,
|
||||
rectheight: true,
|
||||
rx: true,
|
||||
ry: true,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user