react-native-canvas-hash
v1.1.0
Published
High-performance native Android canvas component for React Native with drawing, erasing, undo/redo support
Maintainers
Readme
react-native-canvas-hash
Note this is only for android
High-performance native Android canvas component for React Native with drawing, erasing, undo/redo support.
Features
- ✅ Native Android Performance - Built with Kotlin for optimal performance
- ✅ Drawing - Smooth pen drawing with customizable color and size
- ✅ Eraser - Erase drawings with customizable eraser size
- ✅ Undo/Redo - Full undo/redo support
- ✅ Hand Mode - Enable scrolling when hand tool is active
- ✅ Base64 Export - Export drawings as base64 images
- ✅ Path Counting - Get path counts for undo/redo button states
Installation
npm install react-native-canvas-hash
# or
yarn add react-native-canvas-hashAndroid Setup
- Add the package to
settings.gradle(in your project'sandroidfolder):
include ':react-native-canvas-hash'
project(':react-native-canvas-hash').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-canvas-hash/android')- Add the dependency to your app's
build.gradle(usuallyandroid/app/build.gradle):
dependencies {
// ... other dependencies
implementation project(':react-native-canvas-hash')
}- Add the package to your
MainApplication.java(orMainApplication.ktif using Kotlin):
For Java:
import com.hash.canvas.CanvasPackage
public class MainApplication extends Application implements ReactApplication {
// ...
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
add(CanvasPackage()) // Add this line
);
}
}For Kotlin:
import com.hash.canvas.CanvasPackage
class MainApplication : Application(), ReactApplication {
// ...
override fun getPackages(): List<ReactPackage> {
return listOf(
MainReactPackage(),
CanvasPackage() // Add this line
)
}
}- Sync Gradle files (in Android Studio: File → Sync Project with Gradle Files) and rebuild.
Usage
import React, { useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import CanvasView, { CanvasViewRef } from 'react-native-canvas-hash';
const App = () => {
const canvasRef = useRef<CanvasViewRef>(null);
const handleUndo = async () => {
await canvasRef.current?.undo();
};
const handleRedo = async () => {
await canvasRef.current?.redo();
};
const handleClear = async () => {
await canvasRef.current?.clear();
};
const handleSave = async () => {
const base64 = await canvasRef.current?.readSignature();
console.log('Drawing saved:', base64);
};
return (
<View style={styles.container}>
<CanvasView
ref={canvasRef}
style={styles.canvas}
penColor="rgba(255, 0, 0, 1)"
penSize={3}
eraserSize={20}
isEraserMode={false}
isHandMode={false}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
canvas: {
flex: 1,
backgroundColor: 'transparent',
},
});Props
CanvasView Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| penColor | string | "rgba(255, 0, 0, 1)" | Pen color in rgba format |
| penSize | number | 2 | Pen stroke width |
| eraserSize | number | 20 | Eraser stroke width |
| isEraserMode | boolean | false | Enable eraser mode |
| isHandMode | boolean | false | Enable hand mode (allows scrolling) |
Methods
CanvasViewRef Methods
All methods return Promises and should be awaited.
undo()- Undo last drawing actionredo()- Redo last undone actionclear()- Clear all drawingsreadSignature()- Get base64 image string (data URI format)getData()- Get base64 image string (raw base64)getPathCount()- Get current path count (for undo button state)getUndonePathCount()- Get undone path count (for redo button state)
Example: Full Drawing App
import React, { useRef, useState } from 'react';
import { View, StyleSheet, TouchableOpacity, Text } from 'react-native';
import CanvasView, { CanvasViewRef } from 'react-native-canvas-hash';
const DrawingApp = () => {
const canvasRef = useRef<CanvasViewRef>(null);
const [isEraser, setIsEraser] = useState(false);
const [canUndo, setCanUndo] = useState(false);
const [canRedo, setCanRedo] = useState(false);
// Check undo/redo state periodically
React.useEffect(() => {
const interval = setInterval(async () => {
const pathCount = await canvasRef.current?.getPathCount() || 0;
const undoneCount = await canvasRef.current?.getUndonePathCount() || 0;
setCanUndo(pathCount > 0);
setCanRedo(undoneCount > 0);
}, 100);
return () => clearInterval(interval);
}, []);
return (
<View style={styles.container}>
<CanvasView
ref={canvasRef}
style={styles.canvas}
penColor="rgba(255, 0, 0, 1)"
penSize={3}
eraserSize={20}
isEraserMode={isEraser}
isHandMode={false}
/>
<View style={styles.toolbar}>
<TouchableOpacity
style={[styles.button, isEraser && styles.buttonActive]}
onPress={() => setIsEraser(!isEraser)}
>
<Text>Eraser</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, !canUndo && styles.buttonDisabled]}
onPress={() => canvasRef.current?.undo()}
disabled={!canUndo}
>
<Text>Undo</Text>
</TouchableOpacity>
<TouchableOpacity
style={[styles.button, !canRedo && styles.buttonDisabled]}
onPress={() => canvasRef.current?.redo()}
disabled={!canRedo}
>
<Text>Redo</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.button}
onPress={() => canvasRef.current?.clear()}
>
<Text>Clear</Text>
</TouchableOpacity>
</View>
</View>
);
};License
MIT
Author
Hamid
