@capgo/camera-preview 7.4.0-beta.1 → 7.4.0-beta.11
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/README.md +195 -31
- package/android/.gradle/8.14.2/checksums/checksums.lock +0 -0
- package/android/.gradle/8.14.2/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.14.2/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.14.2/executionHistory/executionHistory.bin +0 -0
- package/android/.gradle/8.14.2/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.14.2/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/8.14.2/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.14.2/fileHashes/resourceHashesCache.bin +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/file-system.probe +0 -0
- package/android/build.gradle +3 -1
- package/android/src/main/AndroidManifest.xml +5 -3
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraPreview.java +473 -88
- package/android/src/main/java/com/ahm/capacitor/camera/preview/CameraXView.java +2065 -704
- package/android/src/main/java/com/ahm/capacitor/camera/preview/GridOverlayView.java +95 -0
- package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraDevice.java +55 -46
- package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraLens.java +61 -52
- package/android/src/main/java/com/ahm/capacitor/camera/preview/model/CameraSessionConfiguration.java +152 -59
- package/android/src/main/java/com/ahm/capacitor/camera/preview/model/LensInfo.java +29 -23
- package/android/src/main/java/com/ahm/capacitor/camera/preview/model/ZoomFactors.java +24 -23
- package/dist/docs.json +235 -6
- package/dist/esm/definitions.d.ts +119 -3
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +47 -3
- package/dist/esm/web.js +297 -96
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +293 -96
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +293 -96
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapgoCameraPreview/CameraController.swift +364 -218
- package/ios/Sources/CapgoCameraPreview/GridOverlayView.swift +65 -0
- package/ios/Sources/CapgoCameraPreview/Plugin.swift +886 -242
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -16,6 +16,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
16
16
|
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.CameraPreviewWeb()),
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
+
const DEFAULT_VIDEO_ID = "capgo_video";
|
|
19
20
|
class CameraPreviewWeb extends core.WebPlugin {
|
|
20
21
|
constructor() {
|
|
21
22
|
super();
|
|
@@ -25,87 +26,104 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
25
26
|
*/
|
|
26
27
|
this.isBackCamera = false;
|
|
27
28
|
this.currentDeviceId = null;
|
|
29
|
+
this.videoElement = null;
|
|
30
|
+
this.isStarted = false;
|
|
28
31
|
}
|
|
29
32
|
async getSupportedPictureSizes() {
|
|
30
33
|
throw new Error("getSupportedPictureSizes not supported under the web platform");
|
|
31
34
|
}
|
|
32
35
|
async start(options) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
stream.getTracks().forEach((track) => track.stop());
|
|
42
|
-
})
|
|
43
|
-
.catch((error) => {
|
|
44
|
-
Promise.reject(error);
|
|
45
|
-
});
|
|
46
|
-
const video = document.getElementById("video");
|
|
36
|
+
if (options.aspectRatio && (options.width || options.height)) {
|
|
37
|
+
throw new Error("Cannot set both aspectRatio and size (width/height). Use setPreviewSize after start.");
|
|
38
|
+
}
|
|
39
|
+
if (this.isStarted) {
|
|
40
|
+
throw new Error("camera already started");
|
|
41
|
+
}
|
|
42
|
+
this.isBackCamera = true;
|
|
43
|
+
this.isStarted = false;
|
|
47
44
|
const parent = document.getElementById((options === null || options === void 0 ? void 0 : options.parent) || "");
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
const gridMode = (options === null || options === void 0 ? void 0 : options.gridMode) || "none";
|
|
46
|
+
if (options.position) {
|
|
47
|
+
this.isBackCamera = options.position === "rear";
|
|
48
|
+
}
|
|
49
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
50
|
+
if (video) {
|
|
51
|
+
video.remove();
|
|
52
|
+
}
|
|
53
|
+
const container = options.parent
|
|
54
|
+
? document.getElementById(options.parent)
|
|
55
|
+
: document.body;
|
|
56
|
+
if (!container) {
|
|
57
|
+
throw new Error("container not found");
|
|
58
|
+
}
|
|
59
|
+
this.videoElement = document.createElement("video");
|
|
60
|
+
this.videoElement.id = DEFAULT_VIDEO_ID;
|
|
61
|
+
this.videoElement.className = options.className || "";
|
|
62
|
+
this.videoElement.playsInline = true;
|
|
63
|
+
this.videoElement.muted = true;
|
|
64
|
+
this.videoElement.autoplay = true;
|
|
65
|
+
container.appendChild(this.videoElement);
|
|
66
|
+
if (options.toBack) {
|
|
67
|
+
this.videoElement.style.zIndex = "-1";
|
|
68
|
+
}
|
|
69
|
+
if (options.width) {
|
|
70
|
+
this.videoElement.width = options.width;
|
|
71
|
+
}
|
|
72
|
+
if (options.height) {
|
|
73
|
+
this.videoElement.height = options.height;
|
|
74
|
+
}
|
|
75
|
+
if (options.x) {
|
|
76
|
+
this.videoElement.style.left = `${options.x}px`;
|
|
77
|
+
}
|
|
78
|
+
// Create and add grid overlay if needed
|
|
79
|
+
if (gridMode !== "none") {
|
|
80
|
+
const gridOverlay = this.createGridOverlay(gridMode);
|
|
81
|
+
gridOverlay.id = "camera-grid-overlay";
|
|
82
|
+
parent === null || parent === void 0 ? void 0 : parent.appendChild(gridOverlay);
|
|
83
|
+
}
|
|
84
|
+
if (options.y) {
|
|
85
|
+
this.videoElement.style.top = `${options.y}px`;
|
|
86
|
+
}
|
|
87
|
+
if (options.aspectRatio) {
|
|
88
|
+
const [widthRatio, heightRatio] = options.aspectRatio
|
|
89
|
+
.split(":")
|
|
90
|
+
.map(Number);
|
|
91
|
+
const ratio = widthRatio / heightRatio;
|
|
92
|
+
if (options.width) {
|
|
93
|
+
this.videoElement.height = options.width / ratio;
|
|
55
94
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Safari on iOS needs to have the autoplay, muted and playsinline attributes set for video.play() to be successful
|
|
59
|
-
// Without these attributes videoElement.play() will throw a NotAllowedError
|
|
60
|
-
// https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari
|
|
61
|
-
if (isSafari) {
|
|
62
|
-
videoElement.setAttribute("autoplay", "true");
|
|
63
|
-
videoElement.setAttribute("muted", "true");
|
|
64
|
-
videoElement.setAttribute("playsinline", "true");
|
|
65
|
-
}
|
|
66
|
-
parent === null || parent === void 0 ? void 0 : parent.appendChild(videoElement);
|
|
67
|
-
if ((_a = navigator === null || navigator === void 0 ? void 0 : navigator.mediaDevices) === null || _a === void 0 ? void 0 : _a.getUserMedia) {
|
|
68
|
-
const constraints = {
|
|
69
|
-
video: {
|
|
70
|
-
width: { ideal: options.width },
|
|
71
|
-
height: { ideal: options.height },
|
|
72
|
-
},
|
|
73
|
-
};
|
|
74
|
-
if (options.deviceId) {
|
|
75
|
-
constraints.video.deviceId = { exact: options.deviceId };
|
|
76
|
-
this.currentDeviceId = options.deviceId;
|
|
77
|
-
// Try to determine camera position from device
|
|
78
|
-
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
79
|
-
const device = devices.find(d => d.deviceId === options.deviceId);
|
|
80
|
-
this.isBackCamera = (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('back')) || (device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes('rear')) || false;
|
|
81
|
-
}
|
|
82
|
-
else if (options.position === "rear") {
|
|
83
|
-
constraints.video.facingMode = "environment";
|
|
84
|
-
this.isBackCamera = true;
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
this.isBackCamera = false;
|
|
88
|
-
}
|
|
89
|
-
const self = this;
|
|
90
|
-
await navigator.mediaDevices.getUserMedia(constraints).then((stream) => {
|
|
91
|
-
if (document.getElementById("video")) {
|
|
92
|
-
// video.src = window.URL.createObjectURL(stream);
|
|
93
|
-
videoElement.srcObject = stream;
|
|
94
|
-
videoElement.play();
|
|
95
|
-
Promise.resolve({});
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
self.stopStream(stream);
|
|
99
|
-
Promise.reject(new Error("camera already stopped"));
|
|
100
|
-
}
|
|
101
|
-
}, (err) => {
|
|
102
|
-
Promise.reject(new Error(err));
|
|
103
|
-
});
|
|
95
|
+
else if (options.height) {
|
|
96
|
+
this.videoElement.width = options.height * ratio;
|
|
104
97
|
}
|
|
105
98
|
}
|
|
106
99
|
else {
|
|
107
|
-
|
|
100
|
+
this.videoElement.style.objectFit = "cover";
|
|
101
|
+
}
|
|
102
|
+
const constraints = {
|
|
103
|
+
video: {
|
|
104
|
+
width: { ideal: this.videoElement.width || 640 },
|
|
105
|
+
height: { ideal: this.videoElement.height || window.innerHeight },
|
|
106
|
+
facingMode: this.isBackCamera ? "environment" : "user",
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
110
|
+
if (!stream) {
|
|
111
|
+
throw new Error("could not acquire stream");
|
|
108
112
|
}
|
|
113
|
+
if (!this.videoElement) {
|
|
114
|
+
throw new Error("video element not found");
|
|
115
|
+
}
|
|
116
|
+
this.videoElement.srcObject = stream;
|
|
117
|
+
if (!this.isBackCamera) {
|
|
118
|
+
this.videoElement.style.transform = "scaleX(-1)";
|
|
119
|
+
}
|
|
120
|
+
this.isStarted = true;
|
|
121
|
+
return {
|
|
122
|
+
width: this.videoElement.width,
|
|
123
|
+
height: this.videoElement.height,
|
|
124
|
+
x: this.videoElement.getBoundingClientRect().x,
|
|
125
|
+
y: this.videoElement.getBoundingClientRect().y,
|
|
126
|
+
};
|
|
109
127
|
}
|
|
110
128
|
stopStream(stream) {
|
|
111
129
|
if (stream) {
|
|
@@ -115,16 +133,20 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
115
133
|
}
|
|
116
134
|
}
|
|
117
135
|
async stop() {
|
|
118
|
-
const video = document.getElementById(
|
|
136
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
119
137
|
if (video) {
|
|
120
138
|
video.pause();
|
|
121
139
|
this.stopStream(video.srcObject);
|
|
122
140
|
video.remove();
|
|
141
|
+
this.isStarted = false;
|
|
123
142
|
}
|
|
143
|
+
// Remove grid overlay if it exists
|
|
144
|
+
const gridOverlay = document.getElementById("camera-grid-overlay");
|
|
145
|
+
gridOverlay === null || gridOverlay === void 0 ? void 0 : gridOverlay.remove();
|
|
124
146
|
}
|
|
125
147
|
async capture(options) {
|
|
126
148
|
return new Promise((resolve, reject) => {
|
|
127
|
-
const video = document.getElementById(
|
|
149
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
128
150
|
if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {
|
|
129
151
|
reject(new Error("camera is not running"));
|
|
130
152
|
return;
|
|
@@ -142,6 +164,8 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
142
164
|
context === null || context === void 0 ? void 0 : context.scale(-1, 1);
|
|
143
165
|
}
|
|
144
166
|
context === null || context === void 0 ? void 0 : context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
|
|
167
|
+
if (options.saveToGallery) ;
|
|
168
|
+
if (options.withExifLocation) ;
|
|
145
169
|
if ((options.format || "jpeg") === "jpeg") {
|
|
146
170
|
base64EncodedImage = canvas
|
|
147
171
|
.toDataURL("image/jpeg", (options.quality || 85) / 100.0)
|
|
@@ -155,6 +179,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
155
179
|
}
|
|
156
180
|
resolve({
|
|
157
181
|
value: base64EncodedImage,
|
|
182
|
+
exif: {},
|
|
158
183
|
});
|
|
159
184
|
});
|
|
160
185
|
}
|
|
@@ -178,7 +203,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
178
203
|
throw new Error(`setFlashMode not supported under the web platform${_options}`);
|
|
179
204
|
}
|
|
180
205
|
async flip() {
|
|
181
|
-
const video = document.getElementById(
|
|
206
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
182
207
|
if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {
|
|
183
208
|
throw new Error("camera is not running");
|
|
184
209
|
}
|
|
@@ -218,12 +243,12 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
218
243
|
}
|
|
219
244
|
}
|
|
220
245
|
async setOpacity(_options) {
|
|
221
|
-
const video = document.getElementById(
|
|
246
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
222
247
|
if (!!video && !!_options.opacity)
|
|
223
248
|
video.style.setProperty("opacity", _options.opacity.toString());
|
|
224
249
|
}
|
|
225
250
|
async isRunning() {
|
|
226
|
-
const video = document.getElementById(
|
|
251
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
227
252
|
return { isRunning: !!video && !!video.srcObject };
|
|
228
253
|
}
|
|
229
254
|
async getAvailableDevices() {
|
|
@@ -232,7 +257,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
232
257
|
throw new Error("getAvailableDevices not supported under the web platform");
|
|
233
258
|
}
|
|
234
259
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
235
|
-
const videoDevices = devices.filter(device => device.kind ===
|
|
260
|
+
const videoDevices = devices.filter((device) => device.kind === "videoinput");
|
|
236
261
|
// Group devices by position (front/back)
|
|
237
262
|
const frontDevices = [];
|
|
238
263
|
const backDevices = [];
|
|
@@ -242,15 +267,19 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
242
267
|
// Determine device type based on label
|
|
243
268
|
let deviceType = exports.DeviceType.WIDE_ANGLE;
|
|
244
269
|
let baseZoomRatio = 1.0;
|
|
245
|
-
if (labelLower.includes(
|
|
270
|
+
if (labelLower.includes("ultra") || labelLower.includes("0.5")) {
|
|
246
271
|
deviceType = exports.DeviceType.ULTRA_WIDE;
|
|
247
272
|
baseZoomRatio = 0.5;
|
|
248
273
|
}
|
|
249
|
-
else if (labelLower.includes(
|
|
274
|
+
else if (labelLower.includes("telephoto") ||
|
|
275
|
+
labelLower.includes("tele") ||
|
|
276
|
+
labelLower.includes("2x") ||
|
|
277
|
+
labelLower.includes("3x")) {
|
|
250
278
|
deviceType = exports.DeviceType.TELEPHOTO;
|
|
251
279
|
baseZoomRatio = 2.0;
|
|
252
280
|
}
|
|
253
|
-
else if (labelLower.includes(
|
|
281
|
+
else if (labelLower.includes("depth") ||
|
|
282
|
+
labelLower.includes("truedepth")) {
|
|
254
283
|
deviceType = exports.DeviceType.TRUE_DEPTH;
|
|
255
284
|
baseZoomRatio = 1.0;
|
|
256
285
|
}
|
|
@@ -261,10 +290,10 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
261
290
|
focalLength: 4.25,
|
|
262
291
|
baseZoomRatio,
|
|
263
292
|
minZoom: 1.0,
|
|
264
|
-
maxZoom: 1.0
|
|
293
|
+
maxZoom: 1.0,
|
|
265
294
|
};
|
|
266
295
|
// Determine position and add to appropriate array
|
|
267
|
-
if (labelLower.includes(
|
|
296
|
+
if (labelLower.includes("back") || labelLower.includes("rear")) {
|
|
268
297
|
backDevices.push(lensInfo);
|
|
269
298
|
}
|
|
270
299
|
else {
|
|
@@ -279,8 +308,8 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
279
308
|
position: "front",
|
|
280
309
|
lenses: frontDevices,
|
|
281
310
|
isLogical: false,
|
|
282
|
-
minZoom: Math.min(...frontDevices.map(d => d.minZoom)),
|
|
283
|
-
maxZoom: Math.max(...frontDevices.map(d => d.maxZoom))
|
|
311
|
+
minZoom: Math.min(...frontDevices.map((d) => d.minZoom)),
|
|
312
|
+
maxZoom: Math.max(...frontDevices.map((d) => d.maxZoom)),
|
|
284
313
|
});
|
|
285
314
|
}
|
|
286
315
|
if (backDevices.length > 0) {
|
|
@@ -290,14 +319,14 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
290
319
|
position: "rear",
|
|
291
320
|
lenses: backDevices,
|
|
292
321
|
isLogical: false,
|
|
293
|
-
minZoom: Math.min(...backDevices.map(d => d.minZoom)),
|
|
294
|
-
maxZoom: Math.max(...backDevices.map(d => d.maxZoom))
|
|
322
|
+
minZoom: Math.min(...backDevices.map((d) => d.minZoom)),
|
|
323
|
+
maxZoom: Math.max(...backDevices.map((d) => d.maxZoom)),
|
|
295
324
|
});
|
|
296
325
|
}
|
|
297
326
|
return { devices: result };
|
|
298
327
|
}
|
|
299
328
|
async getZoom() {
|
|
300
|
-
const video = document.getElementById(
|
|
329
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
301
330
|
if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {
|
|
302
331
|
throw new Error("camera is not running");
|
|
303
332
|
}
|
|
@@ -316,18 +345,22 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
316
345
|
let baseZoomRatio = 1.0;
|
|
317
346
|
if (this.currentDeviceId) {
|
|
318
347
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
319
|
-
const device = devices.find(d => d.deviceId === this.currentDeviceId);
|
|
348
|
+
const device = devices.find((d) => d.deviceId === this.currentDeviceId);
|
|
320
349
|
if (device) {
|
|
321
350
|
const labelLower = device.label.toLowerCase();
|
|
322
|
-
if (labelLower.includes(
|
|
351
|
+
if (labelLower.includes("ultra") || labelLower.includes("0.5")) {
|
|
323
352
|
deviceType = exports.DeviceType.ULTRA_WIDE;
|
|
324
353
|
baseZoomRatio = 0.5;
|
|
325
354
|
}
|
|
326
|
-
else if (labelLower.includes(
|
|
355
|
+
else if (labelLower.includes("telephoto") ||
|
|
356
|
+
labelLower.includes("tele") ||
|
|
357
|
+
labelLower.includes("2x") ||
|
|
358
|
+
labelLower.includes("3x")) {
|
|
327
359
|
deviceType = exports.DeviceType.TELEPHOTO;
|
|
328
360
|
baseZoomRatio = 2.0;
|
|
329
361
|
}
|
|
330
|
-
else if (labelLower.includes(
|
|
362
|
+
else if (labelLower.includes("depth") ||
|
|
363
|
+
labelLower.includes("truedepth")) {
|
|
331
364
|
deviceType = exports.DeviceType.TRUE_DEPTH;
|
|
332
365
|
baseZoomRatio = 1.0;
|
|
333
366
|
}
|
|
@@ -338,7 +371,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
338
371
|
focalLength: 4.25,
|
|
339
372
|
deviceType,
|
|
340
373
|
baseZoomRatio,
|
|
341
|
-
digitalZoom: currentZoom / baseZoomRatio
|
|
374
|
+
digitalZoom: currentZoom / baseZoomRatio,
|
|
342
375
|
};
|
|
343
376
|
return {
|
|
344
377
|
min: capabilities.zoom.min || 1,
|
|
@@ -348,7 +381,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
348
381
|
};
|
|
349
382
|
}
|
|
350
383
|
async setZoom(options) {
|
|
351
|
-
const video = document.getElementById(
|
|
384
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
352
385
|
if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {
|
|
353
386
|
throw new Error("camera is not running");
|
|
354
387
|
}
|
|
@@ -364,7 +397,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
364
397
|
const zoomLevel = Math.max(capabilities.zoom.min || 1, Math.min(capabilities.zoom.max || 1, options.level));
|
|
365
398
|
try {
|
|
366
399
|
await videoTrack.applyConstraints({
|
|
367
|
-
advanced: [{ zoom: zoomLevel }]
|
|
400
|
+
advanced: [{ zoom: zoomLevel }],
|
|
368
401
|
});
|
|
369
402
|
}
|
|
370
403
|
catch (error) {
|
|
@@ -378,7 +411,7 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
378
411
|
return { deviceId: this.currentDeviceId || "" };
|
|
379
412
|
}
|
|
380
413
|
async setDeviceId(options) {
|
|
381
|
-
const video = document.getElementById(
|
|
414
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
382
415
|
if (!(video === null || video === void 0 ? void 0 : video.srcObject)) {
|
|
383
416
|
throw new Error("camera is not running");
|
|
384
417
|
}
|
|
@@ -397,8 +430,11 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
397
430
|
try {
|
|
398
431
|
// Try to determine camera position from device
|
|
399
432
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
400
|
-
const device = devices.find(d => d.deviceId === options.deviceId);
|
|
401
|
-
this.isBackCamera =
|
|
433
|
+
const device = devices.find((d) => d.deviceId === options.deviceId);
|
|
434
|
+
this.isBackCamera =
|
|
435
|
+
(device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes("back")) ||
|
|
436
|
+
(device === null || device === void 0 ? void 0 : device.label.toLowerCase().includes("rear")) ||
|
|
437
|
+
false;
|
|
402
438
|
const stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
403
439
|
video.srcObject = stream;
|
|
404
440
|
// Update video transform based on camera
|
|
@@ -416,6 +452,167 @@ var capacitorCapacitorCameraView = (function (exports, core) {
|
|
|
416
452
|
throw new Error(`Failed to swap to device ${options.deviceId}: ${error}`);
|
|
417
453
|
}
|
|
418
454
|
}
|
|
455
|
+
async getAspectRatio() {
|
|
456
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
457
|
+
if (!video) {
|
|
458
|
+
throw new Error("camera is not running");
|
|
459
|
+
}
|
|
460
|
+
const width = video.offsetWidth;
|
|
461
|
+
const height = video.offsetHeight;
|
|
462
|
+
if (width && height) {
|
|
463
|
+
const ratio = width / height;
|
|
464
|
+
// Check for portrait camera ratios: 4:3 -> 3:4, 16:9 -> 9:16
|
|
465
|
+
if (Math.abs(ratio - 3 / 4) < 0.01) {
|
|
466
|
+
return { aspectRatio: "4:3" };
|
|
467
|
+
}
|
|
468
|
+
if (Math.abs(ratio - 9 / 16) < 0.01) {
|
|
469
|
+
return { aspectRatio: "16:9" };
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
// Default to 4:3 if no specific aspect ratio is matched
|
|
473
|
+
return { aspectRatio: "4:3" };
|
|
474
|
+
}
|
|
475
|
+
async setAspectRatio(options) {
|
|
476
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
477
|
+
if (!video) {
|
|
478
|
+
throw new Error("camera is not running");
|
|
479
|
+
}
|
|
480
|
+
if (options.aspectRatio) {
|
|
481
|
+
const [widthRatio, heightRatio] = options.aspectRatio
|
|
482
|
+
.split(":")
|
|
483
|
+
.map(Number);
|
|
484
|
+
// For camera, use portrait orientation: 4:3 becomes 3:4, 16:9 becomes 9:16
|
|
485
|
+
const ratio = heightRatio / widthRatio;
|
|
486
|
+
// Get current position and size
|
|
487
|
+
const rect = video.getBoundingClientRect();
|
|
488
|
+
const currentWidth = rect.width;
|
|
489
|
+
const currentHeight = rect.height;
|
|
490
|
+
const currentRatio = currentWidth / currentHeight;
|
|
491
|
+
let newWidth;
|
|
492
|
+
let newHeight;
|
|
493
|
+
if (currentRatio > ratio) {
|
|
494
|
+
// Width is larger, fit by height and center horizontally
|
|
495
|
+
newWidth = currentHeight * ratio;
|
|
496
|
+
newHeight = currentHeight;
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
// Height is larger, fit by width and center vertically
|
|
500
|
+
newWidth = currentWidth;
|
|
501
|
+
newHeight = currentWidth / ratio;
|
|
502
|
+
}
|
|
503
|
+
// Calculate position
|
|
504
|
+
let x, y;
|
|
505
|
+
if (options.x !== undefined && options.y !== undefined) {
|
|
506
|
+
// Use provided coordinates, ensuring they stay within screen boundaries
|
|
507
|
+
x = Math.max(0, Math.min(options.x, window.innerWidth - newWidth));
|
|
508
|
+
y = Math.max(0, Math.min(options.y, window.innerHeight - newHeight));
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
// Auto-center the view
|
|
512
|
+
x = (window.innerWidth - newWidth) / 2;
|
|
513
|
+
y = (window.innerHeight - newHeight) / 2;
|
|
514
|
+
}
|
|
515
|
+
video.style.width = `${newWidth}px`;
|
|
516
|
+
video.style.height = `${newHeight}px`;
|
|
517
|
+
video.style.left = `${x}px`;
|
|
518
|
+
video.style.top = `${y}px`;
|
|
519
|
+
video.style.position = "absolute";
|
|
520
|
+
return {
|
|
521
|
+
width: Math.round(newWidth),
|
|
522
|
+
height: Math.round(newHeight),
|
|
523
|
+
x: Math.round(x),
|
|
524
|
+
y: Math.round(y),
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
video.style.objectFit = "cover";
|
|
529
|
+
const rect = video.getBoundingClientRect();
|
|
530
|
+
return {
|
|
531
|
+
width: Math.round(rect.width),
|
|
532
|
+
height: Math.round(rect.height),
|
|
533
|
+
x: Math.round(rect.left),
|
|
534
|
+
y: Math.round(rect.top),
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
createGridOverlay(gridMode) {
|
|
539
|
+
const overlay = document.createElement("div");
|
|
540
|
+
overlay.style.position = "absolute";
|
|
541
|
+
overlay.style.top = "0";
|
|
542
|
+
overlay.style.left = "0";
|
|
543
|
+
overlay.style.width = "100%";
|
|
544
|
+
overlay.style.height = "100%";
|
|
545
|
+
overlay.style.pointerEvents = "none";
|
|
546
|
+
overlay.style.zIndex = "10";
|
|
547
|
+
const divisions = gridMode === "3x3" ? 3 : 4;
|
|
548
|
+
// Create SVG for grid lines
|
|
549
|
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
|
550
|
+
svg.style.width = "100%";
|
|
551
|
+
svg.style.height = "100%";
|
|
552
|
+
svg.style.position = "absolute";
|
|
553
|
+
svg.style.top = "0";
|
|
554
|
+
svg.style.left = "0";
|
|
555
|
+
// Create grid lines
|
|
556
|
+
for (let i = 1; i < divisions; i++) {
|
|
557
|
+
// Vertical lines
|
|
558
|
+
const verticalLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
559
|
+
verticalLine.setAttribute("x1", `${(i / divisions) * 100}%`);
|
|
560
|
+
verticalLine.setAttribute("y1", "0%");
|
|
561
|
+
verticalLine.setAttribute("x2", `${(i / divisions) * 100}%`);
|
|
562
|
+
verticalLine.setAttribute("y2", "100%");
|
|
563
|
+
verticalLine.setAttribute("stroke", "rgba(255, 255, 255, 0.5)");
|
|
564
|
+
verticalLine.setAttribute("stroke-width", "1");
|
|
565
|
+
svg.appendChild(verticalLine);
|
|
566
|
+
// Horizontal lines
|
|
567
|
+
const horizontalLine = document.createElementNS("http://www.w3.org/2000/svg", "line");
|
|
568
|
+
horizontalLine.setAttribute("x1", "0%");
|
|
569
|
+
horizontalLine.setAttribute("y1", `${(i / divisions) * 100}%`);
|
|
570
|
+
horizontalLine.setAttribute("x2", "100%");
|
|
571
|
+
horizontalLine.setAttribute("y2", `${(i / divisions) * 100}%`);
|
|
572
|
+
horizontalLine.setAttribute("stroke", "rgba(255, 255, 255, 0.5)");
|
|
573
|
+
horizontalLine.setAttribute("stroke-width", "1");
|
|
574
|
+
svg.appendChild(horizontalLine);
|
|
575
|
+
}
|
|
576
|
+
overlay.appendChild(svg);
|
|
577
|
+
return overlay;
|
|
578
|
+
}
|
|
579
|
+
async setGridMode(options) {
|
|
580
|
+
// Web implementation of grid mode would need to be implemented
|
|
581
|
+
// For now, just resolve as a no-op
|
|
582
|
+
console.warn(`Grid mode '${options.gridMode}' is not yet implemented for web platform`);
|
|
583
|
+
}
|
|
584
|
+
async getGridMode() {
|
|
585
|
+
// Web implementation - default to none
|
|
586
|
+
return { gridMode: "none" };
|
|
587
|
+
}
|
|
588
|
+
async getPreviewSize() {
|
|
589
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
590
|
+
if (!video) {
|
|
591
|
+
throw new Error("camera is not running");
|
|
592
|
+
}
|
|
593
|
+
return {
|
|
594
|
+
x: video.offsetLeft,
|
|
595
|
+
y: video.offsetTop,
|
|
596
|
+
width: video.width,
|
|
597
|
+
height: video.height,
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
async setPreviewSize(options) {
|
|
601
|
+
const video = document.getElementById(DEFAULT_VIDEO_ID);
|
|
602
|
+
if (!video) {
|
|
603
|
+
throw new Error("camera is not running");
|
|
604
|
+
}
|
|
605
|
+
video.style.left = `${options.x}px`;
|
|
606
|
+
video.style.top = `${options.y}px`;
|
|
607
|
+
video.width = options.width;
|
|
608
|
+
video.height = options.height;
|
|
609
|
+
return {
|
|
610
|
+
width: options.width,
|
|
611
|
+
height: options.height,
|
|
612
|
+
x: options.x,
|
|
613
|
+
y: options.y,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
419
616
|
}
|
|
420
617
|
|
|
421
618
|
var web = /*#__PURE__*/Object.freeze({
|