Skip to main content

用相机拍照

现在进入有趣的部分——使用 Capacitor Camera API 为设备的摄像头添加拍照功能。我们将从为网页构建开始,然后进行一些小调整,使其在移动设备(iOS 和 Android)上也能运行。

🌐 Now for the fun part - adding the ability to take photos with the device’s camera using the Capacitor Camera API. We’ll begin with building it for the web, then make some small tweaks to make it work on mobile (iOS and Android).

照片服务

🌐 Photo Service

所有电容器逻辑(相机使用和其他原生功能)将封装在一个服务类中。使用 ionic generate 命令创建 PhotoService

🌐 All Capacitor logic (Camera usage and other native features) will be encapsulated in a service class. Create PhotoService using the ionic generate command:

ionic g service services/photo.service

打开新的 services/photo.service.ts 文件,让我们添加将为相机功能提供支持的逻辑。首先,导入 Capacitor 依赖,并获取对 CameraFilesystemStorage 插件的引用:

🌐 Open the new services/photo.service.ts file, and let’s add the logic that will power the camera functionality. First, import Capacitor dependencies and get references to the Camera, Filesystem, and Storage plugins:

import { Injectable } from '@angular/core';
// CHANGE: Add the following import
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';

@Injectable({
providedIn: 'root',
})
export class PhotoService {}

接下来,定义一个新的类方法 addNewToGallery(),它将包含拍摄设备照片并将其保存到文件系统的核心逻辑。让我们从打开设备相机开始。

🌐 Next, define a new class method, addNewToGallery(), that will contain the core logic to take a device photo and save it to the filesystem. Let’s start by opening the device camera.

import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';

@Injectable({
providedIn: 'root',
})
export class PhotoService {
// CHANGE: Add the gallery method
public async addNewToGallery() {
// Take a photo
const capturedPhoto = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100,
});
}
}

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

🌐 Notice the magic here: there's no platform-specific code (web, iOS, or Android)! The Capacitor Camera plugin abstracts that away for us, leaving just one method call - Camera.getPhoto() - that will open up the device's camera and allow us to take photos.

接下来,在 tab2.page.ts 中导入 PhotoService 类,并添加一个方法来调用它的 addNewToGallery 方法。

🌐 Next, in tab2.page.ts, import the PhotoService class and add a method to call its addNewToGallery method.

import { Component } from '@angular/core';
// CHANGE: Import the PhotoService
import { PhotoService } from '../services/photo.service';

@Component({
selector: 'app-tab2',
templateUrl: 'tab2.page.html',
styleUrls: ['tab2.page.scss'],
standalone: false,
})
export class Tab2Page {
// CHANGE: Update constructor to include `photoService`
constructor(public photoService: PhotoService) {}

// CHANGE: Add `addNewToGallery()` method
addPhotoToGallery() {
this.photoService.addNewToGallery();
}
}

然后,打开 tab2.page.html 并在点击/轻触 FAB 时调用 addPhotoToGallery() 方法:

🌐 Then, open tab2.page.html and call the addPhotoToGallery() method when the FAB is tapped/clicked:

<ion-header [translucent]="true">
<ion-toolbar>
<ion-title> Photo Gallery </ion-title>
</ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Photo Gallery</ion-title>
</ion-toolbar>
</ion-header>

<ion-fab vertical="bottom" horizontal="center" slot="fixed">

<ion-fab-button (click)="addPhotoToGallery()">
<ion-icon name="camera"></ion-icon>
</ion-fab-button>
</ion-fab>
</ion-content>

如果开发服务器还没有运行,请通过在浏览器中运行 ionic serve 来重新启动。在照片图库标签上,点击相机按钮。如果你的电脑有任何类型的网络摄像头,会出现一个模态窗口。拍一张自拍!

🌐 If it's not running already, restart the development server in your browser by running ionic serve. On the Photo Gallery tab, click the Camera button. If your computer has a webcam of any sort, a modal window appears. Take a selfie!

