跳至主要内容
版本:v8

使用相机拍摄照片

现在,让我们开始最有趣的部分 - 使用 Capacitor 的 相机 API 添加使用设备相机拍摄照片的功能。我们将从为 Web 构建它开始,然后进行一些小的调整使其在移动设备(iOS 和 Android)上也能正常工作。

为此,我们将创建一个自定义的 React 钩子来管理图库中的照片。

注意

如果您不熟悉 React 钩子,React 钩子介绍 来自官方 React 文档,是一个很好的入门资源。

src/hooks/usePhotoGallery.ts 中创建一个新文件并打开它。

自定义钩子只是一个使用其他 React 钩子的函数。这就是我们要做的!我们将从导入将要使用的各种钩子和实用程序开始,这些钩子和实用程序来自 React 核心、Ionic React Hooks 项目和 Capacitor。

import { useState, useEffect } from 'react';
import { isPlatform } from '@ionic/react';

import { Camera, CameraResultType, CameraSource, Photo } from '@capacitor/camera';
import { Filesystem, Directory } from '@capacitor/filesystem';
import { Preferences } from '@capacitor/preferences';
import { Capacitor } from '@capacitor/core';

接下来,创建一个名为 usePhotoGallery 的函数。

export function usePhotoGallery() {
const takePhoto = async () => {
const photo = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100,
});
};

return {
takePhoto,
};
}

我们的 usePhotoGallery 钩子公开了一个名为 takePhoto 的方法,该方法会调用 Capacitor 的 getPhoto 方法。

注意这里的妙处:没有平台特定的代码(Web、iOS 或 Android)!Capacitor 相机插件为我们抽象了这一切,只留下一个方法调用 - getPhoto() - 它将打开设备的相机并允许我们拍摄照片。

我们最后需要做的步骤是在 Tab2 页面上使用这个新的钩子。返回 Tab2.tsx 并导入钩子

import { usePhotoGallery } from '../hooks/usePhotoGallery';

在函数组件的 return 语句之前,使用钩子获取对 takePhoto 方法的访问权限

const Tab2: React.FC = () => {
const { takePhoto } = usePhotoGallery();

// snip - rest of code

保存文件,如果您还没有,请通过运行 ionic serve 在浏览器中重启开发服务器。在“照片图库”选项卡上,单击“相机”按钮。如果您的电脑有摄像头,则会弹出一个模态窗口。拍张自拍照!

A photo gallery app displaying a webcam selfie.

(你的自拍照可能比我的好很多)

拍摄照片后,它会消失。我们仍然需要在应用程序中显示它并保存它以便将来访问。

显示照片

首先,我们将创建一个新类型来定义我们的照片,它将包含特定元数据。在 usePhotoGallery.ts 文件中添加以下 UserPhoto 接口,位于主函数之外

export interface UserPhoto {
filepath: string;
webviewPath?: string;
}

回到函数的顶部(在调用 usePhotoGallery 之后),我们将定义一个状态变量来存储使用相机拍摄的每张照片的数组。

const [photos, setPhotos] = useState<UserPhoto[]>([]);

当相机完成拍摄照片后,从 Capacitor 返回的 Photo 将存储在 photo 变量中。我们希望创建一个新的照片对象并将其添加到照片状态数组中。我们确保不会意外地修改当前照片数组,而是创建一个新的数组,然后调用 setPhotos 将数组存储到状态中。更新 takePhoto 方法并在 getPhoto 调用之后添加以下代码

const fileName = Date.now() + '.jpeg';
const newPhotos = [
{
filepath: fileName,
webviewPath: photo.webPath,
},
...photos,
];
setPhotos(newPhotos);

接下来,让我们从我们的钩子中公开照片数组。更新 return 语句以包含照片

return {
photos,
takePhoto,
};

然后回到 Tab2 组件,获取对照片的访问权限

const { photos, takePhoto } = usePhotoGallery();

将照片存储到主数组后,我们就可以在屏幕上显示图像。添加一个 网格组件 ,以便在将照片添加到图库时每张照片都能很好地显示,并在照片数组中循环遍历每张照片,为每张照片添加一个图像组件 (<IonImg>) 。将 src (源)指向照片的路径

<IonContent>
<IonGrid>
<IonRow>
{photos.map((photo, index) => (
<IonCol size="6" key={photo.filepath}>
<IonImg src={photo.webviewPath} />
</IonCol>
))}
</IonRow>
</IonGrid>
<!-- <IonFab> markup -->
</IonContent>

保存所有文件。在 Web 浏览器中,单击“相机”按钮并拍摄另一张照片。这一次,照片将显示在“照片图库”中!

接下来,我们将添加对将照片保存到文件系统的支持,以便稍后可以检索和显示它们。