react-native-image-annotator
v0.2.10
Published
A comprehensive image annotation library for React Native
Maintainers
Readme
React Native Image Annotator
A comprehensive image annotation library for React Native that allows users to draw, add text, and shapes to images, with support for saving in various formats including base64.
Features
- Multiple annotation tools: pen, line, rectangle, circle, arrow, text, and eraser
- Color and stroke width selection
- Undo/redo functionality
- Enhanced zoom and pan support with pinch-to-zoom
- Smooth pen drawing with bezier curves
- Draggable text annotations with selection state
- Support for base64 encoded images, URLs, and local images
- Automatic orientation handling (portrait/landscape)
- Export annotations in various formats (PNG, JPG, Base64)
- Customizable UI with flexible toolbar positioning
- Custom image styling support
- Stable annotation positioning (annotations stay in place when toolbar is toggled)
- TypeScript support
- Comprehensive example app
Installation
npm install react-native-image-annotator
# or
yarn add react-native-image-annotatorDependencies
This library depends on the following packages:
npm install react-native-gesture-handler react-native-reanimated react-native-svg react-native-view-shot
# or
yarn add react-native-gesture-handler react-native-reanimated react-native-svg react-native-view-shotCorepack Support
This project uses Corepack to ensure consistent package manager usage. Corepack is included by default with Node.js versions 16.9+ and 14.19+.
To enable Corepack, run:
corepack enableThis will ensure that the correct version of Yarn (1.22.21) is used when working with this project. For more information about Corepack, visit Yarn's Corepack documentation.
Usage
import React, { useState } from 'react';
import { View, Button, StyleSheet, Switch, Text } from 'react-native';
import { ImageAnnotator } from 'react-native-image-annotator';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
// Example base64 image (this is a tiny placeholder - use your actual base64 string)
const SAMPLE_BASE64 =
'iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAnElEQVR42u3RAQ0AAAjDMO5fNCCDkC5z0HSOmIUKEBABASIgAgJEQIAICBABERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgQAQEiIAAERAgAiIgJ1MAARZcZy0rAAAAAElFTkSuQmCC';
const App = () => {
const [annotatedImage, setAnnotatedImage] = useState(null);
const [useBase64, setUseBase64] = useState(false);
const [showToolbar, setShowToolbar] = useState(true);
const [toolbarPosition, setToolbarPosition] = useState('bottom');
const handleSaveImage = (result, format) => {
console.log('Saved image in format:', format);
setAnnotatedImage(result);
};
// Choose between URL and base64 image source
const imageSource = useBase64
? { base64: SAMPLE_BASE64 }
: { uri: 'https://picsum.photos/600/400' };
return (
<GestureHandlerRootView style={styles.container}>
<View style={styles.buttonContainer}>
<Button
title={useBase64 ? 'Switch to URL image' : 'Switch to Base64 image'}
onPress={() => setUseBase64(!useBase64)}
/>
<View style={styles.controlRow}>
<Text>Show Toolbar: </Text>
<Switch value={showToolbar} onValueChange={setShowToolbar} />
</View>
<View style={styles.controlRow}>
<Text>Toolbar Position: </Text>
<Button
title={toolbarPosition === 'bottom' ? 'Bottom' : 'Top'}
onPress={() =>
setToolbarPosition(
toolbarPosition === 'bottom' ? 'top' : 'bottom'
)
}
/>
</View>
</View>
<ImageAnnotator
source={imageSource}
onSaveImage={handleSaveImage}
defaultTool="pen"
defaultColor="#FF0000"
defaultStrokeWidth={4}
enableZoom={true}
showToolbar={showToolbar}
toolbarPosition={toolbarPosition}
imageStyle={{
borderRadius: 10,
borderWidth: 1,
borderColor: '#ddd',
}}
textOptions={{
fontSize: 20,
fontWeight: 'bold',
}}
/>
</GestureHandlerRootView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
buttonContainer: {
padding: 10,
},
controlRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginTop: 10,
},
});
export default App;Testing the Library
Option 1: Add to Your Existing React Native Project
The easiest way to test this library is to add it to your existing React Native project:
# Navigate to your React Native project
cd your-react-native-project
# Install the library and its dependencies
yarn add react-native-image-annotator react-native-gesture-handler react-native-reanimated react-native-svg react-native-view-shot
# For iOS, install pods
cd ios && pod install && cd ..Then, add the component to one of your screens:
import { ImageAnnotator } from 'react-native-image-annotator';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
function MyScreen() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<ImageAnnotator
source={{ uri: 'https://picsum.photos/600/400' }}
onSaveImage={(result, format) => console.log(result, format)}
containerStyle={{ height: 400 }}
/>
</GestureHandlerRootView>
);
}Option 2: Create a New Test Project
Automatic Setup (Recommended)
We provide a script that automatically creates a test React Native project with the library and example code already set up:
# Clone the repository
git clone https://github.com/kuldeep2022/react-native-image-annotator.git
cd react-native-image-annotator
# Make the script executable (if needed)
chmod +x create-test-app.sh
# Run the script (creates a project named "ImageAnnotatorTest" by default)
./create-test-app.sh
# Or specify a custom project name
./create-test-app.sh MyTestAppThe script will:
- Create a new React Native project
- Install all required dependencies
- Link the local library
- Configure babel.config.js for Reanimated
- Create an example App.js file
- Install pods for iOS (if on macOS)
After the script completes, you can run the test app:
cd ImageAnnotatorTest # or your custom project name
npx react-native run-ios # For iOS
npx react-native run-android # For AndroidManual Setup
Alternatively, you can manually create a test project:
# Create a new React Native project
npx react-native init ImageAnnotatorTest
# Navigate to the project
cd ImageAnnotatorTest
# Install the library and its dependencies
yarn add react-native-image-annotator react-native-gesture-handler react-native-reanimated react-native-svg react-native-view-shot
# Update babel.config.js to include the Reanimated plugin
# Add this line to the plugins array: "react-native-reanimated/plugin"
# For iOS, install pods
cd ios && pod install && cd ..Then replace the content of App.js with the example code from our INTEGRATION.md file.
For detailed integration instructions, see the INTEGRATION.md guide.
The example app demonstrates:
- Image selection
- Tool selection (pen, line, rectangle, circle, arrow, text, eraser)
- Color selection
- Annotation with the selected tool and color
- Exporting the annotated image in various formats (PNG, JPG, Base64)
- Viewing the exported result
Props
| Prop | Type | Default | Description |
| ------------------ | ------------------------------------------------- | ----------- | ----------------------------------------------------------- |
| source | { uri: string } \| number \| { base64: string } | Required | The image source (URI, require, or base64 string) |
| initialPaths | AnnotationPath[] | [] | Initial annotation paths |
| containerStyle | object | {} | Style for the container |
| imageStyle | object | {} | Custom style for the image |
| toolbarPosition | 'bottom' \| 'top' | 'bottom' | Position of the toolbar |
| defaultTool | AnnotationTool | 'pen' | Default selected tool |
| defaultColor | string | '#FF0000' | Default color |
| defaultStrokeWidth | number | 4 | Default stroke width |
| onPathsChange | (paths: AnnotationPath[]) => void | - | Callback when paths change |
| onSaveImage | (result: string, format: string) => void | - | Callback when image is saved |
| enableZoom | boolean | true | Enable zoom and pan |
| enableUndo | boolean | true | Enable undo functionality |
| enableRedo | boolean | true | Enable redo functionality |
| showToolbar | boolean | true | Show/hide the annotation toolbar without losing annotations |
| textOptions | object | {} | Options for text annotations |
Types
AnnotationTool
type AnnotationTool =
| 'pen'
| 'line'
| 'rectangle'
| 'circle'
| 'arrow'
| 'text'
| 'eraser';ExportFormat
type ExportFormat = 'png' | 'jpg' | 'base64';ExportOptions
type ExportOptions = {
format: ExportFormat;
quality?: number; // 0-1, default 1
result?: 'file' | 'base64'; // How the result should be returned
filename?: string; // Only used when result is 'file'
};Advanced Usage
Custom Toolbar
You can create a custom toolbar by using the exported types and utility functions:
import React, { useState, useRef } from 'react';
import { View, Button } from 'react-native';
import { ImageAnnotator, captureView } from 'react-native-image-annotator';
const CustomToolbarExample = () => {
const [tool, setTool] = useState('pen');
const [color, setColor] = useState('#000000');
const annotatorRef = useRef(null);
const saveAsBase64 = async () => {
try {
const result = await captureView(annotatorRef, {
format: 'base64',
quality: 1,
});
console.log('Base64 image:', result);
} catch (error) {
console.error('Error saving image:', error);
}
};
return (
<View style={{ flex: 1 }}>
<View style={{ flexDirection: 'row', padding: 10 }}>
<Button title="Pen" onPress={() => setTool('pen')} />
<Button title="Line" onPress={() => setTool('line')} />
<Button title="Save as Base64" onPress={saveAsBase64} />
</View>
<ImageAnnotator
ref={annotatorRef}
source={{ uri: 'https://example.com/image.jpg' }}
defaultTool={tool}
defaultColor={color}
/>
</View>
);
};License
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Acknowledgments
- Thanks to all contributors who have helped improve this library
- Inspired by the need for a flexible and powerful image annotation tool in React Native