A photo gallery app displaying a webcam selfie.

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

🌐 (Your selfie is probably much better than mine)

拍照后,它会立即消失。我们需要在应用内显示它,并保存以供将来访问。

🌐 After taking a photo, it disappears right away. We need to display it within our app and save it for future access.

显示照片

🌐 Displaying Photos

要为我们的照片元数据定义数据结构,创建一个名为 UserPhoto 的新接口。在 photo.service.ts 文件的最底部添加此接口,紧接在 PhotoService 类定义之后:

🌐 To define the data structure for our photo metadata, create a new interface named UserPhoto. Add this interface at the very bottom of the photo.service.ts file, immediately after the PhotoService class definition:

export class PhotoService {
// ...existing code...
}

// CHANGE: Add the `UserPhoto` interface
export interface UserPhoto {
filepath: string;
webviewPath?: string;
}

addNewToGallery() 方法上方,定义一个 UserPhoto 数组,用于存储用相机拍摄的每张照片的引用。

🌐 Above the addNewToGallery() method, define an array of UserPhoto, which will contain a reference to each photo captured with the Camera.

export class PhotoService {
// CHANGE: Add the `photos` array
public photos: UserPhoto[] = [];

public async addNewToGallery() {
// ...existing code...
}
}

addNewToGallery 方法中,将新拍摄的照片添加到 photos 数组的开头。

🌐 Over in the addNewToGallery method, add the newly captured photo to the beginning of the photos array.

// CHANGE: Update `addNewToGallery()` method
public async addNewToGallery() {
// Take a photo
const capturedPhoto = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100
});

// CHANGE: Add the new photo to the photos array
this.photos.unshift({
filepath: "soon...",
webviewPath: capturedPhoto.webPath!
});
}

photo.service.ts 现在应该看起来像这样:

import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';

@Injectable({
providedIn: 'root',
})
export class PhotoService {
public photos: UserPhoto[] = [];

public async addNewToGallery() {
// Take a photo
const capturedPhoto = await Camera.getPhoto({
resultType: CameraResultType.Uri,
source: CameraSource.Camera,
quality: 100,
});

this.photos.unshift({
filepath: 'soon...',
webviewPath: capturedPhoto.webPath!,
});
}
}

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

接下来,切换到 tab2.page.html 以显示图片。我们将添加一个 网格组件 来确保照片在添加到图库时整齐显示。在网格内,循环遍历 PhotoServicephotos 数组中的每张照片。对于每一项,添加一个 图片组件,并将其 src 属性设置为照片的路径。

🌐 Next, switch to tab2.page.html to display the images. We'll add a Grid component to ensure the photos display neatly as they're added to the gallery. Inside the grid, loop through each photo in the PhotoService's photos array. For each item, add an Image component and set its src property to the photo's path.

<ion-header [translucent]="true">
<ion-toolbar>
<ion-title> Photo Gallery </ion-title>
</ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Photo Gallery</ion-title>
</ion-toolbar>
</ion-header>


<ion-grid>
<ion-row>

<ion-col size="6" *ngFor="let photo of photoService.photos; index as position">
<ion-img [src]="photo.webviewPath"></ion-img>
</ion-col>
</ion-row>
</ion-grid>

<ion-fab vertical="bottom" horizontal="center" slot="fixed">
<ion-fab-button (click)="addPhotoToGallery()">
<ion-icon name="camera"></ion-icon>
</ion-fab-button>
</ion-fab>
</ion-content>

在网页浏览器中,点击相机按钮,再拍一张照片。这一次,照片会显示在照片库中!

🌐 Within the web browser, click the camera button and take another photo. This time, the photo is displayed in the Photo Gallery!

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

🌐 Up next, we’ll add support for saving the photos to the filesystem, so they can be retrieved and displayed in our app at a later time.