From 8bc66a4ee962b302136727f69b45b67ec6fb0407 Mon Sep 17 00:00:00 2001 From: a1518 Date: Wed, 1 Jul 2026 19:07:32 -0700 Subject: [PATCH] refactor: remove Chinese, add build obfuscation, polish README - Remove all Chinese characters from src/, example/, ios/, patches/, tests/ - Add esbuild-based build obfuscation (minify + identifier mangle + no sourcemaps) - Drop src/ from npm publish, only ship minified dist/ - Remove source maps and declaration maps from build output - Add README icons and visual polish throughout - Fix broken Table of Contents anchor links in README Co-authored-by: Cursor --- .npmignore | 1 + App.tsx | 22 +- README.md | 886 ++++----- __tests__/wallTextureSplit.test.ts | 4 +- dist/components/MaskSegmentCanvas.d.ts | 1 - dist/components/MaskSegmentCanvas.d.ts.map | 1 - dist/components/MaskSegmentCanvas.js | 1589 +---------------- dist/components/MaskSegmentCanvas.js.map | 1 - dist/components/MaskSegmentCanvas.types.d.ts | 25 +- .../MaskSegmentCanvas.types.d.ts.map | 1 - dist/components/MaskSegmentCanvas.types.js | 3 +- .../components/MaskSegmentCanvas.types.js.map | 1 - dist/index.d.ts | 1 - dist/index.d.ts.map | 1 - dist/index.js | 7 +- dist/index.js.map | 1 - dist/shaders/regionPaint.sksl.d.ts | 3 +- dist/shaders/regionPaint.sksl.d.ts.map | 1 - dist/shaders/regionPaint.sksl.js | 12 +- dist/shaders/regionPaint.sksl.js.map | 1 - dist/utils/canvasGeometry.d.ts | 1 - dist/utils/canvasGeometry.d.ts.map | 1 - dist/utils/canvasGeometry.js | 307 +--- dist/utils/canvasGeometry.js.map | 1 - dist/utils/compositePaintedImage.d.ts | 13 +- dist/utils/compositePaintedImage.d.ts.map | 1 - dist/utils/compositePaintedImage.js | 147 +- dist/utils/compositePaintedImage.js.map | 1 - dist/utils/exportUtils.d.ts | 1 - dist/utils/exportUtils.d.ts.map | 1 - dist/utils/exportUtils.js | 33 +- dist/utils/exportUtils.js.map | 1 - dist/utils/freqLayerPrep.d.ts | 13 +- dist/utils/freqLayerPrep.d.ts.map | 1 - dist/utils/freqLayerPrep.js | 179 +- dist/utils/freqLayerPrep.js.map | 1 - dist/utils/maskOutlinePaths.d.ts | 1 - dist/utils/maskOutlinePaths.d.ts.map | 1 - dist/utils/maskOutlinePaths.js | 420 +---- dist/utils/maskOutlinePaths.js.map | 1 - dist/utils/maskSegmentRuntime.d.ts | 1 - dist/utils/maskSegmentRuntime.d.ts.map | 1 - dist/utils/maskSegmentRuntime.js | 198 +- dist/utils/maskSegmentRuntime.js.map | 1 - dist/utils/maskSegmentation.d.ts | 27 +- dist/utils/maskSegmentation.d.ts.map | 1 - dist/utils/maskSegmentation.js | 1213 +------------ dist/utils/maskSegmentation.js.map | 1 - dist/utils/maskSemanticPalette.d.ts | 15 +- dist/utils/maskSemanticPalette.d.ts.map | 1 - dist/utils/maskSemanticPalette.js | 135 +- dist/utils/maskSemanticPalette.js.map | 1 - dist/utils/opencvAdapter.d.ts | 25 +- dist/utils/opencvAdapter.d.ts.map | 1 - dist/utils/opencvAdapter.js | 357 +--- dist/utils/opencvAdapter.js.map | 1 - dist/utils/paintColorMapTexture.d.ts | 3 +- dist/utils/paintColorMapTexture.d.ts.map | 1 - dist/utils/paintColorMapTexture.js | 204 +-- dist/utils/paintColorMapTexture.js.map | 1 - dist/utils/paintShaderRuntime.d.ts | 5 +- dist/utils/paintShaderRuntime.d.ts.map | 1 - dist/utils/paintShaderRuntime.js | 77 +- dist/utils/paintShaderRuntime.js.map | 1 - dist/utils/pickMapTexture.d.ts | 3 +- dist/utils/pickMapTexture.d.ts.map | 1 - dist/utils/pickMapTexture.js | 25 +- dist/utils/pickMapTexture.js.map | 1 - dist/utils/pngImage.d.ts | 21 +- dist/utils/pngImage.d.ts.map | 1 - dist/utils/pngImage.js | 439 +---- dist/utils/pngImage.js.map | 1 - dist/utils/resolveAssetPath.d.ts | 3 +- dist/utils/resolveAssetPath.d.ts.map | 1 - dist/utils/resolveAssetPath.js | 57 +- dist/utils/resolveAssetPath.js.map | 1 - dist/utils/resolveImageUrl.d.ts | 3 +- dist/utils/resolveImageUrl.d.ts.map | 1 - dist/utils/resolveImageUrl.js | 71 +- dist/utils/resolveImageUrl.js.map | 1 - dist/utils/skiaImage.d.ts | 3 +- dist/utils/skiaImage.d.ts.map | 1 - dist/utils/skiaImage.js | 13 +- dist/utils/skiaImage.js.map | 1 - dist/utils/wallTextureSplit.d.ts | 5 +- dist/utils/wallTextureSplit.d.ts.map | 1 - dist/utils/wallTextureSplit.js | 480 +---- dist/utils/wallTextureSplit.js.map | 1 - example/App.tsx | 148 +- example/README.md | 140 +- example/index.js | 10 +- example/metro.config.js | 24 +- index.js | 6 - ios/MaskSegmentApp/Info.plist | 4 +- ios/Podfile | 4 +- ios/offline_pods.rb | 2 +- ios/scripts/setup_vendor_pods.sh | 2 +- metro.config.js | 13 - package-lock.json | 490 ++++- package.json | 10 +- patches/react-native-fast-opencv+0.4.8.patch | 2 +- scripts/build.mjs | 50 + src/components/MaskSegmentCanvas.tsx | 8 +- src/components/MaskSegmentCanvas.types.ts | 24 +- src/globals.d.ts | 2 +- src/shaders/regionPaint.sksl.ts | 2 +- src/utils/canvasGeometry.ts | 16 +- src/utils/compositePaintedImage.ts | 16 +- src/utils/freqLayerPrep.ts | 14 +- src/utils/maskOutlinePaths.ts | 2 +- src/utils/maskSegmentation.ts | 38 +- src/utils/maskSemanticPalette.ts | 14 +- src/utils/opencvAdapter.ts | 34 +- src/utils/paintColorMapTexture.ts | 2 +- src/utils/paintShaderRuntime.tsx | 4 +- src/utils/pickMapTexture.ts | 2 +- src/utils/pngImage.ts | 40 +- src/utils/resolveAssetPath.ts | 2 +- src/utils/resolveImageUrl.ts | 2 +- src/utils/skiaImage.ts | 2 +- src/utils/wallTextureSplit.ts | 11 +- tsconfig.build.json | 5 +- 122 files changed, 1394 insertions(+), 6845 deletions(-) delete mode 100644 dist/components/MaskSegmentCanvas.d.ts.map delete mode 100644 dist/components/MaskSegmentCanvas.js.map delete mode 100644 dist/components/MaskSegmentCanvas.types.d.ts.map delete mode 100644 dist/components/MaskSegmentCanvas.types.js.map delete mode 100644 dist/index.d.ts.map delete mode 100644 dist/index.js.map delete mode 100644 dist/shaders/regionPaint.sksl.d.ts.map delete mode 100644 dist/shaders/regionPaint.sksl.js.map delete mode 100644 dist/utils/canvasGeometry.d.ts.map delete mode 100644 dist/utils/canvasGeometry.js.map delete mode 100644 dist/utils/compositePaintedImage.d.ts.map delete mode 100644 dist/utils/compositePaintedImage.js.map delete mode 100644 dist/utils/exportUtils.d.ts.map delete mode 100644 dist/utils/exportUtils.js.map delete mode 100644 dist/utils/freqLayerPrep.d.ts.map delete mode 100644 dist/utils/freqLayerPrep.js.map delete mode 100644 dist/utils/maskOutlinePaths.d.ts.map delete mode 100644 dist/utils/maskOutlinePaths.js.map delete mode 100644 dist/utils/maskSegmentRuntime.d.ts.map delete mode 100644 dist/utils/maskSegmentRuntime.js.map delete mode 100644 dist/utils/maskSegmentation.d.ts.map delete mode 100644 dist/utils/maskSegmentation.js.map delete mode 100644 dist/utils/maskSemanticPalette.d.ts.map delete mode 100644 dist/utils/maskSemanticPalette.js.map delete mode 100644 dist/utils/opencvAdapter.d.ts.map delete mode 100644 dist/utils/opencvAdapter.js.map delete mode 100644 dist/utils/paintColorMapTexture.d.ts.map delete mode 100644 dist/utils/paintColorMapTexture.js.map delete mode 100644 dist/utils/paintShaderRuntime.d.ts.map delete mode 100644 dist/utils/paintShaderRuntime.js.map delete mode 100644 dist/utils/pickMapTexture.d.ts.map delete mode 100644 dist/utils/pickMapTexture.js.map delete mode 100644 dist/utils/pngImage.d.ts.map delete mode 100644 dist/utils/pngImage.js.map delete mode 100644 dist/utils/resolveAssetPath.d.ts.map delete mode 100644 dist/utils/resolveAssetPath.js.map delete mode 100644 dist/utils/resolveImageUrl.d.ts.map delete mode 100644 dist/utils/resolveImageUrl.js.map delete mode 100644 dist/utils/skiaImage.d.ts.map delete mode 100644 dist/utils/skiaImage.js.map delete mode 100644 dist/utils/wallTextureSplit.d.ts.map delete mode 100644 dist/utils/wallTextureSplit.js.map create mode 100644 scripts/build.mjs diff --git a/.npmignore b/.npmignore index 9c68c63..aa4e0d7 100644 --- a/.npmignore +++ b/.npmignore @@ -24,6 +24,7 @@ tsconfig.build.json .cursor/ agent-transcripts/ assets/ +scripts/ # Dependencies node_modules/ diff --git a/App.tsx b/App.tsx index 6f1452c..7359785 100644 --- a/App.tsx +++ b/App.tsx @@ -1,9 +1,9 @@ /** * Mask Segment Demo App - * 基于 OpenCV + Skia 的掩码分区交互画布 + * Mask segmentation canvas based on OpenCV + Skia * - * 注意:这是库开发自测用的 Demo,直接引用 ./src。 - * 业务项目集成演示请参考 example/ 目录(使用公开包名导入)。 + * Note: This is a demo for library development testing, directly referencing ./src. + * For business project integration demonstration, please refer to the example/ directory (import using the public package name). */ import React, { useEffect, useRef, useState } from 'react'; @@ -37,15 +37,15 @@ function formatWatchStatus(state: MaskSegmentWatchState | ''): string { return ''; } if (state === 'interactive') { - return '可上色(轮廓加载中…)'; + return 'Colorable (outline loading...)'; } if (state === 'mask_paths_ready') { - return '就绪'; + return 'Ready'; } if (state === 'error') { - return '失败'; + return 'Failed'; } - return `加载中:${state}`; + return `Loading: ${state}`; } function App(): React.JSX.Element { @@ -103,8 +103,8 @@ function App(): React.JSX.Element { <> {watchState ? ( - 状态: {formatWatchStatus(watchState)} - {isFullyReady ? ' · 轮播虚线已就绪' : null} + Status: {formatWatchStatus(watchState)} + {isFullyReady ? ' · Carousel dashed line ready' : null} ) : null} @@ -153,14 +153,14 @@ function App(): React.JSX.Element { {sessionDraft ? ( - 已恢复 MMKV 草稿({sessionDraft.painted.length} 区域) + Restored MMKV draft ({sessionDraft.painted.length} regions) ) : null} ) : ( - 加载健身房测试图… + Loading gym test image... )} diff --git a/README.md b/README.md index 093688d..0242f26 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,105 @@ -# react-native-mask-segment-canvas +# 🎨 react-native-mask-segment-canvas -基于 React Native **0.79** 的掩码分区交互库,核心导出 `MaskSegmentCanvas` 组件,可通过 **npm 包** 或 **npm link** 接入其它 RN 工程。 +A React Native **0.79** interactive mask segmentation library. The core export is the `MaskSegmentCanvas` component, consumable via **npm package** or **npm link** from any React Native project. -- **OpenCV**(`react-native-fast-opencv`):掩码语义布局、踢脚线修补、分区提取 -- **Skia RuntimeEffect(SkSL)**:原图 + LAB 高低频纹理叠色(单次全屏 Shader) -- **Skia Path**:分区虚线轮廓高亮 -- **交互**:底部笔刷选色(可选初始化)→ 点击分区上色;未选笔刷时点击分区会通过 `onPaintCallback` 提示;未选笔刷时长按预览分区虚线轮廓 +- 🧠 **OpenCV** (`react-native-fast-opencv`): mask semantic layout, baseboard patching, region extraction +- 🖌️ **Skia RuntimeEffect (SkSL)**: single-pass full-screen shader blending original image + LAB low/high frequency texture color overlays +- ✂️ **Skia Path**: dashed outline highlights for regions +- 👆 **Interaction**: bottom color bar for brush selection (optional initialization) → tap a region to paint; tapping without a brush selected fires `onPaintCallback` with a hint; long-press without a brush previews the region's dashed outline -本仓库同时作为 **库源码**(`src/index.ts`)与 **自测 Demo**(根目录 `App.tsx`)维护。 +This repository serves as both the **library source** (`src/index.ts`) and a **self-test demo** (root `App.tsx`). -**推荐的集成演示请查看 `example/` 目录**:它只使用公开 API,完整模拟业务项目接入方式(含 `package.json`、Metro 配置、完整可参考的 `App.tsx`)。 +📌 **For the recommended integration demo, see the `example/` directory** — it uses only the public API, fully simulating how a consumer project would integrate (including `package.json`, Metro configuration, and a complete reference `App.tsx`). --- -## 作为 npm 包接入其它工程 +## Table of Contents -### 安装依赖(宿主工程) +- [Overview](#overview) +- [Requirements](#requirements) +- [Installation](#installation) + - [Peer Dependencies](#peer-dependencies) + - [Postinstall Setup](#postinstall-setup) + - [iOS / Android Native Dependencies](#ios--android-native-dependencies) + - [Metro Configuration](#metro-configuration) + - [Troubleshooting: Duplicate Module Errors](#troubleshooting-duplicate-module-errors) +- [Quick Start (Dev Demo)](#quick-start-dev-demo) +- [Basic Usage](#basic-usage) + - [Minimal Example](#minimal-example) + - [State Variables](#state-variables) + - [Choosing Configuration Values](#choosing-configuration-values) + - [watchState & UI Guidance](#watchstate--ui-guidance) +- [API Reference](#api-reference) + - [Imports](#imports) + - [Props: Image & Initialization](#props-image--initialization) + - [Props: Semantic Colors & Outline](#props-semantic-colors--outline) + - [Props: maskConfig](#props-maskconfig) + - [Props: pipelineConfig](#props-pipelineconfig) + - [Props: paintConfig](#props-paintconfig) + - [Props: interactionConfig](#props-interactionconfig) + - [Props: UI Controls & Styling](#props-ui-controls--styling) + - [Props: Callbacks](#props-callbacks) + - [Ref Methods](#ref-methods) + - [Storage Convention](#storage-convention) +- [Interaction Guide](#interaction-guide) +- [Integration Examples](#integration-examples) + - [Pre-warm PNG Cache (Recommended)](#pre-warm-png-cache-recommended) + - [Passing Local Paths from an API](#passing-local-paths-from-an-api) + - [Draft Recovery](#draft-recovery) + - [Custom Semantic Color Table](#custom-semantic-color-table) +- [Project Structure](#project-structure) +- [Dependencies](#dependencies) +- [Performance](#performance) + - [Measured Reference (Dev Env + PNG Pre-warming)](#measured-reference-dev-env-png-pre-warming) + - [Resolution vs pipelineConfig](#resolution-vs-pipelineconfig) + - [interactive Estimation (Default Pipeline)](#interactive-estimation-default-pipeline) + - [Device Tier (1080p, Default Pipeline)](#device-tier-1080p-default-pipeline) + - [Impact of Raising maxImageLongSide](#impact-of-raising-maximagelongside) + - [Optimization Tips](#optimization-tips) +- [Notes](#notes) +- [Troubleshooting](#troubleshooting) -```bash -npm install react-native-mask-segment-canvas -# 或本地联调 -npm link ../MaskSegmentApp # 在库目录先执行 npm link -npm link react-native-mask-segment-canvas -``` +--- -宿主工程还需安装 **peerDependencies**(版本需与宿主 RN 对齐): +## 🔭 Overview + +`MaskSegmentCanvas` renders an original image with an overlaid semantic mask, allowing users to tap regions and apply colors. The pipeline: + +1. 📥 **Load** the origin image and mask image (local `file://` or remote `http(s)://`) +2. 🧩 **Segment** the mask via OpenCV into semantic regions (walls, ceiling, baseboard, etc.) +3. 🎨 **Prepare** LAB frequency-layer textures via SkSL for realistic color blending +4. 📐 **Build** Skia dashed-outline paths for each region +5. 👆 **Interactive** — users select a brush color and tap regions to paint; paint layers preserve the underlying texture +6. 💾 **Save** the composited result as PNG; export a JSON session for draft recovery + +The component emits `onWatch` state transitions through the pipeline so the host app can show appropriate loading states. + +--- + +## 📋 Requirements + +- 🟢 Node.js >= 18 (recommended 20+) +- 🍎 Xcode 15+ (iOS) +- 🤖 Android Studio + JDK 17 (Android) +- 📦 CocoaPods (iOS) + +--- + +## 📦 Installation + +### 📦 Peer Dependencies + +Install these in your host project (versions should match your host RN version): ```bash npm install @shopify/react-native-skia react-native-reanimated react-native-fast-opencv react-native-fs buffer upng-js -# 若使用 showDebugPickers 相册选图 +# If using showDebugPickers (photo library picker) npm install react-native-image-picker ``` -### 宿主工程 postinstall(必需) +### 🛠️ Postinstall Setup -本库依赖 `patch-package` 修补 `react-native-fast-opencv`,宿主 `package.json` 需配置: +This library relies on `patch-package` to patch `react-native-fast-opencv`. Your host `package.json` must include: ```json { @@ -47,19 +112,19 @@ npm install react-native-image-picker } ``` -安装本库后,`node_modules/react-native-mask-segment-canvas/patches/` 中的补丁会在宿主 `postinstall` 时自动应用。 +After installing this library, patches from `node_modules/react-native-mask-segment-canvas/patches/` are applied automatically during the host's `postinstall`. -### iOS / Android 原生依赖 +### 📱 iOS / Android Native Dependencies ```bash cd ios && pod install && cd .. ``` -确保宿主已按各原生库文档完成 Skia、Reanimated、OpenCV 等配置。 +Ensure the host project has completed Skia, Reanimated, and OpenCV native setup per each library's documentation. -### Metro 配置(npm link / monorepo / file: 依赖时) +### 🚇 Metro Configuration -联调时若出现模块解析问题,在宿主 `metro.config.js` 中把本库加入 `watchFolders`,并使用下面推荐的完整配置(同时包含 extraNodeModules + blockList)。这是防止所有「类似重复模块问题」(SkiaPictureView undefined、Reanimated Animated node already exists 等)的可靠做法: +When using `npm link`, a monorepo, or `file:` dependencies, add this library to `watchFolders` and use `extraNodeModules` + `blockList` to prevent duplicate module resolution: ```js const path = require('path'); @@ -68,7 +133,6 @@ module.exports = { watchFolders: [path.resolve(__dirname, '../MaskSegmentApp')], resolver: { nodeModulesPaths: [path.resolve(__dirname, 'node_modules')], - // 推荐同时使用 extraNodeModules + blockList extraNodeModules: { 'react-native-reanimated': path.resolve(__dirname, 'node_modules/react-native-reanimated'), '@shopify/react-native-skia': path.resolve(__dirname, 'node_modules/@shopify/react-native-skia'), @@ -89,103 +153,36 @@ module.exports = { }; ``` -**强烈建议**在宿主 `index.js` 最顶部加入(在任何业务代码之前): +**Strongly recommended** — add this at the very top of the host `index.js` (before any business code): ```js import '@shopify/react-native-skia'; ``` -(完整推荐配置见下文「故障排查」以及 `example/metro.config.js` + `example/index.js`,那里有覆盖全部 peer 的 singletons 列表。) +See `example/metro.config.js` and `example/index.js` for the complete configuration with all peer singleton packages. -### 故障排查:各种重复模块导致的运行时错误 +### ⚠️ Troubleshooting: Duplicate Module Errors -常见症状(同类问题): +Common symptoms: - `SkiaPictureView must be a function (received 'undefined')` - `createAnimatedNode: Animated node[...] already exists` -**几乎总是**因为 Metro 同时解析到多份 reanimated / skia / gesture-handler / fast-opencv / safe-area 等包。 +These are almost always caused by Metro resolving multiple copies of reanimated / skia / gesture-handler / fast-opencv / safe-area packages. -**最佳实践**: +**Best practice:** -- 直接复制 `example/metro.config.js` 里的 `singletonPackages` + extraNodeModules + blockList 写法 -- 在你的 `index.js` 最顶部加入 gesture-handler → reanimated → skia 三个 import -- 重启 Metro (`--reset-cache`) + 重装 app - -详细清单和模板见 `example/README.md` 的「运行时出现类似错误」一节。 -### 业务侧引入 - -```tsx -import MaskSegmentCanvas, { - type MaskSegmentCanvasRef, - type MaskSegmentSession, - type MaskSegmentWatchState, - type MaskSegmentWatchDetail, - type BgrColor, - type MaskSemanticColor, - type PaintCallbackPayload, - type PaintedRegionRecord, - type PipelineConfig, - type MaskSegmentConfig, - type PaintConfig, - type InteractionConfig, - type SavePaintResult, - MASK_SEMANTIC_COLORS, - BASEBOARD_SEMANTIC_NAME, - prewarmPngBgrCacheAsync, - DEFAULT_PIPELINE_CONFIG, - DEFAULT_MASK_CONFIG, - DEFAULT_PAINT_CONFIG, - DEFAULT_INTERACTION_CONFIG, -} from 'react-native-mask-segment-canvas'; -``` - -主要导出一览: - - -| 类别 | 名称 | -| -------------- | ----------------------------------------------------------------------------------- | -| 组件 | `MaskSegmentCanvas`(default) | -| Ref / Props 类型 | `MaskSegmentCanvasRef`、`MaskSegmentCanvasProps` | -| 会话 / 回调类型 | `MaskSegmentSession`、`PaintCallbackPayload`、`PaintedRegionRecord`、`SavePaintResult` | -| Watch 类型 | `MaskSegmentWatchState`、`MaskSegmentWatchDetail` | -| 配置类型 | `PipelineConfig`、`MaskSegmentConfig`、`PaintConfig`、`InteractionConfig` | -| 语义色 | `MASK_SEMANTIC_COLORS`、`BASEBOARD_SEMANTIC_NAME` | -| 工具 | `prewarmPngBgrCacheAsync`、`prewarmPngBgrCache` | -| 运行时 | `DEFAULT_*_CONFIG`、`getMaskSegmentRuntimeConfig`、`setMaskSegmentRuntimeConfig` | +1. Copy the `singletonPackages` + `extraNodeModules` + `blockList` pattern from `example/metro.config.js` +2. At the top of your `index.js`, import gesture-handler → reanimated → skia in order +3. Restart Metro with `--reset-cache` and reinstall the app +See `example/README.md` for a detailed checklist and template. --- -## 推荐:通过 example/ 目录学习集成 +## 🚀 Quick Start (Dev Demo) -`example/` 是**专门为业务侧集成准备的演示文件夹**,它: - -- 只通过 `import ... from 'react-native-mask-segment-canvas'` 使用公开 API(不碰内部 src) -- 提供了独立的 `package.json`(含 peer deps + 本地 file 依赖) -- 包含针对本地联调的 `metro.config.js` -- `App.tsx` 是一个可直接参考的完整页面,涵盖预热、状态管理、ref 操作、回调处理等 - -建议: - -1. 直接阅读 `example/App.tsx` 获取最新可运行的集成写法。 -2. 按 `example/README.md` 的步骤在本机跑起来,验证安装、patch、Metro 配置是否正确。 -3. 把 `example/App.tsx` 中的核心逻辑复制到你自己的页面/组件中即可。 - -这样可以确保你接入的是「库的公开契约」,而不是内部实现细节。 - ---- - -## 环境要求 - -- Node.js >= 18(推荐 20+) -- Xcode 15+(iOS) -- Android Studio + JDK 17(Android) -- CocoaPods(iOS) - -## 快速开始(本仓库 Demo) - -根目录 `App.tsx` 是库作者自测用的完整 Demo,内部直接 import `./src`。 +The root `App.tsx` is a full self-test demo that imports directly from `./src`. ```bash cd MaskSegmentApp @@ -196,51 +193,21 @@ cd ios && bundle exec pod install && cd .. npm start -# 另开终端 +# In another terminal npm run ios -# 或 +# or npm run android ``` -**想看「纯业务项目如何集成」**:请进入 `example/` 目录,按其 `README.md` 操作。它使用 `import from 'react-native-mask-segment-canvas'` + 标准的 `package.json` + Metro 配置,完全模拟消费者环境。 - -Demo 入口 `App.tsx` 通过 `./src`(即包入口 `src/index.ts`)引用组件,与业务侧 `import from 'react-native-mask-segment-canvas'` 等价。 +**To see how a consumer project integrates:** go to the `example/` directory and follow its `README.md`. It uses `import from 'react-native-mask-segment-canvas'` with standard `package.json` and Metro config, fully simulating a consumer environment. --- -## MaskSegmentCanvas 组件 +## 💡 Basic Usage -### 引入 +### 🧑‍💻 Minimal Example -```tsx -import React, { useRef } from 'react'; -import MaskSegmentCanvas, { - type MaskSegmentCanvasRef, - type MaskSegmentSession, - type MaskSegmentWatchState, - type MaskSegmentWatchDetail, - type BgrColor, - type MaskSemanticColor, - type PaintCallbackPayload, - MASK_SEMANTIC_COLORS, - prewarmPngBgrCacheAsync, -} from 'react-native-mask-segment-canvas'; -``` - -也可按需导入运行时默认值(与组件 Props 合并使用): - -```tsx -import { - DEFAULT_PIPELINE_CONFIG, - DEFAULT_MASK_CONFIG, - DEFAULT_PAINT_CONFIG, - DEFAULT_INTERACTION_CONFIG, -} from 'react-native-mask-segment-canvas'; -``` - -### 最小示例 - -下面是一个可直接放进业务页面的完整示例,涵盖 **PNG 预热**、**state**、**配置**、**加载态**、**onWatch** 与 **ref** 常用操作。 +A complete, copy-pasteable example covering **PNG pre-warming**, **state management**, **configuration**, **loading states**, **onWatch**, and **ref operations**. ```tsx import React, { useEffect, useRef, useState } from 'react'; @@ -254,7 +221,7 @@ import MaskSegmentCanvas, { prewarmPngBgrCacheAsync, } from 'react-native-mask-segment-canvas'; -/** 业务侧准备好的图片地址(本地 file:// 或 http(s)://) */ +/** Image paths prepared by the host app (local file:// or http(s)://) */ type ImagePaths = { origin: string; mask: string; @@ -284,7 +251,7 @@ export function PaintScreen() { !INTERACTIVE_STATES.includes(watchState as MaskSegmentWatchState) && watchState !== 'error'; - // 示例:接口下载完成后写入路径,并预热 PNG 解码缓存 + // Example: download images, then pre-warm PNG decode cache useEffect(() => { let cancelled = false; @@ -322,18 +289,18 @@ export function PaintScreen() { return ( - 等待原图与掩码… + Waiting for origin and mask images... ); } return ( - {isCanvasLoading ? 加载中:{watchState} : null} + {isCanvasLoading ? Loading: {watchState} : null} {watchState === 'interactive' ? ( - 可上色(轮廓加载中…) + Paintable (outlines loading...) ) : null} - {isOutlineReady ? 就绪 : null} + {isOutlineReady ? Ready : null} {errorMessage ? {errorMessage} : null} { setWatchState(state); - // detail: regionCount, maskPathsReady, freqLayersReady, errorMessage console.log('[onWatch]', state, durationMs, detail); }} onPaintCallback={payload => { @@ -374,49 +340,44 @@ export function PaintScreen() { setWatchState('error'); }} /> - - {/* ref 示例:disabled={!isInteractive} 时可按需绑定 */} - {/*