diff --git a/android/src/main/java/com/horcrux/svg/SvgView.java b/android/src/main/java/com/horcrux/svg/SvgView.java index 81fbdf1b..f58e4b32 100644 --- a/android/src/main/java/com/horcrux/svg/SvgView.java +++ b/android/src/main/java/com/horcrux/svg/SvgView.java @@ -64,6 +64,11 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC public SvgView(ReactContext reactContext) { super(reactContext); mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density; + mScaleX = 1; + mScaleY = 1; + mPaint.setFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.SUBPIXEL_TEXT_FLAG); + mPaint.setTypeface(Typeface.DEFAULT); + // for some reason on Fabric the `onDraw` won't be called without it setWillNotDraw(false); } @@ -131,7 +136,15 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC mBitmap = drawOutput(); } if (mBitmap != null) { - canvas.drawBitmap(mBitmap, 0, 0, null); + if (mScaleX != 1 || mScaleY != 1) { + canvas.drawBitmap( + mBitmap, + -(float) (mBitmap.getWidth() - getWidth()) / 2, + -(float) (mBitmap.getHeight() - getHeight()) / 2, + mPaint); + } else { + canvas.drawBitmap(mBitmap, 0, 0, mPaint); + } if (toDataUrlTask != null) { toDataUrlTask.run(); toDataUrlTask = null; @@ -166,6 +179,9 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC private final Map mDefinedBrushes = new HashMap<>(); private Canvas mCanvas; private final float mScale; + private float mScaleX; + private float mScaleY; + private final Paint mPaint = new Paint(); private float mMinX; private float mMinY; @@ -265,7 +281,9 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC if (invalid) { return null; } - Bitmap bitmap = Bitmap.createBitmap((int) width, (int) height, Bitmap.Config.ARGB_8888); + Bitmap bitmap = + Bitmap.createBitmap( + (int) (width * mScaleX), (int) (height * mScaleY), Bitmap.Config.ARGB_8888); mCurrentBitmap = bitmap; drawChildren(new Canvas(bitmap)); return bitmap; @@ -297,12 +315,6 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC canvas.concat(mViewBoxMatrix); } - final Paint paint = new Paint(); - - paint.setFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.SUBPIXEL_TEXT_FLAG); - - paint.setTypeface(Typeface.DEFAULT); - for (int i = 0; i < getChildCount(); i++) { View node = getChildAt(i); if (node instanceof VirtualView) { @@ -315,7 +327,7 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC if (lNode instanceof VirtualView) { VirtualView node = (VirtualView) lNode; int count = node.saveAndSetupCanvas(canvas, mViewBoxMatrix); - node.render(canvas, paint, 1f); + node.render(canvas, mPaint, 1f); node.restoreCanvas(canvas, count); if (node.isResponsible() && !mResponsible) { @@ -374,7 +386,11 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC } float[] transformed = {touchX, touchY}; - mInvViewBoxMatrix.mapPoints(transformed); + int width = getWidth(); + int height = getHeight(); + Matrix invViewBoxMatrix = new Matrix(mInvViewBoxMatrix); + invViewBoxMatrix.preTranslate((width * mScaleX - width) / 2, (height * mScaleY - height) / 2); + invViewBoxMatrix.mapPoints(transformed); int count = getChildCount(); int viewTag = -1; @@ -444,4 +460,12 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC public Bitmap getCurrentBitmap() { return mCurrentBitmap; } + + public void setTransformProperty() { + mScaleX = super.getScaleX(); + mScaleY = super.getScaleY(); + super.setScaleX(1); + super.setScaleY(1); + invalidate(); + } } diff --git a/android/src/main/java/com/horcrux/svg/SvgViewManager.java b/android/src/main/java/com/horcrux/svg/SvgViewManager.java index 2f21dec9..5ae96ddb 100644 --- a/android/src/main/java/com/horcrux/svg/SvgViewManager.java +++ b/android/src/main/java/com/horcrux/svg/SvgViewManager.java @@ -10,8 +10,10 @@ package com.horcrux.svg; import android.graphics.Rect; import android.util.SparseArray; +import androidx.annotation.NonNull; import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Dynamic; +import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.common.ReactConstants; import com.facebook.react.uimanager.PixelUtil; @@ -390,4 +392,13 @@ class SvgViewManager extends ReactViewManager public void setBorderStartStartRadius(SvgView view, double value) { super.setBorderRadius(view, 12, (float) value); } + + @Override + public void setTransformProperty( + @NonNull ReactViewGroup view, + @androidx.annotation.Nullable ReadableArray transforms, + @androidx.annotation.Nullable ReadableArray transformOrigin) { + super.setTransformProperty(view, transforms, transformOrigin); + ((SvgView) view).setTransformProperty(); + } } diff --git a/apps/test-examples/index.tsx b/apps/test-examples/index.tsx index 09b86822..75fb937a 100644 --- a/apps/test-examples/index.tsx +++ b/apps/test-examples/index.tsx @@ -26,6 +26,7 @@ import Test2327 from './src/Test2327'; import Test2233 from './src/Test2233'; import Test2366 from './src/Test2366'; import Test2397 from './src/Test2397'; +import Test2403 from './src/Test2403'; import Test2407 from './src/Test2407'; export default function App() { diff --git a/apps/test-examples/src/Test2403.tsx b/apps/test-examples/src/Test2403.tsx new file mode 100644 index 00000000..347b0558 --- /dev/null +++ b/apps/test-examples/src/Test2403.tsx @@ -0,0 +1,95 @@ +import {useCallback} from 'react'; +import { + Animated, + Button, + Easing, + Text, + View, + useAnimatedValue, +} from 'react-native'; +import {Circle, Mask, Path, Rect, Svg} from 'react-native-svg'; + +export const EASING_IN: (t: number) => number = Easing.bezier(0.7, 0, 0.3, 1); +export const EASING_OUT: (t: number) => number = Easing.bezier(0.5, 0, 0.5, 1); + +const AnimatedSvg = Animated.createAnimatedComponent(Svg); + +export default function Playground() { + const animatedValue = useAnimatedValue(0); + + const handleMouseEnter = useCallback(() => { + Animated.timing(animatedValue, { + duration: 350, + easing: EASING_IN, + toValue: 1, + useNativeDriver: false, + }).start(); + }, [animatedValue]); + + const handleMouseLeave = useCallback(() => { + Animated.timing(animatedValue, { + duration: 350, + easing: EASING_OUT, + toValue: 0, + useNativeDriver: false, + }).start(); + }, [animatedValue]); + + return ( + + Text1 + + + + + + + console.log('sadas')} + /> + + + + Text2 +