Skip to content

Commit b10274a

Browse files
authored
Merge pull request rpmsoftware#9 from rpmsoftware/issue-5-generate-signature-from-name
Generate signature from name
2 parents 7545dee + e75abb1 commit b10274a

File tree

4 files changed

+138
-18
lines changed

4 files changed

+138
-18
lines changed

README.md

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,42 @@ React Native wrapper around @[szimek's](https://github.com/szimek) HTML5 Canvas
1717
npm install --save react-native-signature-pad
1818
```
1919

20+
## Using a Custom Signature Font
21+
22+
There is an option to generate a signature based off the user's name. You can use your own custom font. Currently, we recommend converting your font file into a data URL (we used [dataurl.net](http://dataurl.net/#dataurlmaker)). Store that in a .js file with the contents similar to something like below:
23+
24+
```js
25+
var content = `
26+
@font-face {
27+
font-family: 'SignatureFont';
28+
src: url(/* data url of your font */) format(/* orig font file type i.e. 'ttf' */);
29+
}
30+
`;
31+
32+
export default content;
33+
```
34+
35+
## Generating a Signature from a String
36+
37+
If you would like to generate a signature as opposed to manually writing your own, you can enable the `useFont` prop to `true` and use the prop `name` where the generated signature will be based from.
38+
39+
```js
40+
...
41+
42+
var signatureFont = require('./signature-font');
43+
44+
...
45+
46+
var aName = 'John Doe';
47+
48+
<SignaturePad
49+
...
50+
useFont={true}
51+
name={aName}
52+
fontStyle={signatureFont}
53+
/>
54+
```
55+
2056
## Example
2157

2258
```js
@@ -36,11 +72,14 @@ export default class Demo extends Component {
3672
render = () => {
3773
return (
3874
<View style={{flex: 1}}>
39-
<SignaturePad onError={this._signaturePadError}
40-
onChange={this._signaturePadChange}
41-
penMinWidth={penMinWidth}
42-
penMaxWidth={penMaxWidth}
43-
style={{flex: 1, backgroundColor: 'white'}}/>
75+
<SignaturePad
76+
onError={this._signaturePadError}
77+
onChange={this._signaturePadChange}
78+
penMinWidth={penMinWidth}
79+
penMaxWidth={penMaxWidth}
80+
style={{flex: 1, backgroundColor: 'white'}}
81+
useFont={false}
82+
/>
4483
</View>
4584
)
4685
};

index.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,22 @@ class SignaturePad extends Component {
2222
dataURL: PropTypes.string,
2323
penMinWidth: PropTypes.number,
2424
penMaxWidth: PropTypes.number,
25+
useFont: PropTypes.bool,
26+
name: PropTypes.string,
27+
fontStyle: PropTypes.string,
2528
};
2629

2730
static defaultProps = {
2831
onChange: () => {},
2932
onError: () => {},
3033
style: {},
34+
useFont: false
3135
};
3236

3337
constructor(props) {
3438
super(props);
35-
this.state = {base64DataUrl: props.dataURL || null};
39+
var escapedName = props.name.replace(/"/, `\\"`);
40+
this.state = {base64DataUrl: props.dataURL || null, name: escapedName };
3641
const { backgroundColor } = StyleSheet.flatten(props.style);
3742
var injectedJavaScript = injectedExecuteNativeFunction
3843
+ injectedErrorHandler
@@ -43,15 +48,40 @@ class SignaturePad extends Component {
4348
props.dataURL,
4449
props.penMinWidth,
4550
props.penMaxWidth,
51+
props.useFont,
52+
escapedName
4653
);
47-
var html = htmlContent(injectedJavaScript);
54+
var html = htmlContent(injectedJavaScript, props.fontStyle);
4855
this.source = { html };
4956
// We don't use WebView's injectedJavaScript because on Android,
5057
// the WebView re-injects the JavaScript upon every url change.
5158
// Given that we use url changes to communicate signature changes to the
5259
// React Native app, the JS is re-injected every time a stroke is drawn.
5360
}
5461

62+
componentWillReceiveProps = (nextProps) => {
63+
if (this.props.useFont && this.state.name !== nextProps.name) {
64+
var escapedName = nextProps.name.replace(/"/, `\\"`);
65+
this.setState({ name: escapedName });
66+
67+
const { backgroundColor } = StyleSheet.flatten(this.props.style);
68+
var injectedJavaScript = injectedExecuteNativeFunction
69+
+ injectedErrorHandler
70+
+ injectedSignaturePad
71+
+ injectedApplication(
72+
this.props.penColor,
73+
backgroundColor,
74+
this.props.dataURL,
75+
this.props.penMinWidth,
76+
this.props.penMaxWidth,
77+
this.props.useFont,
78+
escapedName
79+
);
80+
var html = htmlContent(injectedJavaScript, this.props.fontStyle);
81+
this.source = { html };
82+
}
83+
};
84+
5585
_onNavigationChange = (args) => {
5686
this._parseMessageFromWebViewNavigationChange(unescape(args.url));
5787
};

injectedHtml/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var content = script =>
1+
var content = (script, fontStyle) =>
22
`<html>
33
<style>
44
*
@@ -16,8 +16,12 @@ var content = script =>
1616
-ms-transform:rotate(-90deg) translate(-100%, 0px);
1717
-webkit-transform:rotate(-90deg) translate(-100%, 0px);*/
1818
}
19+
</style>
1920
21+
<style type="text/css">
22+
${fontStyle}
2023
</style>
24+
2125
<body>
2226
<canvas style="margin-left: 0; margin-top: 0;"></canvas>
2327
<script>

injectedJavaScript/application.js

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
var content = (penColor, backgroundColor, dataURL, penMinWidth, penMaxWidth) => `
1+
var content = (penColor, backgroundColor, dataURL, penMinWidth, penMaxWidth, useFont, name) => `
22
33
var showSignaturePad = function (signaturePadCanvas, bodyWidth, bodyHeight) {
44
/*We're rotating by 90% -> Flip X and Y*/
@@ -14,17 +14,17 @@ var content = (penColor, backgroundColor, dataURL, penMinWidth, penMaxWidth) =>
1414
var canvasHeight = height * devicePixelRatio;
1515
signaturePadCanvas.width = canvasWidth;
1616
signaturePadCanvas.height = canvasHeight;
17-
signaturePadCanvas.getContext('2d').scale(devicePixelRatio, devicePixelRatio);
17+
signaturePadCanvas.getContext("2d").scale(devicePixelRatio, devicePixelRatio);
1818
};
1919
2020
var finishedStroke = function(base64DataUrl) {
21-
executeNativeFunction('finishedStroke', {base64DataUrl: base64DataUrl});
21+
executeNativeFunction("finishedStroke", {base64DataUrl: base64DataUrl});
2222
};
2323
2424
var enableSignaturePadFunctionality = function () {
2525
var signaturePad = new SignaturePad(signaturePadCanvas, {
26-
penColor: '${penColor || 'black'}',
27-
backgroundColor: '${backgroundColor || 'white'}',
26+
penColor: "${penColor || "black"}",
27+
backgroundColor: "${backgroundColor || "white"}",
2828
onEnd: function() { finishedStroke(signaturePad.toDataURL()); }
2929
});
3030
/* signaturePad.translateMouseCoordinates = function (point) {
@@ -35,16 +35,15 @@ var content = (penColor, backgroundColor, dataURL, penMinWidth, penMaxWidth) =>
3535
}; */
3636
signaturePad.minWidth = ${penMinWidth || 1};
3737
signaturePad.maxWidth = ${penMaxWidth || 4};
38-
if ('${dataURL}') {
39-
signaturePad.fromDataURL('${dataURL}');
38+
if ("${dataURL}") {
39+
signaturePad.fromDataURL("${dataURL}");
4040
}
4141
};
4242
4343
sizeSignaturePad();
4444
enableSignaturePadFunctionality();
4545
};
4646
47-
4847
var bodyWidth = document.body.clientWidth;
4948
var bodyHeight = document.body.clientHeight;
5049
if(!bodyWidth) {
@@ -54,8 +53,56 @@ var content = (penColor, backgroundColor, dataURL, penMinWidth, penMaxWidth) =>
5453
bodyHeight = window.innerHeight;
5554
}
5655
57-
var canvasElement = document.querySelector('canvas');
58-
showSignaturePad(canvasElement, bodyWidth, bodyHeight);
56+
var canvasElement = document.querySelector("canvas");
57+
58+
if (${useFont}) {
59+
var context = canvasElement.getContext("2d");
60+
var devicePixelRatio = 1; /* window.devicePixelRatio || 1; */
61+
context.canvas.width = bodyWidth * devicePixelRatio;
62+
context.canvas.height = bodyHeight * devicePixelRatio;
63+
64+
var ratio = Math.max(window.devicePixelRatio || 1, 1);
65+
var backingStoreRatio = context.webkitBackingStorePixelRatio ||
66+
context.mozBackingStorePixelRatio ||
67+
context.msBackingStorePixelRatio ||
68+
context.oBackingStorePixelRatio ||
69+
context.backingStorePixelRatio || 1;
70+
var realRatio = ratio / backingStoreRatio;
71+
if (ratio !== backingStoreRatio) {
72+
ratio = ratio / backingStoreRatio;
73+
}
74+
75+
var oldWidth = context.canvas.width;
76+
var oldHeight = context.canvas.height;
77+
78+
var fontSize = 45;
79+
var textHeight = 12;
80+
if (realRatio === 2) {
81+
fontSize = 90;
82+
textHeight = 18;
83+
}
84+
85+
var textWidth = -1;
86+
87+
do {
88+
context.font = fontSize + "px SignatureFont";
89+
textWidth = context.measureText("${name}").width * ratio;
90+
fontSize = 7 * fontSize / 8;
91+
} while (textWidth > oldWidth);
92+
93+
var textPosition = {
94+
x: ((oldWidth - textWidth) / 2),
95+
y: ((3 * oldHeight / 4) - textHeight)
96+
};
97+
98+
context.fillStyle = "${penColor}";
99+
context.fillText("${name}", textPosition.x, textPosition.y);
100+
101+
/* Fire a finishedStroke function to update the state */
102+
executeNativeFunction("finishedStroke", {base64DataUrl: canvasElement.toDataURL()});
103+
} else {
104+
showSignaturePad(canvasElement, bodyWidth, bodyHeight);
105+
}
59106
`;
60107

61108
export default content;

0 commit comments

Comments
 (0)