SVG In ScrollView
See original GitHub issueHi,
I am trying to make a drawing app using React Native and this library. Here is my code:
import React from "react";
import { PanResponder, Alert, StyleSheet, View, Text } from "react-native";
import { G, Line, Svg, Path } from "react-native-svg";
class Drawing extends React.Component {
constructor(props) {
super(props);
this.state = {
offsetX: 0,
offsetY: 0,
width: "100%",
height: "200",
paths: [],
currentPath: ""
};
this.layout.bind(this);
}
layout(event) {
// Called when the board is rendered and frame dimensions are available
this._board.measure((width, height, px, py, fx, fy) => {
this.setState({
offsetX: fx,
offsetY: fy,
width: px,
height: py
});
});
}
componentWillMount() {
// Simple equation to map a number within a range to another range
Number.prototype.map = function(in_min, in_max, out_min, out_max) {
return (
(this - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
);
};
let extractCoordinates = gestureState => {
// Subtract offset from coordinate returned and map to viewBox range
return {
x: (gestureState.moveX - this.state.offsetX).map(
0,
this.state.width,
0,
720
),
y: (gestureState.moveY - this.state.offsetY).map(
0,
this.state.height,
0,
1000
)
};
};
this._touchCatcher = PanResponder.create({
onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
this.props.drawingEnabled,
onPanResponderGrant: (event, gestureState) => {
// Gesture started
let point = extractCoordinates(gestureState);
this.setState({
currentPath: `M${point.x} ${point.y} `
});
},
onPanResponderMove: (evt, gestureState) => {
let point = extractCoordinates(gestureState);
this.setState({
currentPath: this.state.currentPath + `L${point.x} ${point.y} `
});
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
// The user has released all touches while this view is the
// responder. This typically means a gesture has succeeded
this.setState({
paths: [...this.state.paths, this.state.currentPath],
currentPath: ""
});
},
onPanResponderTerminate: (evt, gestureState) => {
// Another component has become the responder, so this gesture
// should be cancelled
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// Returns whether this component should block native components from becoming the JS
// responder. Returns true by default. Is currently only supported on android.
return true;
}
});
}
render() {
let pathElements = [];
let i = 0;
for (path of this.state.paths) {
pathElements.push(<Path key={i} d={path} stroke="black" fill="none" strokeWidth="1" />);
i++;
}
return (
<View style={styles.border}>
<View
style={{
width: "100%",
height: "100%",
backgroundColor: "white"
}}
ref={board => (this._board = board)}
onLayout={e => this.layout(e)}
{...this._touchCatcher.panHandlers}
>
<Svg
width={this.state.width}
height={this.state.height}
key={this.state.paths.length}
viewBox="0 0 720 1000"
>
<G>
<Path
d={this.state.currentPath}
fill="none"
stroke="black"
strokeWidth={1}
/>
{pathElements}
</G>
</Svg>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
border: {
width: "100%",
aspectRatio: 0.72,
padding: "4%",
backgroundColor: "#E57373",
borderRadius: 10,
shadowOpacity: 0.75,
shadowRadius: 5,
shadowColor: "grey",
shadowOffset: { height: 8, width: 0 }
},
board: {
width: "100%",
height: "100%",
backgroundColor: "white"
}
});
export default Drawing;
The problem is that when I zoom in to draw on a particular section of the drawing, the path is very low resolution. I have looked into previous issues filed on how to force a re-render of the SVG, but as you can see I’m already using the key
workaround and that doesn’t appear to be working. The only way I have found to trigger a refresh is to set the width and height to arbitrary values and then draw a path and then change them back to what they were before; but this is obviously not an ideal way to do this.
What should I be doing instead?
As a Swift developer I would say the easiest thing for you guys to do would be to implement a forceReload
prop or something else so that the SVG is re-drawn every time a render is called. I could try doing this myself and filing a pull request, I would just need guidance on what files I should touch and what you guys think of my approach.
Thanks for all the work you’ve already put in!
- Andi
Issue Analytics
- State:
- Created 6 years ago
- Comments:7
Top GitHub Comments
@Nexuist I’ve made an example here: https://snack.expo.io/@msand/svg-pinch-to-pan-and-zoom
We had to use the same trick in https://infinitewhiteboard.com thought it might be useful for you as well 😄