capacitor-camera-multicapture 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CameraMultiCapture.podspec +17 -0
- package/LICENSE +21 -0
- package/Package.swift +28 -0
- package/README.md +551 -0
- package/android/build.gradle +69 -0
- package/android/src/main/AndroidManifest.xml +6 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/CameraConfig.java +45 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/CameraConfigMapper.java +98 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/CameraMultiCapture.java +10 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/CameraMultiCapturePlugin.java +1340 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/ExifWrapper.java +108 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/GenericUploadWorker.java +173 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/ImageUtils.java +215 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/PluginVersion.java +6 -0
- package/android/src/main/java/dev/hemang/cameramulticapture/ThumbnailGenerator.java +48 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/esm/controllers/camera-controller.d.ts +127 -0
- package/dist/esm/controllers/camera-controller.js +388 -0
- package/dist/esm/controllers/camera-controller.js.map +1 -0
- package/dist/esm/controllers/gallery-controller.d.ts +66 -0
- package/dist/esm/controllers/gallery-controller.js +333 -0
- package/dist/esm/controllers/gallery-controller.js.map +1 -0
- package/dist/esm/definitions.d.ts +372 -0
- package/dist/esm/definitions.js +6 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/overlay-manager.d.ts +124 -0
- package/dist/esm/overlay-manager.js +732 -0
- package/dist/esm/overlay-manager.js.map +1 -0
- package/dist/esm/overlay.d.ts +2 -0
- package/dist/esm/overlay.js +39 -0
- package/dist/esm/overlay.js.map +1 -0
- package/dist/esm/registration.d.ts +5 -0
- package/dist/esm/registration.js +8 -0
- package/dist/esm/registration.js.map +1 -0
- package/dist/esm/types/ui-types.d.ts +78 -0
- package/dist/esm/types/ui-types.js +2 -0
- package/dist/esm/types/ui-types.js.map +1 -0
- package/dist/esm/ui/capture-gesture-handler.d.ts +15 -0
- package/dist/esm/ui/capture-gesture-handler.js +87 -0
- package/dist/esm/ui/capture-gesture-handler.js.map +1 -0
- package/dist/esm/ui/default-styles.d.ts +27 -0
- package/dist/esm/ui/default-styles.js +134 -0
- package/dist/esm/ui/default-styles.js.map +1 -0
- package/dist/esm/ui/image-editor.d.ts +10 -0
- package/dist/esm/ui/image-editor.js +103 -0
- package/dist/esm/ui/image-editor.js.map +1 -0
- package/dist/esm/ui/layout-manager.d.ts +42 -0
- package/dist/esm/ui/layout-manager.js +199 -0
- package/dist/esm/ui/layout-manager.js.map +1 -0
- package/dist/esm/ui/media-viewer.d.ts +2 -0
- package/dist/esm/ui/media-viewer.js +267 -0
- package/dist/esm/ui/media-viewer.js.map +1 -0
- package/dist/esm/ui/pinch-zoom-handler.d.ts +37 -0
- package/dist/esm/ui/pinch-zoom-handler.js +118 -0
- package/dist/esm/ui/pinch-zoom-handler.js.map +1 -0
- package/dist/esm/ui/ui-factory.d.ts +39 -0
- package/dist/esm/ui/ui-factory.js +272 -0
- package/dist/esm/ui/ui-factory.js.map +1 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/esm/web.d.ts +69 -0
- package/dist/esm/web.js +122 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +6274 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +6276 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/CameraMultiCapturePlugin/CameraMultiCapture.swift +8 -0
- package/ios/Sources/CameraMultiCapturePlugin/CameraMultiCapturePlugin.swift +1551 -0
- package/ios/Sources/CameraMultiCapturePlugin/PluginVersion.swift +2 -0
- package/ios/Tests/CameraMultiCapturePluginTests/CameraMultiCapturePluginTests.swift +15 -0
- package/package.json +93 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = 'CameraMultiCapture'
|
|
7
|
+
s.version = package['version']
|
|
8
|
+
s.summary = package['description']
|
|
9
|
+
s.license = package['license']
|
|
10
|
+
s.homepage = package['repository']['url']
|
|
11
|
+
s.author = package['author']
|
|
12
|
+
s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
|
|
13
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
14
|
+
s.ios.deployment_target = '14.0'
|
|
15
|
+
s.dependency 'Capacitor'
|
|
16
|
+
s.swift_version = '5.1'
|
|
17
|
+
end
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Hemang Kumar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/Package.swift
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "CameraMultiCapture",
|
|
6
|
+
platforms: [.iOS(.v14)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "CameraMultiCapture",
|
|
10
|
+
targets: ["CameraMultiCapturePlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "CameraMultiCapturePlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Sources/CameraMultiCapturePlugin"),
|
|
23
|
+
.testTarget(
|
|
24
|
+
name: "CameraMultiCapturePluginTests",
|
|
25
|
+
dependencies: ["CameraMultiCapturePlugin"],
|
|
26
|
+
path: "ios/Tests/CameraMultiCapturePluginTests")
|
|
27
|
+
]
|
|
28
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
# capacitor-camera-multicapture
|
|
2
|
+
|
|
3
|
+
Capacitor plugin that lets the user capture multiple photos and videos with a customizable UI overlay in a single camera session. Includes built-in image annotation powered by marker.js 2.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install capacitor-camera-multicapture
|
|
9
|
+
npx cap sync
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
13
|
+
|
|
14
|
+
### iOS (Info.plist)
|
|
15
|
+
|
|
16
|
+
Add the following permissions to your iOS app's `Info.plist` file:
|
|
17
|
+
|
|
18
|
+
```xml
|
|
19
|
+
<key>NSCameraUsageDescription</key>
|
|
20
|
+
<string>This app needs access to camera to capture photos</string>
|
|
21
|
+
<key>NSPhotoLibraryUsageDescription</key>
|
|
22
|
+
<string>This app needs access to photo library to save captured images</string>
|
|
23
|
+
<key>NSPhotoLibraryAddUsageDescription</key>
|
|
24
|
+
<string>This app needs access to photo library to save captured images</string>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Android (AndroidManifest.xml)
|
|
28
|
+
|
|
29
|
+
The plugin automatically adds the necessary permissions to your Android app. However, if you need to declare them explicitly, add these to your `android/app/src/main/AndroidManifest.xml`:
|
|
30
|
+
|
|
31
|
+
```xml
|
|
32
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
33
|
+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
|
34
|
+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Permission Handling
|
|
38
|
+
|
|
39
|
+
Before using the camera, check and request permissions:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { CameraMultiCapture } from 'capacitor-camera-multicapture';
|
|
43
|
+
|
|
44
|
+
// Check current permissions
|
|
45
|
+
const permissions = await CameraMultiCapture.checkPermissions();
|
|
46
|
+
|
|
47
|
+
if (permissions.camera !== 'granted' || permissions.photos !== 'granted') {
|
|
48
|
+
// Request permissions
|
|
49
|
+
const result = await CameraMultiCapture.requestPermissions();
|
|
50
|
+
|
|
51
|
+
if (result.camera !== 'granted') {
|
|
52
|
+
console.error('Camera permission denied');
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Now you can safely use the camera
|
|
58
|
+
const cameraResult = await CameraMultiCapture.start(options);
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Demo
|
|
62
|
+
|
|
63
|
+
https://github.com/hemangsk/capacitor-multi-preview-demo
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { initialize, CameraOverlayResult } from 'capacitor-camera-multicapture';
|
|
69
|
+
|
|
70
|
+
const result = await initialize({
|
|
71
|
+
containerId: 'camera-overlay',
|
|
72
|
+
quality: 90,
|
|
73
|
+
thumbnailStyle: {
|
|
74
|
+
width: '100px',
|
|
75
|
+
height: '100px'
|
|
76
|
+
},
|
|
77
|
+
|
|
78
|
+
/** more options */
|
|
79
|
+
}).then((result: CameraOverlayResult) => {
|
|
80
|
+
if (result.cancelled) {
|
|
81
|
+
console.log('User cancelled the camera overlay');
|
|
82
|
+
} else {
|
|
83
|
+
console.log('Captured images:', result.images);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// normally you'd want go back to previous screen
|
|
87
|
+
|
|
88
|
+
// this.navCtrl.pop();
|
|
89
|
+
// this.navCtrl.navigateBack();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Single capture mode example - returns immediately after one photo
|
|
93
|
+
const singleResult = await initialize({
|
|
94
|
+
containerId: 'camera-overlay',
|
|
95
|
+
quality: 90,
|
|
96
|
+
maxCaptures: 1 // Automatically returns after capturing one image
|
|
97
|
+
}).then((result: CameraOverlayResult) => {
|
|
98
|
+
if (!result.cancelled && result.images.length > 0) {
|
|
99
|
+
console.log('Single image captured:', result.images[0]);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<div id="camera-overlay"></div>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```css
|
|
109
|
+
#camera-overlay {
|
|
110
|
+
width: 100%; // or any other value for custom container
|
|
111
|
+
height: 100%;
|
|
112
|
+
|
|
113
|
+
background-color: transparent !important;
|
|
114
|
+
--background: transparent !important;
|
|
115
|
+
--ion-background-color: transparent !important;
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Examples
|
|
120
|
+
|
|
121
|
+
#### Single Capture Mode
|
|
122
|
+
|
|
123
|
+
```typescript
|
|
124
|
+
// Capture only one image and return immediately
|
|
125
|
+
const result = await initialize({
|
|
126
|
+
maxCaptures: 1, // Single capture mode
|
|
127
|
+
containerId: 'camera-container',
|
|
128
|
+
quality: 90
|
|
129
|
+
});
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Video Recording (Tap & Long-Press)
|
|
133
|
+
|
|
134
|
+
The capture button supports dual gestures: a quick tap captures a photo, and a long-press starts video recording. During recording a pulsing indicator with an elapsed timer is shown, and the capture button glows red.
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
const result = await initialize({
|
|
138
|
+
containerId: 'camera-container',
|
|
139
|
+
quality: 90,
|
|
140
|
+
maxRecordingDuration: 30, // seconds; auto-stops when reached
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// result.images – captured photos
|
|
144
|
+
// result.videos – captured videos (uri, thumbnail, duration)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Videos appear as thumbnails with a play badge and duration label. Tapping a video thumbnail opens a fullscreen preview.
|
|
148
|
+
|
|
149
|
+
#### Image Annotation (marker.js 2)
|
|
150
|
+
|
|
151
|
+
After capturing photos you can annotate them directly in the camera session. Tap a thumbnail to open the fullscreen preview, then tap the edit (pencil) icon to launch the marker.js 2 editor.
|
|
152
|
+
|
|
153
|
+
The editor supports freehand drawing, arrows, text, callouts, and more. Annotations are non-destructive — editor state is preserved so you can re-open and continue editing. On save the annotated image replaces the original in the gallery.
|
|
154
|
+
|
|
155
|
+
#### Smart Zoom with Physical Camera Switching
|
|
156
|
+
|
|
157
|
+
The plugin automatically detects available physical cameras (ultrawide, wide, telephoto) and displays appropriate zoom buttons. The system seamlessly switches between physical cameras when you select certain zoom levels.
|
|
158
|
+
|
|
159
|
+
#### Button Opacity and Shot Counter
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Semi-transparent buttons with shot counter
|
|
163
|
+
const result = await initialize({
|
|
164
|
+
containerId: 'camera-container',
|
|
165
|
+
quality: 90,
|
|
166
|
+
showShotCounter: true, // Display shot count
|
|
167
|
+
buttons: {
|
|
168
|
+
capture: {
|
|
169
|
+
style: {
|
|
170
|
+
backgroundColor: '#ffffff',
|
|
171
|
+
opacity: 0.8 // 80% opacity
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
done: {
|
|
175
|
+
style: {
|
|
176
|
+
backgroundColor: '#28a745',
|
|
177
|
+
opacity: 0.9 // 90% opacity
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### Flash Auto Mode
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
// Enable flash auto mode
|
|
188
|
+
const result = await initialize({
|
|
189
|
+
containerId: 'camera-container',
|
|
190
|
+
flashAutoModeEnabled: true, // Allow auto flash mode
|
|
191
|
+
flash: 'auto' // Start with auto flash
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### Pinch-to-Zoom with Zoom Button Sync
|
|
196
|
+
|
|
197
|
+
The overlay supports a JavaScript-based pinch-to-zoom gesture on both Android and iOS.
|
|
198
|
+
|
|
199
|
+
When enabled:
|
|
200
|
+
|
|
201
|
+
- Users can pinch in/out anywhere on the camera preview.
|
|
202
|
+
- The current zoom level is clamped to the device’s supported zoom range.
|
|
203
|
+
- Zoom buttons (e.g. 0.7x, 1x, 2x) stay in sync with the active zoom level.
|
|
204
|
+
- If `lockToNearestStep` is `true`, the zoom snaps to the nearest preset level when the pinch ends.
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
|
|
208
|
+
import { initialize, CameraOverlayResult } from "capacitor-camera-multicapture";
|
|
209
|
+
const result: CameraOverlayResult = await initialize({
|
|
210
|
+
containerId: "camera-container",
|
|
211
|
+
quality: 90,
|
|
212
|
+
// Enable JS pinch-to-zoom
|
|
213
|
+
pinchToZoom: {
|
|
214
|
+
enabled: true,
|
|
215
|
+
lockToNearestStep: true, // Snap to nearest preset (e.g. 0.7x, 1x, 2x)
|
|
216
|
+
},
|
|
217
|
+
buttons: {
|
|
218
|
+
// Optional: smart zoom buttons that are kept in sync with pinch
|
|
219
|
+
zoom: {
|
|
220
|
+
levels: [0.7, 1, 2, 3], // Example zoom steps; plugin may override with device-specific smart levels
|
|
221
|
+
style: {
|
|
222
|
+
radius: 30,
|
|
223
|
+
backgroundColor: "rgba(0,0,0,0.5)",
|
|
224
|
+
color: "#ffffff",
|
|
225
|
+
padding: "10px",
|
|
226
|
+
size: 24,
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
**Notes:**
|
|
233
|
+
|
|
234
|
+
- Pinch handling is implemented entirely in the overlay layer (JavaScript), independent of native gesture recognizers.
|
|
235
|
+
- The plugin still uses native camera APIs (CameraX / AVFoundation) for the actual zoom, but all gesture detection runs on the web side.
|
|
236
|
+
- If `pinchToZoom` is omitted or `enabled` is `false`, pinch gestures are ignored and only the zoom buttons are used.
|
|
237
|
+
|
|
238
|
+
#### Advanced Button Styling with Box Shadows and Filters
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
// Enhanced button styling with shadows and filters
|
|
242
|
+
const result = await initialize({
|
|
243
|
+
containerId: 'camera-container',
|
|
244
|
+
quality: 90,
|
|
245
|
+
buttons: {
|
|
246
|
+
capture: {
|
|
247
|
+
style: {
|
|
248
|
+
backgroundColor: '#ffffff',
|
|
249
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1)',
|
|
250
|
+
filter: 'brightness(1.1)'
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
done: {
|
|
254
|
+
style: {
|
|
255
|
+
backgroundColor: '#28a745',
|
|
256
|
+
boxShadow: '0 2px 8px rgba(40, 167, 69, 0.3)',
|
|
257
|
+
filter: 'saturate(1.2)'
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
cancel: {
|
|
261
|
+
style: {
|
|
262
|
+
backgroundColor: '#dc3545',
|
|
263
|
+
boxShadow: '0 2px 8px rgba(220, 53, 69, 0.3)',
|
|
264
|
+
filter: 'contrast(1.1)'
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
switchCamera: {
|
|
268
|
+
style: {
|
|
269
|
+
backgroundColor: 'rgba(0,0,0,0.5)',
|
|
270
|
+
boxShadow: '0 2px 6px rgba(0, 0, 0, 0.3)',
|
|
271
|
+
filter: 'blur(0.5px) brightness(1.1)'
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Available Filter Effects:**
|
|
279
|
+
- `blur(2px)` - Blur effect
|
|
280
|
+
- `brightness(1.2)` - Brightness adjustment (1.0 = normal)
|
|
281
|
+
- `contrast(1.5)` - Contrast enhancement
|
|
282
|
+
- `grayscale(100%)` - Grayscale effect
|
|
283
|
+
- `saturate(1.3)` - Saturation boost
|
|
284
|
+
- `hue-rotate(90deg)` - Hue rotation
|
|
285
|
+
- `drop-shadow(0 2px 4px rgba(0,0,0,0.2))` - Drop shadow alternative
|
|
286
|
+
- Multiple filters: `brightness(1.1) contrast(1.2) saturate(1.3)`
|
|
287
|
+
|
|
288
|
+
**Box Shadow Examples:**
|
|
289
|
+
- Subtle: `0 2px 4px rgba(0, 0, 0, 0.1)`
|
|
290
|
+
- Prominent: `0 4px 12px rgba(0, 0, 0, 0.15), 0 2px 4px rgba(0, 0, 0, 0.1)`
|
|
291
|
+
- Colored: `0 4px 12px rgba(59, 130, 246, 0.4)`
|
|
292
|
+
- Inset: `inset 0 1px 0 rgba(255, 255, 255, 0.2)`
|
|
293
|
+
|
|
294
|
+
## API
|
|
295
|
+
|
|
296
|
+
<docgen-index>
|
|
297
|
+
|
|
298
|
+
* [`start(...)`](#start)
|
|
299
|
+
* [`capture()`](#capture)
|
|
300
|
+
* [`stop()`](#stop)
|
|
301
|
+
* [`switchCamera()`](#switchcamera)
|
|
302
|
+
* [`setZoom(...)`](#setzoom)
|
|
303
|
+
* [`updatePreviewRect(...)`](#updatepreviewrect)
|
|
304
|
+
* [`checkPermissions()`](#checkpermissions)
|
|
305
|
+
* [`requestPermissions()`](#requestpermissions)
|
|
306
|
+
* [Interfaces](#interfaces)
|
|
307
|
+
* [Type Aliases](#type-aliases)
|
|
308
|
+
|
|
309
|
+
</docgen-index>
|
|
310
|
+
|
|
311
|
+
<docgen-api>
|
|
312
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
313
|
+
|
|
314
|
+
### start(...)
|
|
315
|
+
|
|
316
|
+
```typescript
|
|
317
|
+
start(options?: CameraOverlayOptions | undefined) => Promise<CameraOverlayResult>
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Starts the camera overlay session.
|
|
321
|
+
|
|
322
|
+
| Param | Type |
|
|
323
|
+
| ------------- | --------------------------------------------------------------------- |
|
|
324
|
+
| **`options`** | <code><a href="#cameraoverlayoptions">CameraOverlayOptions</a></code> |
|
|
325
|
+
|
|
326
|
+
**Returns:** <code>Promise<<a href="#cameraoverlayresult">CameraOverlayResult</a>></code>
|
|
327
|
+
|
|
328
|
+
--------------------
|
|
329
|
+
|
|
330
|
+
|
|
331
|
+
### capture()
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
capture() => Promise<{ value: CameraImageData; }>
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
Captures a single frame.
|
|
338
|
+
|
|
339
|
+
**Returns:** <code>Promise<{ value: <a href="#cameraimagedata">CameraImageData</a>; }></code>
|
|
340
|
+
|
|
341
|
+
--------------------
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
### stop()
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
stop() => Promise<void>
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
Stops and tears down the camera session.
|
|
351
|
+
|
|
352
|
+
--------------------
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
### switchCamera()
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
switchCamera() => Promise<void>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Switches the camera between front and back.
|
|
362
|
+
|
|
363
|
+
--------------------
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
### setZoom(...)
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
setZoom(options: { zoom: number; }) => Promise<void>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Sets the zoom level of the camera.
|
|
373
|
+
|
|
374
|
+
| Param | Type |
|
|
375
|
+
| ------------- | ------------------------------ |
|
|
376
|
+
| **`options`** | <code>{ zoom: number; }</code> |
|
|
377
|
+
|
|
378
|
+
--------------------
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
### updatePreviewRect(...)
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
updatePreviewRect(options: CameraPreviewRect) => Promise<void>
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
Updates the camera preview rectangle dimensions.
|
|
388
|
+
Call this when the container size changes (e.g., orientation change).
|
|
389
|
+
|
|
390
|
+
| Param | Type |
|
|
391
|
+
| ------------- | --------------------------------------------------------------- |
|
|
392
|
+
| **`options`** | <code><a href="#camerapreviewrect">CameraPreviewRect</a></code> |
|
|
393
|
+
|
|
394
|
+
--------------------
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
### checkPermissions()
|
|
398
|
+
|
|
399
|
+
```typescript
|
|
400
|
+
checkPermissions() => Promise<PermissionStatus>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Check camera and photo library permissions
|
|
404
|
+
|
|
405
|
+
**Returns:** <code>Promise<<a href="#permissionstatus">PermissionStatus</a>></code>
|
|
406
|
+
|
|
407
|
+
--------------------
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
### requestPermissions()
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
requestPermissions() => Promise<PermissionStatus>
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
Request camera and photo library permissions
|
|
417
|
+
|
|
418
|
+
**Returns:** <code>Promise<<a href="#permissionstatus">PermissionStatus</a>></code>
|
|
419
|
+
|
|
420
|
+
--------------------
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
### Interfaces
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
#### CameraOverlayResult
|
|
427
|
+
|
|
428
|
+
| Prop | Type |
|
|
429
|
+
| --------------- | ------------------------------ |
|
|
430
|
+
| **`images`** | <code>CameraImageData[]</code> |
|
|
431
|
+
| **`videos`** | <code>CameraVideoData[]</code> |
|
|
432
|
+
| **`cancelled`** | <code>boolean</code> |
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
#### PermissionStatus
|
|
436
|
+
|
|
437
|
+
Permission status for the camera multi-capture plugin
|
|
438
|
+
|
|
439
|
+
| Prop | Type |
|
|
440
|
+
| ------------ | ----------------------------------------------------------- |
|
|
441
|
+
| **`camera`** | <code>'granted' \| 'denied' \| 'prompt'</code> |
|
|
442
|
+
| **`photos`** | <code>'granted' \| 'denied' \| 'prompt'</code> |
|
|
443
|
+
|
|
444
|
+
|
|
445
|
+
#### CameraImageData
|
|
446
|
+
|
|
447
|
+
Structure for image data returned by the camera
|
|
448
|
+
|
|
449
|
+
| Prop | Type |
|
|
450
|
+
| ------------ | ------------------- |
|
|
451
|
+
| **`uri`** | <code>string</code> |
|
|
452
|
+
| **`base64`** | <code>string</code> |
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
#### CameraOverlayOptions
|
|
456
|
+
|
|
457
|
+
| Prop | Type |
|
|
458
|
+
| -------------------- | --------------------------------------------------------------------- |
|
|
459
|
+
| **`buttons`** | <code><a href="#cameraoverlaybuttons">CameraOverlayButtons</a></code> |
|
|
460
|
+
| **`thumbnailStyle`** | <code>{ width: string; height: string; }</code> |
|
|
461
|
+
| **`quality`** | <code>number</code> |
|
|
462
|
+
| **`containerId`** | <code>string</code> |
|
|
463
|
+
| **`previewRect`** | <code><a href="#camerapreviewrect">CameraPreviewRect</a></code> |
|
|
464
|
+
| **`direction`** | <code><a href="#cameradirection">CameraDirection</a></code> |
|
|
465
|
+
| **`captureMode`** | <code><a href="#capturemode">CaptureMode</a></code> |
|
|
466
|
+
| **`resolution`** | <code><a href="#resolution">Resolution</a></code> |
|
|
467
|
+
| **`zoom`** | <code>number</code> |
|
|
468
|
+
| **`autoFocus`** | <code>boolean</code> |
|
|
469
|
+
| **`maxCaptures`** | <code>number</code> |
|
|
470
|
+
| **`flashAutoModeEnabled`** | <code>boolean</code> |
|
|
471
|
+
| **`showShotCounter`** | <code>boolean</code> |
|
|
472
|
+
| **`pinchToZoom`** | <code>{ enabled?: boolean; lockToNearestStep?: boolean; }</code> |
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
#### CameraOverlayButtons
|
|
476
|
+
|
|
477
|
+
| Prop | Type |
|
|
478
|
+
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
479
|
+
| **`capture`** | <code>{ icon?: string; style?: <a href="#buttonstyle">ButtonStyle</a>; position?: 'center' \| 'left' \| 'right' \| 'custom'; }</code> |
|
|
480
|
+
| **`done`** | <code>{ icon?: string; style?: <a href="#buttonstyle">ButtonStyle</a>; text?: string; }</code> |
|
|
481
|
+
| **`cancel`** | <code>{ icon?: string; style?: <a href="#buttonstyle">ButtonStyle</a>; text?: string; }</code> |
|
|
482
|
+
| **`switchCamera`** | <code>{ icon?: string; style?: <a href="#buttonstyle">ButtonStyle</a>; position?: 'custom' \| 'topLeft' \| 'topRight'; }</code> |
|
|
483
|
+
| **`zoom`** | <code>{ icon?: string; style?: <a href="#buttonstyle">ButtonStyle</a>; levels?: number[]; }</code> |
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
#### ButtonStyle
|
|
487
|
+
|
|
488
|
+
| Prop | Type |
|
|
489
|
+
| --------------------- | ------------------- |
|
|
490
|
+
| **`radius`** | <code>number</code> |
|
|
491
|
+
| **`color`** | <code>string</code> |
|
|
492
|
+
| **`backgroundColor`** | <code>string</code> |
|
|
493
|
+
| **`padding`** | <code>string</code> |
|
|
494
|
+
| **`size`** | <code>number</code> |
|
|
495
|
+
| **`activeColor`** | <code>string</code> |
|
|
496
|
+
| **`border`** | <code>string</code> |
|
|
497
|
+
| **`opacity`** | <code>number</code> |
|
|
498
|
+
| **`boxShadow`** | <code>string</code> |
|
|
499
|
+
| **`filter`** | <code>string</code> |
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
#### CameraPreviewRect
|
|
503
|
+
|
|
504
|
+
| Prop | Type |
|
|
505
|
+
| ------------ | ------------------- |
|
|
506
|
+
| **`width`** | <code>number</code> |
|
|
507
|
+
| **`height`** | <code>number</code> |
|
|
508
|
+
| **`x`** | <code>number</code> |
|
|
509
|
+
| **`y`** | <code>number</code> |
|
|
510
|
+
|
|
511
|
+
|
|
512
|
+
#### Resolution
|
|
513
|
+
|
|
514
|
+
| Prop | Type |
|
|
515
|
+
| ------------ | ------------------- |
|
|
516
|
+
| **`width`** | <code>number</code> |
|
|
517
|
+
| **`height`** | <code>number</code> |
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
### Type Aliases
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
#### ButtonStyle
|
|
524
|
+
|
|
525
|
+
Defines the style properties for camera buttons
|
|
526
|
+
|
|
527
|
+
<code>OriginalButtonStyle</code>
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
#### CameraDirection
|
|
531
|
+
|
|
532
|
+
<code>'front' | 'back'</code>
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
#### CaptureMode
|
|
536
|
+
|
|
537
|
+
<code>'minimizeLatency' | 'maxQuality'</code>
|
|
538
|
+
|
|
539
|
+
</docgen-api>
|
|
540
|
+
|
|
541
|
+
|
|
542
|
+
## License
|
|
543
|
+
|
|
544
|
+
MIT
|
|
545
|
+
|
|
546
|
+
## Acknowledgements
|
|
547
|
+
|
|
548
|
+
- 's comment at https://github.com/ionic-team/capacitor-plugins/issues/1616#issuecomment-1912900318
|
|
549
|
+
- Capawesome plugins repository for formatting scripts and documentation setup.
|
|
550
|
+
- [marker.js 2](https://markerjs.com/) for the image annotation engine.
|
|
551
|
+
- [bigger-picture](https://github.com/henrygd/bigger-picture) for fullscreen media preview.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
google()
|
|
11
|
+
mavenCentral()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.7.3'
|
|
15
|
+
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
apply plugin: 'com.android.library'
|
|
20
|
+
|
|
21
|
+
android {
|
|
22
|
+
namespace "dev.hemang.cameramulticapture"
|
|
23
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
24
|
+
defaultConfig {
|
|
25
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
26
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
27
|
+
versionCode 1
|
|
28
|
+
versionName "1.0"
|
|
29
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
30
|
+
}
|
|
31
|
+
buildTypes {
|
|
32
|
+
release {
|
|
33
|
+
minifyEnabled false
|
|
34
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
lintOptions {
|
|
38
|
+
abortOnError false
|
|
39
|
+
}
|
|
40
|
+
compileOptions {
|
|
41
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
42
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
repositories {
|
|
47
|
+
google()
|
|
48
|
+
mavenCentral()
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
dependencies {
|
|
53
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
54
|
+
implementation project(':capacitor-android')
|
|
55
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
56
|
+
testImplementation "junit:junit:$junitVersion"
|
|
57
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
58
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
59
|
+
|
|
60
|
+
implementation "androidx.camera:camera-core:1.4.2"
|
|
61
|
+
implementation "androidx.camera:camera-camera2:1.4.2"
|
|
62
|
+
implementation "androidx.camera:camera-lifecycle:1.4.2"
|
|
63
|
+
implementation "androidx.camera:camera-view:1.4.2"
|
|
64
|
+
implementation "androidx.camera:camera-video:1.4.2"
|
|
65
|
+
implementation "androidx.camera:camera-extensions:1.4.2"
|
|
66
|
+
implementation 'androidx.work:work-runtime:2.8.1'
|
|
67
|
+
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
|
68
|
+
api 'androidx.exifinterface:exifinterface:1.3.7'
|
|
69
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
|
+
<uses-permission android:name="android.permission.INTERNET" />
|
|
3
|
+
<uses-permission android:name="android.permission.CAMERA" />
|
|
4
|
+
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
|
5
|
+
<uses-feature android:name="android.hardware.camera" android:required="true" />
|
|
6
|
+
</manifest>
|