JSPM

@ninjasumer/react-native-image-annotator

1.0.0
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 1
    • Score
      100M100P100Q32951F
    • License ninjasumer

    A powerful React Native component for annotating images with drawing, text, zoom, and pan capabilities. Works on iOS, Android, and Web.

    Package Exports

    • @ninjasumer/react-native-image-annotator
    • @ninjasumer/react-native-image-annotator/dist/index.js
    • @ninjasumer/react-native-image-annotator/dist/index.mjs

    This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@ninjasumer/react-native-image-annotator) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

    Readme

    🖼️ React Native Image Annotator

    Un componente potente y flexible para React Native que permite anotar imágenes con dibujos a mano alzada, texto y gestos de zoom/pan. Funciona en iOS, Android y Web.

    Platforms React Native

    ✨ Características

    • 🖌️ Dibujo a mano alzada - Dibuja con el dedo o ratón con colores y grosores personalizables
    • 📝 Anotaciones de texto - Añade texto en cualquier posición, arrastra para mover
    • 🔍 Zoom y Pan - Pellizca para hacer zoom, arrastra con dos dedos para mover
    • ↩️ Historial completo - Deshacer/Rehacer todas las acciones
    • 💾 Exportación - Captura la imagen anotada como URI o DataURL
    • 🎨 Toolbar personalizable - Activa/desactiva funciones según necesites
    • Botones personalizados - Añade tus propios botones al toolbar
    • 📱 Multiplataforma - iOS, Android y Web
    • 🎯 Controlado y no controlado - Usa como componente controlado o no controlado

    📦 Instalación

    npm install react-native-image-annotator

    Dependencias requeridas (peer dependencies)

    # Con npm
    npm install react-native-gesture-handler react-native-reanimated react-native-svg react-native-view-shot
    
    # Con Expo
    npx expo install react-native-gesture-handler react-native-reanimated react-native-svg react-native-view-shot

    Configuración adicional

    React Native Reanimated

    Añade el plugin de Babel en babel.config.js:

    module.exports = {
      plugins: ["react-native-reanimated/plugin"],
    };

    React Native Gesture Handler

    Envuelve tu app con GestureHandlerRootView:

    import { GestureHandlerRootView } from "react-native-gesture-handler";
    
    export default function App() {
      return (
        <GestureHandlerRootView style={{ flex: 1 }}>
          {/* Tu app */}
        </GestureHandlerRootView>
      );
    }

    🚀 Uso básico

    import { ImageAnnotator } from "react-native-image-annotator";
    
    export default function App() {
      return (
        <ImageAnnotator
          imageUri="https://example.com/image.jpg"
          height={400}
          showToolBar={true}
        />
      );
    }

    📖 Props

    Prop Tipo Default Descripción
    imageUri string requerido URI de la imagen a anotar
    height number 360 Altura del componente
    imageResizeMode "cover" | "contain" "cover" Modo de redimensionado de imagen
    showToolBar boolean false Muestra el toolbar integrado
    showDefaultControls boolean false Muestra controles básicos por defecto
    toolbarConfig ToolBarConfig - Configura qué elementos mostrar en toolbar
    customToolbarButtons CustomToolbarButton[] - Botones personalizados para el toolbar
    renderControls (api: ControlsAPI) => ReactNode - Renderiza controles personalizados
    onExport (uri: string) => void - Callback al exportar (botón guardar)
    value DrawingJSON - Estado del dibujo (controlado)
    defaultValue DrawingJSON - Estado inicial (no controlado)
    onChange (drawing: DrawingJSON) => void - Callback cuando cambia el dibujo
    strokeColor string "#ff0000" Color de trazo inicial
    strokeWidth number 4 Grosor de trazo inicial
    fontSize number 20 Tamaño de fuente inicial
    minScale number 1 Zoom mínimo
    maxScale number 4 Zoom máximo

    🎛️ Configuración del Toolbar

    Puedes personalizar qué elementos mostrar en el toolbar:

    import { ImageAnnotator, ToolBarConfig } from "react-native-image-annotator";
    
    const config: ToolBarConfig = {
      tools: true, // Herramientas (lápiz, texto, mover)
      colors: true, // Selector de color
      sizes: true, // Selector de grosor/tamaño
      zoom: true, // Controles de zoom (+/-)
      history: true, // Botones deshacer/rehacer
      clear: true, // Botón limpiar
      resetView: true, // Botón resetear vista
      save: true, // Botón guardar
    };
    
    <ImageAnnotator imageUri="..." showToolBar={true} toolbarConfig={config} />;

    🔧 Botones personalizados

    Añade tus propios botones al toolbar:

    import {
      ImageAnnotator,
      CustomToolbarButton,
    } from "react-native-image-annotator";
    
    const customButtons: CustomToolbarButton[] = [
      {
        icon: "🖼️",
        onPress: () => pickNewImage(),
        tooltip: "Cambiar imagen",
      },
      {
        icon: "📤",
        onPress: () => shareImage(),
        tooltip: "Compartir",
      },
    ];
    
    <ImageAnnotator
      imageUri="..."
      showToolBar={true}
      customToolbarButtons={customButtons}
    />;

    � Uso con Ref

    Accede a métodos del componente usando ref:

    import { useRef } from "react";
    import {
      ImageAnnotator,
      ImageAnnotatorRef,
    } from "react-native-image-annotator";
    
    export default function App() {
      const annotatorRef = useRef<ImageAnnotatorRef>(null);
    
      const handleCapture = async () => {
        const uri = await annotatorRef.current?.captureImage("png");
        console.log("Imagen capturada:", uri);
        // Puedes guardarla, compartirla, subirla, etc.
      };
    
      const handleUndo = () => {
        annotatorRef.current?.undo();
      };
    
      const handleExportJSON = () => {
        const json = annotatorRef.current?.exportJSON();
        console.log("Dibujo exportado:", json);
      };
    
      return (
        <ImageAnnotator
          ref={annotatorRef}
          imageUri="https://example.com/image.jpg"
        />
      );
    }

    📤 API del Ref (ImageAnnotatorRef)

    Método Descripción
    undo() Deshace la última acción
    redo() Rehace la última acción deshecha
    clear() Limpia todas las anotaciones
    resetView() Resetea zoom y posición
    setZoom(zoom) Establece el nivel de zoom
    getZoom() Obtiene el nivel de zoom actual
    setStrokeColor(color) Cambia el color del trazo
    setStrokeWidth(width) Cambia el grosor del trazo
    setFontSize(size) Cambia el tamaño de fuente
    setTool(tool) Cambia la herramienta
    addText(text) Añade texto en el centro
    captureImage(format?) Captura la imagen como URI
    exportJSON() Exporta el estado del dibujo como JSON
    loadJSON(json) Carga un estado de dibujo desde JSON

    🎨 Herramientas

    Herramienta Icono Descripción
    Lápiz ✏️ Dibujo a mano alzada
    Texto T Click para colocar texto, arrastra para mover
    Mover Mueve la vista con un dedo/click

    💾 Exportación de imagen

    Usando el callback onExport:

    <ImageAnnotator
      imageUri="..."
      showToolBar={true}
      onExport={async (uri) => {
        // En iOS/Android: uri es un path local
        // En Web: uri es un data URL (base64)
    
        // Ejemplo: Guardar en galería (necesita expo-media-library)
        if (Platform.OS !== "web") {
          await MediaLibrary.saveToLibraryAsync(uri);
        } else {
          // Descargar en web
          const link = document.createElement("a");
          link.href = uri;
          link.download = "imagen-anotada.png";
          link.click();
        }
      }}
    />

    Usando ref programáticamente:

    const handleSave = async () => {
      const uri = await annotatorRef.current?.captureImage("png");
      // Hacer lo que quieras con el URI
    };

    🎮 Controles personalizados

    Crea tu propia UI de controles:

    import { ImageAnnotator, ControlsAPI } from "react-native-image-annotator";
    
    const renderMyControls = (api: ControlsAPI) => (
      <View style={styles.myToolbar}>
        <Button title="Deshacer" onPress={api.undo} />
        <Button title="Rehacer" onPress={api.redo} />
        <Button title="Limpiar" onPress={api.clear} />
        <Button title="Rojo" onPress={() => api.setStrokeColor("#ff0000")} />
        <Button title="Azul" onPress={() => api.setStrokeColor("#0000ff")} />
      </View>
    );
    
    <ImageAnnotator imageUri="..." renderControls={renderMyControls} />;

    📱 Soporte de plataformas

    Plataforma Dibujo Texto Zoom/Pan Exportar
    iOS ✅ (URI)
    Android ✅ (URI)
    Web ✅ (Data URL)

    📝 Tipos TypeScript

    // Estado del dibujo
    type DrawingJSON = {
      version: 1;
      strokes: Stroke[];
      texts?: TextAnnotation[];
    };
    
    // Trazo
    type Stroke = {
      id: string;
      tool: "pen";
      color: string;
      width: number;
      points: Point[];
    };
    
    // Anotación de texto
    type TextAnnotation = {
      id: string;
      tool: "text";
      text: string;
      color: string;
      fontSize: number;
      position: Point;
    };
    
    // Punto
    type Point = { x: number; y: number };
    
    // Herramienta
    type Tool = "pen" | "text" | "pan";
    
    // Configuración del toolbar
    type ToolBarConfig = {
      tools?: boolean;
      colors?: boolean;
      sizes?: boolean;
      zoom?: boolean;
      history?: boolean;
      clear?: boolean;
      resetView?: boolean;
      save?: boolean;
    };
    
    // Botón personalizado
    type CustomToolbarButton = {
      icon: string;
      onPress: () => void;
      tooltip?: string;
    };

    🔄 Componente controlado vs no controlado

    No controlado (más simple):

    <ImageAnnotator
      imageUri="..."
      defaultValue={{ version: 1, strokes: [], texts: [] }}
    />

    Controlado (control total):

    const [drawing, setDrawing] = useState<DrawingJSON>({
      version: 1,
      strokes: [],
      texts: [],
    });
    
    <ImageAnnotator imageUri="..." value={drawing} onChange={setDrawing} />;

    📄 Licencia

    MIT

    Desarrollado como proyecto del Máster en Ingenieria Web (UNIOVI) para la asignatura "Desarrollo de aplicaciones móviles".