diff --git a/Example/examples/Svg.js b/Example/examples/Svg.js index e746d04d..2447657c 100644 --- a/Example/examples/Svg.js +++ b/Example/examples/Svg.js @@ -174,10 +174,12 @@ class SvgNativeMethods extends Component { - + + {this.state.base64 && } + ; } } diff --git a/README.md b/README.md index 3fd74445..969559ed 100644 --- a/README.md +++ b/README.md @@ -579,6 +579,7 @@ npm install 2. more Text features support (textPath, tref, tspan) 3. Pattern element 4. implement Animated elements +5. more Image features support #### Thanks: diff --git a/android/src/main/java/com/horcrux/svg/PropHelper.java b/android/src/main/java/com/horcrux/svg/PropHelper.java index 86f62a11..69965d1b 100644 --- a/android/src/main/java/com/horcrux/svg/PropHelper.java +++ b/android/src/main/java/com/horcrux/svg/PropHelper.java @@ -16,7 +16,6 @@ import android.graphics.RadialGradient; import android.graphics.LinearGradient; import android.graphics.Shader; import android.graphics.Matrix; -import android.util.Log; import javax.annotation.Nullable; diff --git a/android/src/main/java/com/horcrux/svg/RNSVGCircleShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGCircleShadowNode.java index d4a8139c..81f0423a 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGCircleShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGCircleShadowNode.java @@ -12,7 +12,6 @@ package com.horcrux.svg; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; -import android.util.Log; import com.facebook.react.uimanager.annotations.ReactProp; diff --git a/android/src/main/java/com/horcrux/svg/RNSVGEllipseShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGEllipseShadowNode.java index f59c8742..e4734fe5 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGEllipseShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGEllipseShadowNode.java @@ -13,7 +13,6 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; -import android.util.Log; import com.facebook.react.uimanager.annotations.ReactProp; diff --git a/android/src/main/java/com/horcrux/svg/RNSVGGroupShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGGroupShadowNode.java index a34c3ebb..9f0b67a2 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGGroupShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGGroupShadowNode.java @@ -14,14 +14,12 @@ import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; -import android.util.Log; import android.view.View; import android.view.ViewGroup; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.uimanager.ReactShadowNode; -import java.security.PublicKey; import javax.annotation.Nullable; diff --git a/android/src/main/java/com/horcrux/svg/RNSVGLineShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGLineShadowNode.java index f46e97d7..f9d040cf 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGLineShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGLineShadowNode.java @@ -14,8 +14,6 @@ import android.graphics.Paint; import android.graphics.Path; import com.facebook.react.uimanager.annotations.ReactProp; -import javax.annotation.Nullable; - /** * Shadow node for virtual RNSVGPath view */ diff --git a/android/src/main/java/com/horcrux/svg/RNSVGLinearGradientShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGLinearGradientShadowNode.java index 380ec738..314e435a 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGLinearGradientShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGLinearGradientShadowNode.java @@ -14,8 +14,6 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.WritableArray; import com.facebook.react.uimanager.annotations.ReactProp; -import java.util.ArrayList; - /** * Shadow node for virtual LinearGradient definition view */ diff --git a/android/src/main/java/com/horcrux/svg/RNSVGPathShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGPathShadowNode.java index daeb0df7..5e7d2b6d 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGPathShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGPathShadowNode.java @@ -21,7 +21,6 @@ import android.graphics.Point; import android.graphics.RectF; import android.graphics.Color; -import android.util.Log; import android.view.View; import com.facebook.common.logging.FLog; diff --git a/android/src/main/java/com/horcrux/svg/RNSVGRectShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGRectShadowNode.java index d709280d..b3eee6f5 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGRectShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGRectShadowNode.java @@ -15,8 +15,6 @@ import android.graphics.Path; import android.graphics.RectF; import com.facebook.react.uimanager.annotations.ReactProp; -import javax.annotation.Nullable; - /** * Shadow node for virtual RNSVGPath view */ diff --git a/android/src/main/java/com/horcrux/svg/RNSVGRenderableView.java b/android/src/main/java/com/horcrux/svg/RNSVGRenderableView.java index eaf9a1ac..b91a7cb6 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGRenderableView.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGRenderableView.java @@ -13,8 +13,6 @@ import android.content.Context; import android.view.View; import android.view.ViewGroup; -// NativeGestureUtil.notifyNativeGestureStarted - /** * Custom {@link View} implementation that draws an RNSVGSvg React view and its \children. */ diff --git a/android/src/main/java/com/horcrux/svg/RNSVGSvgView.java b/android/src/main/java/com/horcrux/svg/RNSVGSvgView.java index f07bb496..de9c16fb 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGSvgView.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGSvgView.java @@ -21,24 +21,41 @@ import android.view.View; import android.view.ViewGroup; import com.facebook.infer.annotation.Assertions; +import com.facebook.react.bridge.Arguments; +import com.facebook.react.bridge.ReactContext; +import com.facebook.react.bridge.WritableMap; import com.facebook.react.common.SystemClock; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.UIManagerModule; +import com.facebook.react.uimanager.events.RCTEventEmitter; import com.facebook.react.uimanager.events.TouchEvent; import com.facebook.react.uimanager.events.TouchEventCoalescingKeyHelper; import com.facebook.react.uimanager.events.TouchEventType; import com.facebook.react.uimanager.events.EventDispatcher; -// NativeGestureUtil.notifyNativeGestureStarted /** * Custom {@link View} implementation that draws an RNSVGSvg React view and its \children. */ public class RNSVGSvgView extends ViewGroup { + public enum Events { + EVENT_DATA_URL("onDataURL"); + + private final String mName; + + Events(final String name) { + mName = name; + } + + @Override + public String toString() { + return mName; + } + } + private @Nullable Bitmap mBitmap; - + private RCTEventEmitter mEventEmitter; private RNSVGSvgViewShadowNode mSvgViewShadowNode; - private int mTargetTag; private final TouchEventCoalescingKeyHelper mTouchEventCoalescingKeyHelper = @@ -48,6 +65,11 @@ public class RNSVGSvgView extends ViewGroup { super(context); } + public RNSVGSvgView(ReactContext reactContext) { + super(reactContext); + mEventEmitter = reactContext.getJSModule(RCTEventEmitter.class); + } + public void setBitmap(Bitmap bitmap) { if (mBitmap != null) { mBitmap.recycle(); @@ -183,4 +205,10 @@ public class RNSVGSvgView extends ViewGroup { androidEvent.getY(), mTouchEventCoalescingKeyHelper)); } + + public void onDataURL() { + WritableMap event = Arguments.createMap(); + event.putString("base64", mSvgViewShadowNode.getBase64()); + mEventEmitter.receiveEvent(getId(), Events.EVENT_DATA_URL.toString(), event); + } } diff --git a/android/src/main/java/com/horcrux/svg/RNSVGSvgViewManager.java b/android/src/main/java/com/horcrux/svg/RNSVGSvgViewManager.java index 82883f22..8c6673c9 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGSvgViewManager.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGSvgViewManager.java @@ -10,29 +10,16 @@ package com.horcrux.svg; import android.graphics.Bitmap; -import android.telecom.Call; -import android.util.Log; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.uimanager.BaseViewManager; -import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ReactStylesDiffMap; -import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.common.MapBuilder; import com.facebook.react.uimanager.ThemedReactContext; import com.facebook.react.uimanager.ViewGroupManager; -import com.facebook.react.uimanager.ViewManagerPropertyUpdater; -import com.facebook.react.uimanager.events.RCTEventEmitter; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; -import javax.security.auth.callback.Callback; /** * ViewManager for RNSVGSvgView React views. Renders as a {@link RNSVGSvgView} and handles @@ -63,27 +50,27 @@ public class RNSVGSvgViewManager extends ViewGroupManager { return commandsMap; } + @Override + @Nullable + public Map getExportedCustomDirectEventTypeConstants() { + MapBuilder.Builder builder = MapBuilder.builder(); + for (RNSVGSvgView.Events event : RNSVGSvgView.Events.values()) { + builder.put(event.toString(), MapBuilder.of("registrationName", event.toString())); + } + return builder.build(); + } + @Override public void receiveCommand(RNSVGSvgView root, int commandId, @Nullable ReadableArray args) { super.receiveCommand(root, commandId, args); switch (commandId) { case COMMAND_TO_DATA_URL: - toDataURL(root); + root.onDataURL(); break; } } - private void toDataURL(RNSVGSvgView root) { - WritableMap event = Arguments.createMap(); - event.putString("message", "MyMessage"); - ReactContext reactContext = (ReactContext)root.getContext(); - reactContext.getJSModule(RCTEventEmitter.class).receiveEvent( - root.getId(), - "onDataURL", - event); - } - @Override public RNSVGSvgViewShadowNode createShadowNodeInstance() { diff --git a/android/src/main/java/com/horcrux/svg/RNSVGSvgViewShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGSvgViewShadowNode.java index 3ed3bc9d..3f539104 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGSvgViewShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGSvgViewShadowNode.java @@ -13,21 +13,17 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; -import android.graphics.Rect; -import android.util.Log; -import android.view.View; +import android.util.Base64; import android.view.ViewGroup; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.react.uimanager.LayoutShadowNode; -import com.facebook.react.uimanager.ReactShadowNode; import com.facebook.react.uimanager.UIViewOperationQueue; +import java.io.ByteArrayOutputStream; import java.util.HashMap; import java.util.Map; -import javax.annotation.Nonnull; - /** * Shadow node for RNSVG virtual tree root - RNSVGSvgView */ @@ -57,6 +53,15 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode { return bitmap; } + public String getBase64() { + Bitmap bitmap = (Bitmap)drawOutput(); + ByteArrayOutputStream stream = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); + bitmap.recycle(); + byte[] bitmapBytes = stream.toByteArray(); + return Base64.encodeToString(bitmapBytes, Base64.DEFAULT); + } + /** * Draw all of the child nodes of this root node * diff --git a/android/src/main/java/com/horcrux/svg/RNSVGTextShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGTextShadowNode.java index a455b179..45e98774 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGTextShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGTextShadowNode.java @@ -21,7 +21,6 @@ import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Typeface; import android.text.TextUtils; -import android.util.Log; import android.view.View; import com.facebook.react.bridge.ReadableArray; diff --git a/android/src/main/java/com/horcrux/svg/RNSVGUseShadowNode.java b/android/src/main/java/com/horcrux/svg/RNSVGUseShadowNode.java index aae7f0ad..5e15c2e1 100644 --- a/android/src/main/java/com/horcrux/svg/RNSVGUseShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/RNSVGUseShadowNode.java @@ -11,7 +11,6 @@ package com.horcrux.svg; import android.graphics.Canvas; import android.graphics.Paint; -import android.util.Log; import com.facebook.common.logging.FLog; import com.facebook.react.common.ReactConstants; diff --git a/elements/Svg.js b/elements/Svg.js index 3563fef9..8fec1cd5 100644 --- a/elements/Svg.js +++ b/elements/Svg.js @@ -8,10 +8,12 @@ import { StyleSheet, UIManager, findNodeHandle, - NativeModules + NativeModules, + Platform } from 'react-native'; import ViewBox from './ViewBox'; import _ from 'lodash'; +import createReactNativeComponentClass from 'react/lib/createReactNativeComponentClass'; const RNSVGSvgViewManager = NativeModules.RNSVGSvgViewManager; // Svg - Root node of all Svg elements @@ -39,6 +41,7 @@ class Svg extends Component{ super(...arguments); id++; this.id = id; + this.onDataURLCallbacks = []; } measureInWindow = (...args) => { this.root.measureInWindow(...args); @@ -56,8 +59,24 @@ class Svg extends Component{ this.root.setNativeProps(...args); }; - toDataURL = (callback = _.noop) => { + + toDataURL = Platform.OS === 'ios' ? (callback = _.noop) => { RNSVGSvgViewManager.toDataURL(findNodeHandle(this.root), callback); + } : (callback = _.noop) => { + let node = findNodeHandle(this.root); + this.onDataURLCallbacks.push(callback); + UIManager.dispatchViewManagerCommand( + node, + UIManager.RNSVGSvgView.Commands.toDataURL, + null + ); + }; + + _onDataURL = (e) => { + let callback; + while (callback = this.onDataURLCallbacks.shift()) { + callback(e.nativeEvent.base64); + } }; render() { @@ -99,6 +118,7 @@ class Svg extends Component{ }, dimensions ]} + onDataURL={this._onDataURL} > {content} ; @@ -107,4 +127,5 @@ class Svg extends Component{ const NativeSvgView = requireNativeComponent('RNSVGSvgView', null); + export default Svg;