You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中如何导出带黑色打码矩形的PNG图片?

嘿,我完全懂你的需求——你想直接在原始拍摄的图片上添加黑色遮挡打码,而不是用react-native-view-shot那样截取屏幕(毕竟它不仅只能截全屏,生成的图分辨率还不够)。这里有几个实用的方案可以帮你实现:

方案1:用 react-native-canvas 直接编辑图片

这个工具能让你在React Native里使用HTML5 Canvas API,直接加载原始图片并绘制遮挡,最后导出高分辨率的PNG,完美避开屏幕截取的问题。

步骤示例:

  1. 先安装依赖:
npm install react-native-canvas
# iOS 需额外执行 pod install
  1. 核心代码实现:
import React, { useRef, useEffect } from 'react';
import Canvas from 'react-native-canvas';

const ImageCensor = ({ imageUri, censorAreas, onProcessed }) => {
  const canvasRef = useRef(null);

  useEffect(() => {
    if (!canvasRef.current || !imageUri) return;

    const applyCensor = async () => {
      const canvas = canvasRef.current;
      const ctx = canvas.getContext('2d');
      const img = new canvas.Image();
      
      img.onload = async () => {
        // 画布尺寸和原始图片保持一致
        canvas.width = img.width;
        canvas.height = img.height;
        // 先绘制原始图片
        ctx.drawImage(img, 0, 0);
        
        // 逐个绘制黑色遮挡矩形
        censorAreas.forEach(area => {
          ctx.fillStyle = 'black';
          ctx.fillRect(area.x, area.y, area.width, area.height);
        });
        
        // 导出为PNG格式的Base64字符串
        const pngBase64 = await canvas.toDataURL('image/png');
        // 这里可以把结果传给后端,或者转成Blob上传
        onProcessed(pngBase64);
      };
      
      img.src = imageUri; // 传入相机拍摄的原始图片路径
    };

    applyCensor();
  }, [imageUri, censorAreas]);

  // 画布可以隐藏,只做后台处理
  return <Canvas ref={canvasRef} style={{ position: 'absolute', width: 0, height: 0 }} />;
};

export default ImageCensor;

这个方案的优势是直接操作图片像素,生成的图片分辨率和原始图完全一致,没有屏幕截取的画质损失。

方案2:用 react-native-skia 高性能处理

react-native-skia是官方推荐的高性能2D图形库,支持直接绘制和导出图片,性能比Canvas更好,适合大尺寸图片的处理。

步骤示例:

  1. 安装依赖:
npm install @shopify/react-native-skia
  1. 核心代码实现:
import React, { useMemo } from 'react';
import { Button } from 'react-native';
import { Canvas, Image as SkiaImage, Rect, Fill } from '@shopify/react-native-skia';
import { encodeToBase64 } from '@shopify/react-native-skia';

const CensoredImageHandler = ({ imageUri, censorAreas }) => {
  const skiaImage = useMemo(() => SkiaImage.fromUri(imageUri), [imageUri]);
  
  const exportAndUpload = async () => {
    if (!skiaImage) return;
    
    // 创建画布并绘制内容
    const canvas = Canvas.MakeImageSnapshot(skiaImage.width(), skiaImage.height());
    const ctx = canvas.getContext();
    // 绘制原始图片
    ctx.drawImage(skiaImage, 0, 0);
    // 添加黑色遮挡
    censorAreas.forEach(area => {
      ctx.fillRect(area.x, area.y, area.width, area.height, 'black');
    });
    
    // 导出为PNG格式的Base64
    const pngBase64 = encodeToBase64(canvas.makeImageSnapshot(), 'png');
    // 调用后端接口上传图片
    uploadToServer(pngBase64);
  };

  return (
    <>
      {/* 可以预览处理后的效果 */}
      <Canvas style={{ width: skiaImage?.width(), height: skiaImage?.height() }}>
        <SkiaImage image={skiaImage} x={0} y={0} />
        {censorAreas.map((area, idx) => (
          <Rect key={idx} x={area.x} y={area.y} width={area.width} height={area.height}>
            <Fill color="black" />
          </Rect>
        ))}
      </Canvas>
      <Button title="导出并上传" onPress={exportAndUpload} />
    </>
  );
};
方案3:原生模块(iOS/Android)处理(性能最优)

如果你的图片尺寸极大,或者需要极致性能,可以写原生模块直接处理:

  • iOS:用Core Graphics框架加载UIImage,绘制黑色矩形后导出PNG;
  • Android:用Bitmap和Canvas类编辑原始图片,保存为PNG格式。

然后通过React Native的桥接机制,把原生处理方法暴露给JS调用。这种方式性能最好,但需要你具备一定的原生开发能力。

内容的提问来源于stack exchange,提问作者Vladimír

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:14:36