Capacitor 앱에서 사진을 찍고 편집하려면 @capacitor/camera 8.1 이상: Camera.takePhoto() 카메라를 열어 editable: 'in-app' 촬영 및 편집을 위한 카파시토르 앱에서 사진을 찍고 편집하는 방법 chooseFromGallery() 사진을 찍고 편집하는 방법 @capgo/camera-preview이 안내서에서는 촬영, 편집, 권한, 압축, 메타데이터, 저장, 업로드에 대해 설명합니다. code에 대해 Capacitor 8.
어떤 도구를 선택해야 하나요
| 필요한 | 플러그인 | 왜 |
|---|---|---|
| 시스템 카메라 UI를 사용하여 사진을 찍어보세요 | @capacitor/camera takePhoto |
유지 관리가 필요없는 커스텀 UI가 없으며 모든 장치에서 작동합니다. |
| 사용자가 사진을 잘라거나 회전할 수 있도록 해보세요 | @capacitor/camera editable, editPhoto, editURIPhoto |
iOS와 Android에서 내장된 편집기 |
| 사진 또는 비디오 중 하나 이상을 선택하세요 | @capacitor/camera chooseFromGallery |
Android 사진 선택기와 PHPicker를 사용하여 광범위한 권한 없이 |
| 커스텀 카메라 화면 (Overlay, ID 카드 프레임, 얼굴 안내) | @capgo/camera-preview |
HTML과 JS에서 제어하는 네이티브 미리보기 |
| 자신의 그리드 내에서 전체 사진 라이브러리를 탐색 | @capgo/capacitor-photo-library |
썸네일과 함께 페이지네이션된 라이브러리 접근 |
| HEIC를 축소, 리사이즈 또는 변환 | @capgo/capacitor-file-compressor |
네이티브 인코더, EXIF를 제거 |
| 대형 사진을 신뢰할 수 있는 업로드 | @capgo/capacitor-uploader |
네이티브 배경 업로드와 진행률 |
카메라 플러그인을 설치하고 구성
bun add @capacitor/camera
bunx cap sync
버전 8.1 이상이 있어야 합니다. 이 안내서에 설명된 메소드 (takePhoto, chooseFromGallery, editPhoto, editURIPhoto)는 8.1에서 추가되었으며 CameraErrorCode 8.2 에서. 더 오래된 getPhoto 그리고 pickImages deprecated
iOS
이 키를 추가하세요 ios/App/App/Info.plist. 애플은 모호한 문자열이 있는 빌드에 반대하므로 실제 이유를 설명하세요:
<key>NSCameraUsageDescription</key>
<string>Take a photo for your profile or attach it to a report.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Choose existing photos to attach.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Save photos you take to your library.</string>
Android
촬영 및 앨범 선택에는 권한이 필요하지 않습니다. 플러그인은 시스템 카메라 활동을 시작하고 Android 11 이상의 기기에 있는 Android Photo Picker를 사용합니다. 지원하는 기기에서는 이에 fallback합니다. 더 오래된 기기에 Google Play 서비스를 사용하여 백포트된 픽커를 얻으려면 이 안에 추가하세요 ACTION_OPEN_DOCUMENT 8.2 에서 <application> in AndroidManifest.xmlnamespace를 사용하므로 tools 또한 추가하세요 xmlns:tools="http://schemas.android.com/tools" __CAPGO_KEEP_0__ <manifest> element이 아직 존재하지 않으면 (새로운 Capacitor 프로젝트는) xmlns:android):
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
android:enabled="false"
android:exported="false"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
</intent-filter>
<meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>
Only saveToGallery: true Only
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
저장소 권한이 필요하고, 오래된 안드로이드 버전에서만: READ_MEDIA_IMAGES 추가하지 마세요
앱의 핵심 목적이 갤러리나 편집기라면 제외합니다. 구글 플레이의 사진 및 비디오 권한 정책은 간헐적으로 사진이 필요한 앱이 픽커를 사용해야 하며, 권한을 선언하지 않고 이유를 설명하지 않은 빌드가 거부됩니다.
import { Camera, CameraDirection, CameraErrorCode, EncodingType } from '@capacitor/camera';
export async function takePicture() {
try {
const photo = await Camera.takePhoto({
quality: 85,
targetWidth: 2048,
targetHeight: 2048,
correctOrientation: true,
encodingType: EncodingType.JPEG,
cameraDirection: CameraDirection.Rear, // iOS and web
includeMetadata: true,
});
// webPath works directly in <img src>
document.querySelector<HTMLImageElement>('#preview')!.src = photo.webPath!;
return photo;
} catch (e: any) {
if (e.code === CameraErrorCode.TakePhotoCancelled) return null;
if (e.code === CameraErrorCode.CameraPermissionDenied) {
// show a screen that explains how to enable the camera in Settings
return null;
}
throw e;
}
}
사진 찍기 MediaResult:
uri사진 찍기를 완료하면editURIPhoto.webPath: 원본 사진의 native file URI (웹에서는 사용할 수 없음). Filesystem, 업로더, 또는thumbnail: WebView가 로드할 수 있는 URL. 미리보기 대신 base64를 사용하지 마세요.metadata: native에서 base64로 thumbnail, 웹에서 원본 사진을 로드합니다.includeMetadatatrue.savedwhethersaveToGallerysucceeded.
targetWidth and targetHeight 업로드를 피하기 위해 2048 pixel 이미지를 필요로 할 때 12 MP 사진을 업로드하지 않도록 가장 저렴한 방법입니다.
사진 편집: 자르기 및 회전
촬영 직후 편집
설정 editable promise가 해결되기 전에 사용자가 편집기에서 도착합니다:
const photo = await Camera.takePhoto({
quality: 85,
editable: 'in-app', // 'in-app' | 'external' | 'no'
});
'external' Android에서는 Google Photos와 같은 다른 편집기를 설치하여 이미지에 접근하고, iOS에서는 내장 편집기를 사용합니다. 'in-app'.
기존 사진 편집
선택한 사진이나 이전에 저장한 사진을 편집하려면 URI를 전달하세요.
const edited = await Camera.editURIPhoto({
uri: photo.uri!,
saveToGallery: false,
includeMetadata: false,
});
만약에 canvas 또는 서버 응답에서만 base64 (예를 들어)만 가지고 있다면 사용하세요. editPhoto입력은 raw base64일 때만 사용하세요. data: prefix가 없습니다:
const { outputImage } = await Camera.editPhoto({ inputImage: base64 });
img.src = `data:image/jpeg;base64,${outputImage}`;
웹에서 이 두 가지 방법은 사용할 수 없습니다. 필터, 스티커, 텍스트 또는 자유 형식의 드로잉이 필요하다면 내장 편집기는 충분하지 않습니다. 이미지를 렌더링하고 편집을 적용하려면 canvas를 사용하거나 Cropper.js와 같은 자바스크립트 크로퍼를 사용하세요. fixed aspect ratios (예를 들어, 아바타)에서. <canvas> canvas export ( )는 Blob을 반환하여 직접 업로드할 수 있습니다.canvas.toBlob(cb, 'image/jpeg', 0.85)갤러리에서 사진을 선택하세요.
단일 사진을 선택할 때
import { Camera, MediaTypeSelection } from '@capacitor/camera';
const { results } = await Camera.chooseFromGallery({
mediaType: MediaTypeSelection.Photo,
allowMultipleSelection: true,
limit: 5, // Android 13+ and iOS
quality: 85,
targetWidth: 2048,
targetHeight: 2048,
});
const urls = results.map((r) => r.webPath);
plus를 사용하면 한 번에 선택-잘라내기 기능을 제공합니다. allowMultipleSelection: false plus editable: 'in-app' iOS에서 사용자는 제한된 접근 권한을 부여할 수 있습니다. mediaType: MediaTypeSelection.All __CAPGO_KEEP_0__
__CAPGO_KEEP_0__ pickLimitedLibraryPhotos() 앱에서 사진을 찍고 편집하는 방법 getLimitedLibraryPhotos() 선택을 변경하고 변경할 수 있는 것을 반환합니다. 시스템 픽커를 사용하면 거의 필요하지 않습니다. 선택한 항목은 항상 읽을 수 있습니다.
자신만의 갤러리 그리드 만들기
사용자의 라이브러리를 자신의 UI 내에 표시하는 앱 (사진 인쇄 앱, 백업 앱)에서 사용하세요. @capgo/capacitor-photo-library:
import { PhotoLibrary } from '@capgo/capacitor-photo-library';
const { state } = await PhotoLibrary.requestAuthorization();
if (state === 'authorized' || state === 'limited') {
const { assets, hasMore } = await PhotoLibrary.getLibrary({
limit: 60,
offset: 0,
thumbnailWidth: 256,
thumbnailHeight: 256,
});
// assets[i].thumbnail?.webPath for the grid, getPhotoUrl({ id }) for full size
}
같은 플러그인의 pickMedia() 시스템 픽커를 열고 선택을 캐시에 복사합니다. 두 가지 흐름에 하나의 플러그인을 사용하려면 캐시를 원한다면. Android에서 전체 라이브러리 접근을 요청하기 전에 Google Play 정책을 기억하세요.
커스텀 카메라 화면 만들기
시스템 카메라 UI는 ID 카드 프레임, 문서 윤곽, 브랜드를 표시할 수 없습니다. @capgo/camera-preview 자연 카메라 피드를 렌더링하고 HTML에서 UI를 그립니다:
bun add @capgo/camera-preview
bunx cap sync
import { CameraPreview } from '@capgo/camera-preview';
await CameraPreview.start({
position: 'rear',
toBack: true, // preview behind the WebView
aspectRatio: '4:3',
storeToFile: true, // capture() returns a file path instead of base64
disableAudio: true,
});
await CameraPreview.setFlashMode({ flashMode: 'auto' });
await CameraPreview.setZoom({ level: 2 });
const { value: filePath, exif } = await CameraPreview.capture({ quality: 85 });
await CameraPreview.stop();
그것과 함께 toBack: true, 미리보기는 WebView 뒤에 있으므로 페이지와 모든 부모 요소는 카메라가 활성화된 동안 투명한 배경을 가지고 있어야 합니다. 일반적인 패턴은 camera-active 클래스 body 이것을 설정합니다. background: transparent 을 호출합니다. NSCameraUsageDescription 카메라 권한을 요청하기 위해 CAMERA 을 호출합니다. requestPermissions()스크린이 닫히면 카메라를 해제하기 위해 stop() 을 호출합니다.
이미지를 표시, 압축 및 변환합니다.
Use webPath (or Capacitor.convertFileSrc(path) 이미지를 업로드하기 전에 이미지를 축소하세요: <img> that sets
and hides the rest of the app.
import { FileCompressor } from '@capgo/capacitor-file-compressor';
const { path } = await FileCompressor.compressImage({
path: photo.uri!,
width: 1600, // keeps aspect ratio
quality: 0.75,
mimeType: 'image/jpeg',
});
HEIC 형식의 사진을 iPhone에서 받아 HEIC를 JPEG로 변환하는 것을 지원합니다. 이 변환은 백엔드가 HEIC를 읽을 수 없는 경우에만 수행됩니다. 변환 결과는 임시 디렉토리에 저장되므로, 필요할 경우 이 디렉토리에서 사진을 이동해야 합니다. @capacitor/filesystem 이 사진을 유지하려면 이동하세요.
EXIF 메타데이터 및 위치隐私
With includeMetadata: true, metadata.exif 카메라 롤에서 가져온 사진은 GPS 좌표를 포함할 수 있습니다. 두 가지 규칙을 통해 문제를 피할 수 있습니다:
- 공개되는 사진(프로필 사진, 시장 목록)을 업로드하기 전에 위치 정보를 제거하세요.
@capgo/capacitor-file-compressor압축 과정에서 모든 플랫폼에서 EXIF를 제거합니다. - 필요한 경우 위치 정보(现场 보고서, 검사)를 읽어 압축하기 전에 EXIF에서 읽어 분리된 field로 전송하세요. 그런 다음 App Store의 개인 정보 레이블 및 Play 데이터 안전성 양식에 위치 정보를 공개하세요. iOS 쪽에 대한 개인 정보 매니페스트 가이드를 참조하세요. 앱 스토어의 개인 정보 레이블 및 Play 데이터 안전성 양식에 위치 정보를 공개하세요. 사진을 갤러리나 앱 저장소에 저장하세요.
이
saveToGallery: true 디렉토리 takePhoto 또는 editURIPhoto Live Update saved Cloudflare
import { Filesystem, Directory } from '@capacitor/filesystem';
await Filesystem.copy({
from: photo.uri!,
to: `photos/${Date.now()}.jpg`,
toDirectory: Directory.Data,
});
Capacitor
GitHub
Capgo fetch code FormData API
const blob = await fetch(photo.webPath!).then((r) => r.blob());
const form = new FormData();
form.append('file', blob, 'photo.jpg');
await fetch('https://api.example.com/photos', { method: 'POST', body: form });
SDK
import { Uploader } from '@capgo/capacitor-uploader';
const { id } = await Uploader.startUpload({
filePath: path,
serverUrl: 'https://api.example.com/photos',
method: 'POST',
mimeType: 'image/jpeg',
});
await Uploader.addListener('events', (event) => {
console.log(event.name, event.payload);
});
CLI
- npm
- bun
takePhoto또는chooseFromGallery과editable: 'in-app',targetWidth: 1024,targetHeight: 1024. - 1:1 비율을 보장하기 위해 캔버스에서 사각형으로 잘라야 합니다.
- 압축하기
quality: 0.8및 EXIF를 제거합니다. - 업로드하고, 서버 URL을 보여주고, 로컬 파일을 보여주지 않아야 하므로 아바타가 다시 설치될 때 살아남습니다.
문제 해결
iOS에서 카메라가 열릴 때 앱이 충돌합니다.: 사용 설명 키가 누락되어 있습니다. Info.plist.
Android에서 사진이 회전합니다.: correctOrientation: true (기본값)이며 EXIF 회전을 적용하지 않고 raw 픽셀을 읽지 않도록 하십시오.
Android 기기에서 메모리가 부족한 경우 앱이 사진을 찍은 후 재시작됩니다.: 카메라가 열려 있는 동안 액티비티가 종료될 수 있습니다. appRestoredResult from @capacitor/app 을 사용하여 재시작 후 결과를 복원하세요.
webPath 이미지 로드가 실패합니다.: 사진을 저장한 webPath 을 재사용하세요. uri 을 저장하고 다시 로드하세요. Capacitor.convertFileSrc.
또는 을 저장하고 다시 로드하세요. start() 카메라 프리뷰 화면이 검은색 화면으로 표시됩니다.
: WebView 위에 있는 요소가 배경 색상을 가지고 있거나, : 제거 READ_MEDIA_IMAGES 그리고 READ_MEDIA_VIDEO trừ야, 당신이 당신의 앱이 광범위한 접근이 필요하다고 선언한 경우
스토어 릴리즈 없이 고쳐진 것을 배포
이미지 크기, 압축 수준, 자르기 비율 및 업로드 엔드포인트는 모두 당신의 웹 code 에서 관리됩니다. Capgo Live Update __CAPGO_KEEP_0__ Live Update를 사용하면 사용자별로 변경할 수 있습니다. 하지만 네이티브 변경 사항은 새로운 플러그인과 같은 경우 정기적인 빌드 과정을 거칩니다. iOS 빌드를 맥 없이도 필요하다면 Capgo 빌드 __CAPGO_KEEP_0__ Build