Open JamesMcIntosh opened 5 years ago
Thanks James, I'll take a look at your fork and let you know or just steal it.
My usage is only for iOS (for now), so the Android performance is irrelevant to me (for now).
I don't use the onChange
callback, since it fires too often and may miss a change event if the signature pad doesn't cover the whole screen and the user "draws" off its canvas.
This is how I use my component:
_renderSignaturePad = () => {
return (
<View style={styles.sigPadContainer}>
<Text style={styles.sigPadHeading}>Draw your signature below</Text>
<SignaturePad
ref={(ref) => { this._sigPad = ref }}
onError={this._handleSignaturePadError}
style={styles.sigPadBg}
backgroundColor={this.state.penColor}
_pixelRatio={1}
webViewBackgroundColor='#eee'
useFont={false}
/>
<View style={styles.sigPadBaseline} />
</View>
)
}
Then I've got my own Modal
component that renders the above:
render () {
/// ...
const sigPadButtons = [
[
{
text: 'Clear',
type: 'subtle-warning',
onPress: this._handleClearSigPad
}
], [
{
text: 'Cancel'
},
{
text: 'Use',
onPress: this._handleUseSignature,
type: 'primary'
}
]
]
// ...
<Modal
ref={(ref) => { this._modal = ref }}
visible={false}
renderWhenVisible={this._renderSignaturePad}
width={600}
buttonsContainerStyle={layoutStyles.flex0}
buttons={sigPadButtons}
/>
// ...
So the buttons' callbacks are:
_handleClearSigPad = () => {
this._sigPad.clear()
}
_handleUseSignature = async () => {
// NOTE: check if signature is empty
try {
const isEmpty = await this._sigPad.isEmpty()
if (isEmpty) {
Alert.alert('Signature is empty!')
return
}
} catch (err) {
if (__DEBUG__) {
console.error('AdminInspectorDetails:_handleUseSignature - isEmpty', err.message)
}
}
// NOTE: get signature data
let data
try {
data = await this._sigPad.getBase64Data()
} catch (err) {
if (__DEBUG__) {
console.error('AdminInspectorDetails:_handleUseSignature - getBase64Data', err.message)
}
Alert.alert('Error getting signature data')
return
}
const toStrip = 'data:image/png;base64,'
data = data.substr(toStrip.length)
// NOTE: write signature data to file
const filename = `signature-${guid()}.png`
const path = `${docPath}/${filename}`
const uri = `file://${path}`
if (__DEBUG__) {
console.warn('path', path)
}
let stat
let dim
try {
await RNFS.writeFile(path, data, 'base64')
stat = await RNFS.stat(path)
dim = await new Promise((resolve, reject) => { Image.getSize(uri, (width, height) => resolve({ width, height }), reject) })
} catch (err) {
Alert.alert('Error writing signature file')
return
}
// NOTE: fake the signature submit
const value = {
bytes: stat.size,
filename,
path: '',
width: dim.width,
height: dim.height
}
await this._handleValueSubmit({
key: 'signature',
value
}, { FAKE_VALUES: 'FAKE_VALUES' })
// NOTE: update UI
this._inputsController.setValues({
signature: value
})
await this._modal.hide()
}
The fake signature submit is just an implementation detail that's not important.
Wow, thanks for the awesome feedback!
Hi Evo,
I've also borrowed part of your pattern of sending messages into the component to clear the canvas. I implemented the communication into the SignaturePad component as follows, is this how you accomplished it also? It would be good to add it to your Readme.md as an example.
I also made some changes to a fork of react-native-signature-pad, you may be interested in some of my changes to help it perform better on Android.
https://github.com/JamesMcIntosh/react-native-signature-pad/commits/master
Kind regards James