H5开发,开发照相机,以及组件封装

为什么要封装H5照相机组件?

移动端网页中通过<input type="file">调用的原生相机体验较差:

  • 每次拍照后需要确认操作
  • 无法快速连续拍摄
  • 缺少放大缩小、手电筒等常用功能

封装自定义相机组件可以:

  1. 实现连拍功能,提高拍摄效率
  2. 添加更多相机功能
  3. 统一UI风格

核心实现步骤

1. 显示摄像头画面

javascript 复制代码
// 获取摄像头权限
const getStream = async () => {
  const stream = await navigator.mediaDevices.getUserMedia({
    audio: false,
    video: {
      facingMode: "environment", // 后置摄像头
      width: 1920,
      height: 1440
    }
  });
  
  // 将视频流绑定到video元素
  videoRef.current.srcObject = stream;
  videoRef.current.play();
};

2. 拍照功能实现

javascript 复制代码
const takePhoto = () => {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  
  // 设置画布大小
  canvas.width = 480;
  canvas.height = 640;
  
  // 从video元素捕获画面
  ctx.drawImage(
    videoRef.current,
    0, 0, videoWidth, videoHeight, // 源图像参数
    0, 0, canvas.width, canvas.height // 目标画布参数
  );
  
  // 转换为图片
  const photoData = canvas.toDataURL('image/jpeg');
  
  return photoData;
};

3. 连拍功能

javascript 复制代码
const [photos, setPhotos] = useState([]);

const continuousShooting = () => {
  const timer = setInterval(() => {
    const newPhoto = takePhoto();
    setPhotos(prev => [...prev, newPhoto]);
  }, 1000); // 每秒拍一张
  
  // 5秒后停止
  setTimeout(() => clearInterval(timer), 5000);
};

4. 放大缩小功能

javascript 复制代码
const [zoom, setZoom] = useState(1);

// 放大
const zoomIn = () => {
  if (zoom >= 4) return;
  setZoom(zoom + 0.2);
  videoRef.current.style.transform = `scale(${zoom + 0.2})`;
};

// 缩小
const zoomOut = () => {
  if (zoom <= 1) return;
  setZoom(zoom - 0.2);
  videoRef.current.style.transform = `scale(${zoom - 0.2})`;
};

5. 手电筒功能

javascript 复制代码
const toggleFlash = () => {
  const track = videoRef.current.srcObject.getVideoTracks()[0];
  track.applyConstraints({
    advanced: [{ torch: !flashOn }]
  });
  setFlashOn(!flashOn);
};

6. 横竖屏适配

javascript 复制代码
// 使用orientation.js检测屏幕方向
const orientation = new Orientation({
  onChange: (event) => {
    // 根据event.alpha/beta/gamma判断方向
    setIsLandscape(/* 判断逻辑 */);
  }
});

// 拍照时根据方向调整
if (isLandscape) {
  // 旋转画布90度
  ctx.rotate(Math.PI/2);
  // 调整绘制位置
}

完整组件结构

jsx 复制代码
function Camera() {
  const videoRef = useRef();
  const [zoom, setZoom] = useState(1);
  const [photos, setPhotos] = useState([]);
  const [flashOn, setFlashOn] = useState(false);
  const [isLandscape, setIsLandscape] = useState(false);

  // 初始化摄像头
  useEffect(() => {
    initCamera();
    return () => stopCamera();
  }, []);

  return (
    <div className="camera-container">
      {/* 视频预览区域 */}
      <div className="video-wrapper">
        <video ref={videoRef} style={{ transform: `scale(${zoom})` }} />
      </div>
      
      {/* 控制区域 */}
      <div className="controls">
        <button onClick={zoomIn}>放大</button>
        <button onClick={zoomOut}>缩小</button>
        <button onClick={takePhoto}>拍照</button>
        <button onClick={continuousShooting}>连拍</button>
        <button onClick={toggleFlash}>
          {flashOn ? '关闭手电筒' : '打开手电筒'}
        </button>
      </div>
      
      {/* 照片预览 */}
      <div className="preview">
        {photos.map((photo, i) => (
          <img key={i} src={photo} alt={`预览${i}`} />
        ))}
      </div>
    </div>
  );
}

注意事项

  1. 兼容性处理:不同浏览器API可能有差异
  2. 性能优化:及时释放摄像头资源
  3. 移动端适配:处理横竖屏切换
  4. 权限处理:优雅处理用户拒绝权限的情况
  5. 图片压缩:大尺寸图片上传前需要压缩

总结

通过getUserMedia API获取摄像头数据流,结合canvas实现拍照功能,再添加各种控制功能,就能打造一个功能完善的H5相机组件。这种方案比原生<input type="file">提供了更好的用户体验和更多自定义功能。

相关推荐
粥里有勺糖36 分钟前
安利一下最近用的桌面“Agent” | T3 Code
前端·github·ai编程
xy345342 分钟前
Axure 9.0 动态面板基本操作
前端·ui·html·axure·原型·产品设计
不停喝水1 小时前
【前端转全栈java速通课】 项目实战④7-11节 操作数据库-登录-注册-修改密码-注销-mubatis-plus简化crud-
java·前端·数据库
一水鉴天2 小时前
统一对象拓扑(UOT)设计全链定稿:从三件事分离到三继承 之1 20261010(豆包“查看聊天内容”继续)
前端·css
栖凤2 小时前
Java 的 try-catch 在 Agent 里失效了,我用了 5 个模式才兜住
java·前端·python
粥里有勺糖2 小时前
视野修炼第136期 | 前端小恐龙"Deno"被收购
前端·github·ai编程
修炼的dance2 小时前
页面塞了13.88 MB字体,导出的PDF只有71 KB
前端
qq_369173632 小时前
如何将 AI 生成的 HTML 网页发布成在线链接?不用自己搭建服务器
前端·人工智能·html·效率工具·html 发布
风花一世月2 小时前
⚡ 我把一座含氢能源园区搬进了浏览器(五类能流实时算守恒,在线直接玩)
前端·人工智能
羲云2 小时前
Claude 越界事件之后:Agent 权限设计为什么不能只靠提示词
前端