mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-08-16 02:44:58 +00:00
fix: scale path markers so they match ios (#2018)
PR adding scaling of markers of path in order to make them behave the same as on iOS. Also bumped the versions of agp and spotless.
This commit is contained in:
@@ -8,9 +8,10 @@ import {
|
||||
Ellipse,
|
||||
Line,
|
||||
Polygon,
|
||||
Path,
|
||||
} from 'react-native-svg';
|
||||
|
||||
class CircleExample extends Component {
|
||||
class EllipseExample extends Component {
|
||||
static title = 'Circle shaped marker on ellipse';
|
||||
render() {
|
||||
return (
|
||||
@@ -47,7 +48,7 @@ class CircleExample extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
class StrokeCircle extends Component {
|
||||
class LineExample extends Component {
|
||||
static title = 'Triangle shaped marker on line';
|
||||
render() {
|
||||
return (
|
||||
@@ -81,7 +82,7 @@ class StrokeCircle extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
class StrokeOpacityCircle extends Component {
|
||||
class CircleExample extends Component {
|
||||
static title = 'Rect shaped marker on circle';
|
||||
render() {
|
||||
return (
|
||||
@@ -111,7 +112,7 @@ class StrokeOpacityCircle extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
class PieCircle extends Component {
|
||||
class RectExample extends Component {
|
||||
static title = 'Ellipse shaped marker on rect';
|
||||
render() {
|
||||
return (
|
||||
@@ -119,7 +120,7 @@ class PieCircle extends Component {
|
||||
<Defs>
|
||||
<Marker
|
||||
id="selection"
|
||||
markerUnits="userSpaceOnUse"
|
||||
markerUnits="strokeWidth"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
@@ -141,7 +142,7 @@ class PieCircle extends Component {
|
||||
height="30"
|
||||
fill="none"
|
||||
stroke="blue"
|
||||
strokeWidth="5"
|
||||
strokeWidth="1"
|
||||
marker="url(#selection)"
|
||||
/>
|
||||
</Svg>
|
||||
@@ -149,11 +150,69 @@ class PieCircle extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
class PathExample extends Component {
|
||||
static title = 'Path shaped marker on line';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="200" width="400" viewBox="0 0 300 100">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="arrow"
|
||||
// viewBox="0 0 10 10"
|
||||
refX="5"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
// orient="auto-start-reverse"
|
||||
>
|
||||
<Path fill="blue" d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Line
|
||||
x1="10"
|
||||
y1="10"
|
||||
x2="90"
|
||||
y2="90"
|
||||
stroke="black"
|
||||
strokeWidth="3"
|
||||
markerEnd="url(#arrow)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const icon = (
|
||||
<Svg height="30" width="30" viewBox="0 0 20 20">
|
||||
<Circle cx="10" cy="10" r="8" stroke="purple" strokeWidth="1" fill="pink" />
|
||||
<Svg height="30" width="30" viewBox="0 0 3000 2500">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="Triangle"
|
||||
// viewBox="0 0 10 10"
|
||||
refX="0"
|
||||
refY="5"
|
||||
markerUnits="strokeWidth"
|
||||
markerWidth="4"
|
||||
markerHeight="3"
|
||||
orient="auto">
|
||||
<Path fill="blue" d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Path
|
||||
d="M 1000 750 L 2000 750 L 2500 1250"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
strokeWidth="70"
|
||||
markerEnd="url(#Triangle)"
|
||||
markerStart="url(#Triangle)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
|
||||
const samples = [CircleExample, StrokeCircle, StrokeOpacityCircle, PieCircle];
|
||||
const samples = [
|
||||
EllipseExample,
|
||||
LineExample,
|
||||
CircleExample,
|
||||
RectExample,
|
||||
PathExample,
|
||||
];
|
||||
export {icon, samples};
|
||||
|
||||
@@ -113,6 +113,7 @@ const names: (keyof typeof examples)[] = [
|
||||
'PanResponder',
|
||||
'Reusable',
|
||||
'Transforms',
|
||||
'Markers',
|
||||
];
|
||||
|
||||
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 Transforms from './examples/Transforms';
|
||||
import * as Markers from './examples/Markers';
|
||||
|
||||
export {
|
||||
Svg,
|
||||
@@ -36,4 +37,5 @@ export {
|
||||
Reusable,
|
||||
PanResponder,
|
||||
Transforms,
|
||||
Markers,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
import React, {Component} from 'react';
|
||||
import {
|
||||
Svg,
|
||||
Circle,
|
||||
Defs,
|
||||
Marker,
|
||||
Rect,
|
||||
Ellipse,
|
||||
Line,
|
||||
Polygon,
|
||||
Path,
|
||||
} from 'react-native-svg';
|
||||
|
||||
class EllipseExample extends Component {
|
||||
static title = 'Circle shaped marker on ellipse';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="300" width="400">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="selection"
|
||||
markerUnits="userSpaceOnUse"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<Circle
|
||||
fill="#3a6cff"
|
||||
r={5}
|
||||
cx={0}
|
||||
cy={0}
|
||||
strokeWidth={1}
|
||||
stroke="white"
|
||||
/>
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Ellipse
|
||||
cx="200"
|
||||
cy="170"
|
||||
rx="30%"
|
||||
ry="10%"
|
||||
stroke="purple"
|
||||
strokeWidth="2"
|
||||
fill="yellow"
|
||||
marker="url(#selection)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LineExample extends Component {
|
||||
static title = 'Triangle shaped marker on line';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="200" width="200">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="selection"
|
||||
markerUnits="userSpaceOnUse"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<Polygon
|
||||
points="0,0 -5,20 10,30"
|
||||
fill="lime"
|
||||
stroke="purple"
|
||||
strokeWidth="1"
|
||||
/>
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Line
|
||||
x1="20"
|
||||
y1="10%"
|
||||
x2="60%"
|
||||
y2="60%"
|
||||
stroke="red"
|
||||
strokeWidth="2"
|
||||
marker="url(#selection)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CircleExample extends Component {
|
||||
static title = 'Rect shaped marker on circle';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="150" width="200">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="selection"
|
||||
markerUnits="userSpaceOnUse"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<Rect x="0" y="0" width="15" height="15" fill="rgb(0,0,255)" />
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Circle
|
||||
cx="70"
|
||||
cy="70"
|
||||
r="30%"
|
||||
stroke="purple"
|
||||
strokeOpacity="0.5"
|
||||
strokeWidth="10"
|
||||
fill="pink"
|
||||
marker="url(#selection)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RectExample extends Component {
|
||||
static title = 'Ellipse shaped marker on rect';
|
||||
render() {
|
||||
return (
|
||||
<Svg width="400" height="200" viewBox="0 0 100 100">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="selection"
|
||||
markerUnits="strokeWidth"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto">
|
||||
<Ellipse
|
||||
fill="#3a6cff"
|
||||
rx={5}
|
||||
ry={8}
|
||||
cx={0}
|
||||
cy={0}
|
||||
strokeWidth={1}
|
||||
stroke="white"
|
||||
/>
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Rect
|
||||
x="50%"
|
||||
y="50"
|
||||
width="30"
|
||||
height="30"
|
||||
fill="none"
|
||||
stroke="blue"
|
||||
strokeWidth="1"
|
||||
marker="url(#selection)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PathExample extends Component {
|
||||
static title = 'Path shaped marker on line';
|
||||
render() {
|
||||
return (
|
||||
<Svg height="200" width="400" viewBox="0 0 300 100">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="arrow"
|
||||
// viewBox="0 0 10 10"
|
||||
refX="5"
|
||||
refY="5"
|
||||
markerWidth="6"
|
||||
markerHeight="6"
|
||||
// orient="auto-start-reverse"
|
||||
>
|
||||
<Path fill="blue" d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Line
|
||||
x1="10"
|
||||
y1="10"
|
||||
x2="90"
|
||||
y2="90"
|
||||
stroke="black"
|
||||
strokeWidth="3"
|
||||
markerEnd="url(#arrow)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const icon = (
|
||||
<Svg height="30" width="30" viewBox="0 0 3000 2500">
|
||||
<Defs>
|
||||
<Marker
|
||||
id="Triangle"
|
||||
// viewBox="0 0 10 10"
|
||||
refX="0"
|
||||
refY="5"
|
||||
markerUnits="strokeWidth"
|
||||
markerWidth="4"
|
||||
markerHeight="3"
|
||||
orient="auto">
|
||||
<Path fill="blue" d="M 0 0 L 10 5 L 0 10 z" />
|
||||
</Marker>
|
||||
</Defs>
|
||||
<Path
|
||||
d="M 1000 750 L 2000 750 L 2500 1250"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
strokeWidth="70"
|
||||
markerEnd="url(#Triangle)"
|
||||
markerStart="url(#Triangle)"
|
||||
/>
|
||||
</Svg>
|
||||
);
|
||||
|
||||
const samples = [
|
||||
EllipseExample,
|
||||
LineExample,
|
||||
CircleExample,
|
||||
RectExample,
|
||||
PathExample,
|
||||
];
|
||||
export {icon, samples};
|
||||
@@ -7,10 +7,10 @@ buildscript {
|
||||
mavenCentral()
|
||||
google()
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
classpath("com.android.tools.build:gradle:3.6.1")
|
||||
classpath "com.diffplug.spotless:spotless-plugin-gradle:5.15.0"
|
||||
classpath("com.android.tools.build:gradle:7.4.2")
|
||||
classpath "com.diffplug.spotless:spotless-plugin-gradle:6.17.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,8 +39,10 @@ def safeExtGet(prop, fallback) {
|
||||
|
||||
android {
|
||||
compileSdkVersion safeExtGet('compileSdkVersion', 28)
|
||||
namespace "com.horcrux.svg"
|
||||
|
||||
def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION
|
||||
if (agpVersion.tokenize('.')[0].toInteger() >= 7) {
|
||||
namespace "com.horcrux.svg"
|
||||
}
|
||||
// Used to override the NDK path/version on internal CI or by allowing
|
||||
// users to customize the NDK path/version from their root project (e.g. for M1 support)
|
||||
if (rootProject.hasProperty("ndkPath")) {
|
||||
@@ -55,7 +57,7 @@ android {
|
||||
//noinspection OldTargetApi
|
||||
targetSdkVersion safeExtGet('targetSdkVersion', 28)
|
||||
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
||||
|
||||
|
||||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
lintOptions {
|
||||
@@ -66,7 +68,7 @@ android {
|
||||
java {
|
||||
if (!isNewArchitectureEnabled()) {
|
||||
srcDirs += [
|
||||
"src/paper/java",
|
||||
"src/paper/java",
|
||||
"build/generated/source/codegen/java"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,6 +27,12 @@ class PathView extends RenderableView {
|
||||
public void setD(String d) {
|
||||
mPath = PathParser.parse(d);
|
||||
elements = PathParser.elements;
|
||||
for (PathElement elem : elements) {
|
||||
for (Point point : elem.points) {
|
||||
point.x *= mScale;
|
||||
point.y *= mScale;
|
||||
}
|
||||
}
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo (AccessibilityNodeInfo info) {
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
|
||||
Rect r = new Rect();
|
||||
|
||||
@@ -7,9 +7,9 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.Rect;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
@@ -23,7 +23,6 @@ import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.OnLayoutEvent;
|
||||
import com.facebook.react.uimanager.PointerEvents;
|
||||
import com.facebook.react.uimanager.UIManagerHelper;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.views.view.ReactViewGroup;
|
||||
import java.util.ArrayList;
|
||||
@@ -110,29 +109,28 @@ public abstract class VirtualView extends ReactViewGroup {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo (AccessibilityNodeInfo info) {
|
||||
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(info);
|
||||
if (mClientRect != null) {
|
||||
|
||||
SvgView root = getSvgView();
|
||||
SvgView root = getSvgView();
|
||||
|
||||
int[] rootPositionOnScreen = new int[2];
|
||||
getSvgView().getLocationOnScreen(rootPositionOnScreen);
|
||||
Rect infoBoundsInScreen = new Rect();
|
||||
infoBoundsInScreen.left = rootPositionOnScreen[0] + (int) Math.floor(mClientRect.left);
|
||||
infoBoundsInScreen.top = rootPositionOnScreen[1] + (int) Math.floor(mClientRect.top);
|
||||
infoBoundsInScreen.right = infoBoundsInScreen.left + (int) Math.ceil(mClientRect.width());
|
||||
infoBoundsInScreen.bottom = infoBoundsInScreen.top + (int) Math.ceil(mClientRect.height());
|
||||
int[] rootPositionOnScreen = new int[2];
|
||||
getSvgView().getLocationOnScreen(rootPositionOnScreen);
|
||||
Rect infoBoundsInScreen = new Rect();
|
||||
infoBoundsInScreen.left = rootPositionOnScreen[0] + (int) Math.floor(mClientRect.left);
|
||||
infoBoundsInScreen.top = rootPositionOnScreen[1] + (int) Math.floor(mClientRect.top);
|
||||
infoBoundsInScreen.right = infoBoundsInScreen.left + (int) Math.ceil(mClientRect.width());
|
||||
infoBoundsInScreen.bottom = infoBoundsInScreen.top + (int) Math.ceil(mClientRect.height());
|
||||
|
||||
Rect rootVisibleRect = new Rect();
|
||||
boolean isRootVisible = root.getGlobalVisibleRect(rootVisibleRect);
|
||||
boolean infoIsVisibleToUser = isRootVisible && infoBoundsInScreen.intersect(rootVisibleRect);
|
||||
Rect rootVisibleRect = new Rect();
|
||||
boolean isRootVisible = root.getGlobalVisibleRect(rootVisibleRect);
|
||||
boolean infoIsVisibleToUser = isRootVisible && infoBoundsInScreen.intersect(rootVisibleRect);
|
||||
|
||||
|
||||
String infoClassName = this.getClass().getCanonicalName();
|
||||
info.setBoundsInScreen(infoBoundsInScreen);
|
||||
info.setClassName(infoClassName);
|
||||
info.setVisibleToUser(infoIsVisibleToUser);
|
||||
String infoClassName = this.getClass().getCanonicalName();
|
||||
info.setBoundsInScreen(infoBoundsInScreen);
|
||||
info.setClassName(infoClassName);
|
||||
info.setVisibleToUser(infoIsVisibleToUser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,7 +597,8 @@ public abstract class VirtualView extends ReactViewGroup {
|
||||
setRight(right);
|
||||
setBottom(bottom);
|
||||
}
|
||||
EventDispatcher eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(mContext, getId());
|
||||
EventDispatcher eventDispatcher =
|
||||
UIManagerHelper.getEventDispatcherForReactTag(mContext, getId());
|
||||
if (eventDispatcher != null) {
|
||||
eventDispatcher.dispatchEvent(OnLayoutEvent.obtain(this.getId(), left, top, width, height));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user