Kamera: Antippen stellt an der richtigen Stelle scharf, Wechselknopf als Symbol [deploy]
Im Android-Emulator (Chrome 153, echter Camera2-Weg, dumpsys media.camera)
gegengeprüft: Blitz Aus/Auto/An und Licht kommen richtig bei der Kamera an.
Beim Antippen-Fokus waren zwei Fehler:
- Chrome rechnet pointsOfInterest ungedreht auf den quer liegenden Sensor um,
das Sucherbild steht aber hochkant. Ein Tipp rechts unten landete an
falscher Stelle. sensorPunkt() dreht die Tippstelle jetzt in Sensorlage
zurück (hochkant, quer 90° und 270° gemessen).
- focusMode single-shot nimmt Chrome auf Android an, setzt es aber nicht um
(kein AF-Trigger). Der Hinweis „Fokus fest“ war damit falsch und ist weg;
Antippen = Dauer-Autofokus auf die Tippstelle.
Knopf „Kamera wechseln“: weißes Symbol statt 🔄-Emoji (blaues Kästchen),
nur sichtbar, wenn das Gerät mindestens zwei Kameras hat.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
2bf5852147
commit
7c8a3c4bc0
4 changed files with 74 additions and 46 deletions
|
|
@ -21,9 +21,9 @@ Mobile Progressive Web App für die Baustellen-Doku — Foto-Upload, Sprach- und
|
|||
- ✅ **Neuer Auftrag** (FAB): Kunde per Suche/Zuletzt-verwendet wählen, dann **Ihr Zeichen** (Pflicht), **Auftragsbeschreibung** (optional), **Geplanter Liefertermin** (Datum + Uhrzeit) und Checkbox **Auftrag direkt freigeben**. Kunden-Defaults (Zahlungsbedingung/Zahlart, Ansprechpartner) werden übernommen. Bei „direkt freigeben" wird der Auftrag **ohne Position** validiert — die Leistungen kommen aus dem Stundenzettel. (Bis Bericht 1.3.1 hängte das Backend hier eine Std-Lohn-Zeile mit Menge 1 an; die verfälschte den Auftragswert, stand als offene Restmenge in der Lieferauflistung und im Kunden-PDF.)
|
||||
|
||||
**Foto-Upload**
|
||||
- ✅ Live-Kamera-Modal (getUserMedia): bleibt für Serien-Aufnahmen offen — Auslöser + Filmstreifen mit Upload-Status je Foto (💾 gesichert → ⏳ lädt hoch → ✓ fertig), Front-/Rückkamera-Umschaltung, Fehlschuss löschbar
|
||||
- ✅ Live-Kamera-Modal (getUserMedia): bleibt für Serien-Aufnahmen offen — Auslöser + Filmstreifen mit Upload-Status je Foto (💾 gesichert → ⏳ lädt hoch → ✓ fertig), Front-/Rückkamera-Umschaltung (nur bei zwei Kameras), Fehlschuss löschbar
|
||||
- ✅ **Volle Kameraauflösung**: ausgelöst wird über `ImageCapture.takePhoto()` (native JPEG der Kamera inkl. EXIF) — ein Standbild aus dem Video-Stream hat nur Stream-Auflösung und ist nur noch die Rückfallebene (iOS/Safari, ältere Browser)
|
||||
- ✅ **Blitz und Fokus** (19.10.2026): Knopf oben schaltet reihum Aus → Auto → An → 🔦 Licht (nur was das Gerät meldet, Auswahl bleibt gemerkt; Blitz wirkt über `takePhoto({fillLightMode})`). Antippen stellt an der Stelle scharf und hält den Fokus („🎯 Fokus fest · zurück auf Auto“). Frontkamera/Tablet-Webcam ohne diese Fähigkeiten: kein Knopf, Antippen ohne Wirkung
|
||||
- ✅ **Blitz und Fokus** (19.10.2026): Knopf oben schaltet reihum Aus → Auto → An → 🔦 Licht (nur was das Gerät meldet, Auswahl bleibt gemerkt; Blitz wirkt über `takePhoto({fillLightMode})`). Antippen stellt den Autofokus auf diese Stelle (Tippstelle wird in Sensorlage zurückgedreht — Chrome tut das nicht; ein echtes „Fokus festhalten“ bietet Chrome auf Android nicht an). Frontkamera/Tablet-Webcam ohne diese Fähigkeiten: kein Knopf, Antippen ohne Wirkung. Knopf „Kamera wechseln“ (weißes Symbol) nur bei mindestens zwei Kameras. Im Android-Emulator per `dumpsys media.camera` gegengeprüft (ROADMAP Punkt 9)
|
||||
- ✅ **Verkleinerte Fotos heißen `.jpg`** und transparente Bilder bekommen beim Verkleinern weißen Grund (vorher behielt ein verkleinertes AVIF/WebP seinen Namen und wurde vom Server abgelehnt)
|
||||
- ✅ Alternativ Aufnahme aus der Galerie (Mehrfachauswahl: alle Dateien werden sofort nach der Auswahl eingelesen, erst dann hochgeladen, weil Android die Galerie-Dateien nur kurz lesbar hält, siehe ROADMAP Punkt 7)
|
||||
- ✅ **Fotoqualität im Admin einstellbar** (Bericht-Modul → Fotoqualität, `api/config.php`): Vorgabe ist **1:1, gar nicht verkleinern**; optional längste Seite + JPEG-Qualität. Gesichert wird immer zuerst das Original, die kleine Fassung ersetzt es danach — hängt das Verkleinern (Display aus), bleibt das Original
|
||||
|
|
|
|||
41
ROADMAP.md
41
ROADMAP.md
|
|
@ -62,20 +62,37 @@ Eddy: *„beim Fotografieren kann man den Blitz nicht einstellen und den Fokus a
|
|||
klappt das nicht, wird ohne Einstellung ausgelöst) → 🔦 Licht (Dauerlicht, `track.getCapabilities().torch`,
|
||||
nach dem Auslösen erneut gesetzt). Meldet das Gerät nichts davon, gibt es keinen Knopf. Auswahl bleibt gemerkt
|
||||
(`localStorage baustelle.kamera.blitz`).
|
||||
- [x] ✅ 19.10.2026: Antippen stellt dort scharf (`pointsOfInterest` + `focusMode: single-shot`, sonst `continuous`;
|
||||
ohne Punktwahl nur neu scharfstellen), Ring an der Stelle. Bei `single-shot` bleibt der Fokus fest, oben steht
|
||||
„🎯 Fokus fest · zurück auf Auto" (Tippen → `continuous`). Einmaliger Hinweis „Antippen stellt dort scharf".
|
||||
- [x] ✅ 19.10.2026: Antippen stellt dort scharf (`pointsOfInterest` + `focusMode`), Ring an der Stelle, einmaliger
|
||||
Hinweis „Antippen stellt dort scharf".
|
||||
- [x] Lokal geprüft mit nachgebildeter Kamera (Canvas-Strom + gemeldete Fähigkeiten): Reihenfolge der Modi,
|
||||
Licht an/aus, `takePhoto({fillLightMode:"flash"})`, Antippstelle richtig umgerechnet (eingepasste Vorschau,
|
||||
0,803 statt 0,75 bei seitlichem Rand), „Fokus fest" → continuous; ohne Fähigkeiten kein Knopf, keine Wirkung.
|
||||
- [ ] **Am Handy gegenprüfen** (am Schreibtisch nicht nachstellbar): blitzt „An" wirklich, geht „Licht" an,
|
||||
wird nach Antippen die angetippte Stelle scharf.
|
||||
Versuch 19.10.2026 am Rechner Buero: Android-Emulator startet nicht (`SVM disabled (by BIOS)`, außerdem fehlen
|
||||
nach dem Kernel-Update die Module des laufenden Kernels 7.2.9 → erst nach Neustart + SVM im BIOS). Test mit
|
||||
der Webcam Razer Kiyo Pro in Chrome: Die Kamera hing schon beim Starten des Bildstroms
|
||||
(`uvcvideo: Failed to set UVC commit control: -110`) und fiel danach vom USB-Bus (`error -71`) — also vor
|
||||
Blitz/Fokus. Ergebnis daraus nur: Chrome wirft bei nicht unterstützten Fokus-Vorgaben `OverconstrainedError`,
|
||||
den die App abfängt.
|
||||
0,803 statt 0,75 bei seitlichem Rand); ohne Fähigkeiten kein Knopf, keine Wirkung.
|
||||
- [x] ✅ 19.10.2026 abends: **Gegenprobe im Android-Emulator** (AVD `fluke`, Chrome 153, emulierte Rückkamera mit
|
||||
Blitz + AF-Bereich) — echter Camera2-Weg, gemessen per `adb shell dumpsys media.camera` („Last request sent"):
|
||||
|
||||
| Einstellung | was bei der Kamera ankommt | Ergebnis |
|
||||
|---|---|---|
|
||||
| ⚡ Aus | `aeMode ON`, `flash.mode OFF` | ✓ |
|
||||
| ⚡ Auto, Auslösen | Standbild `aeMode ON_AUTO_FLASH` | ✓ Kamera entscheidet |
|
||||
| ⚡ An, Auslösen | Standbild `aeMode ON_ALWAYS_FLASH`, `flash.mode SINGLE` | ✓ wie Kamera-Apps |
|
||||
| 🔦 Licht | `flash.mode TORCH`, bleibt nach dem Auslösen an | ✓ |
|
||||
| Antippen (alt) | `afRegions` an falscher Stelle, `afMode` bleibt `CONTINUOUS_PICTURE` | ✗ zwei Fehler |
|
||||
|
||||
**Fehler 1 — Tippstelle ungedreht:** Chrome rechnet `pointsOfInterest` direkt auf die Sensorfläche um
|
||||
(`VideoCaptureCamera2.java`, keine Drehung), das Sucherbild kommt aber gedreht an (Sensor quer, Bild hochkant).
|
||||
Tipp bei 67 % / 82 % → Bereich bei 67 % / 82 % des quer liegenden Sensors statt 82 % / 33 %. Jetzt dreht
|
||||
`sensorPunkt()` zurück (Rückkamera: Sensor 90° − Bildschirmwinkel; Nothing A059 hat 90°, siehe takePhoto-
|
||||
Drehmarke 6 in KB #1494). Gemessen: hochkant ✓ (zwei Stellen), quer 90° ✓ (1:1), quer 270° ✓ (180°).
|
||||
**Fehler 2 — „Fokus fest" log:** `single-shot` nimmt Chrome ohne Fehler an (auch mit `exact`), setzt auf Android
|
||||
aber nichts um — `AF_TRIGGER_START` kommt im Quelltext nicht vor, der Modus bleibt `CONTINUOUS_PICTURE`, und die
|
||||
gefundene Entfernung meldet Chrome nicht zurück (nur die eigene Vorgabe). Ein echtes Festhalten geht über die
|
||||
Web-Schnittstelle also nicht. Jetzt: Antippen = Dauer-Autofokus **auf die Tippstelle**, der Hinweis
|
||||
„🎯 Fokus fest" ist entfernt.
|
||||
- [x] ✅ 19.10.2026 (Eddy: „den hässlichen Wechselbutton lässt du da doch nicht"): 🔄-Emoji (erschien als blaues
|
||||
Kästchen) → weißes Material-Symbol wie ✕; Knopf nur, wenn `enumerateDevices()` mindestens zwei Kameras meldet.
|
||||
- [ ] **Am Handy beim nächsten Einsatz ansehen** — der Weg bis zur Kamera ist belegt, offen ist nur das Gerät selbst:
|
||||
blitzt das Nothing bei „An" sichtbar, und springt der Fokus nach dem Antippen sofort auf die Stelle (ohne
|
||||
AF-Auslöser hängt das vom Kamera-Treiber ab). Wenn nicht: Tag + Uhrzeit reichen.
|
||||
|
||||
## 7. Galerie-Auswahl: „permission"-Fehler ab dem 3. Foto (gemeldet 2026-09-30)
|
||||
|
||||
|
|
|
|||
16
app.css
16
app.css
|
|
@ -1312,6 +1312,9 @@ body {
|
|||
.cam-shutter.flash { background: #ffd34d; }
|
||||
/* Blitz-Knopf: Text statt nur Symbol, damit der Zustand lesbar ist (Aus/Auto/An/Licht) */
|
||||
.camera-modal .cam-blitz { font-size: 15px; white-space: nowrap; }
|
||||
/* Kamera wechseln: weisses Symbol wie ✕, kein Emoji (das erschien als blaues Kaestchen) */
|
||||
.camera-modal .cam-flip { display: inline-flex; align-items: center; }
|
||||
.camera-modal .cam-flip svg { display: block; }
|
||||
/* Scharfstellen per Antippen */
|
||||
.camera-modal .cam-fokus-ring {
|
||||
position: absolute;
|
||||
|
|
@ -1326,19 +1329,6 @@ body {
|
|||
.camera-modal .cam-fokus-ring.aktiv { animation: cam-fokus 0.35s ease-out; }
|
||||
.camera-modal .cam-fokus-ring.ok { border-color: #ffd34d; }
|
||||
@keyframes cam-fokus { from { transform: scale(1.5); opacity: 0.4; } to { transform: scale(1); opacity: 0.9; } }
|
||||
.camera-modal .cam-fokus-fest {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
color: #ffd34d;
|
||||
border: 1px solid #ffd34d;
|
||||
border-radius: 16px;
|
||||
padding: 6px 12px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.camera-modal [hidden] { display: none !important; }
|
||||
|
||||
/* ============================================================
|
||||
|
|
|
|||
59
app.js
59
app.js
|
|
@ -3618,13 +3618,14 @@ async function openCameraModal(orderId) {
|
|||
<button class="icon-btn" id="cam-close">✕</button>
|
||||
<div class="fs-title">📷 Kamera</div>
|
||||
<button class="icon-btn cam-blitz" id="cam-blitz" title="Blitz" hidden></button>
|
||||
<button class="icon-btn" id="cam-flip" title="Kamera wechseln">🔄</button>
|
||||
<button class="icon-btn cam-flip" id="cam-flip" title="Kamera wechseln" aria-label="Kamera wechseln" hidden>
|
||||
<svg viewBox="0 0 24 24" width="24" height="24" fill="currentColor" aria-hidden="true"><path d="M16 7h-1l-1-1h-4L9 7H8c-1.1 0-2 .9-2 2v6c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V9c0-1.1-.9-2-2-2zm-4 7c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z"/><path d="M8.57.51l4.48 4.48V2.04c4.72.47 8.48 4.23 8.95 8.95h2C23.34 3.02 15.49-1.59 8.57.51zm2.38 21.45c-4.72-.47-8.48-4.23-8.95-8.95H0c.66 7.97 8.51 12.58 15.43 10.48l-4.48-4.48v2.95z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="cam-stage" id="cam-stage">
|
||||
<video id="cam-video" playsinline autoplay muted></video>
|
||||
<div class="cam-hint" id="cam-hint">Kamera wird gestartet…</div>
|
||||
<div class="cam-fokus-ring" id="cam-fokus-ring" hidden></div>
|
||||
<button class="cam-fokus-fest" id="cam-fokus-fest" hidden>🎯 Fokus fest · zurück auf Auto</button>
|
||||
</div>
|
||||
<div class="cam-filmstrip" id="cam-strip"></div>
|
||||
<div class="cam-controls">
|
||||
|
|
@ -3643,7 +3644,7 @@ async function openCameraModal(orderId) {
|
|||
const stage = modal.querySelector('#cam-stage');
|
||||
const blitzBtn = modal.querySelector('#cam-blitz');
|
||||
const fokusRing = modal.querySelector('#cam-fokus-ring');
|
||||
const fokusFest = modal.querySelector('#cam-fokus-fest');
|
||||
const flipBtn = modal.querySelector('#cam-flip');
|
||||
|
||||
let stream = null;
|
||||
let facing = 'environment';
|
||||
|
|
@ -3687,7 +3688,7 @@ async function openCameraModal(orderId) {
|
|||
|
||||
modal.querySelector('#cam-close').onclick = () => closeModal(modal);
|
||||
modal.querySelector('#cam-done').onclick = () => closeModal(modal);
|
||||
modal.querySelector('#cam-flip').onclick = () => {
|
||||
flipBtn.onclick = () => {
|
||||
facing = (facing === 'environment') ? 'user' : 'environment';
|
||||
startStream();
|
||||
};
|
||||
|
|
@ -3716,6 +3717,11 @@ async function openCameraModal(orderId) {
|
|||
video.srcObject = stream;
|
||||
await video.play().catch(() => {});
|
||||
hint.style.display = 'none';
|
||||
// Wechselknopf nur, wenn es eine zweite Kamera gibt (Emulator, Tablet-Webcam: nur eine).
|
||||
// Erst nach der Freigabe ist die Geraeteliste vollstaendig.
|
||||
navigator.mediaDevices.enumerateDevices().then(l => {
|
||||
if (my === gen) flipBtn.hidden = l.filter(d => d.kind === 'videoinput').length < 2;
|
||||
}).catch(() => {});
|
||||
await kameraExtras(my);
|
||||
} catch (err) {
|
||||
if (my !== gen || !document.body.contains(modal)) return; // abgebrochen, nicht mehr relevant
|
||||
|
|
@ -3781,8 +3787,10 @@ async function openCameraModal(orderId) {
|
|||
* - Blitz beim Ausloesen: ImageCapture.getPhotoCapabilities().fillLightMode (auto/flash),
|
||||
* wirkt nur ueber takePhoto({ fillLightMode }) — nicht beim Standbild aus dem Sucher.
|
||||
* - Licht (Dauerlicht): track.getCapabilities().torch, per applyConstraints.
|
||||
* - Scharfstellen per Antippen: focusMode 'single-shot' (stellt einmal scharf und haelt den
|
||||
* Fokus fest) bzw. 'continuous', jeweils mit pointsOfInterest = angetippte Stelle (0..1).
|
||||
* - Scharfstellen per Antippen: pointsOfInterest = angetippte Stelle, focusMode 'continuous'
|
||||
* → der Autofokus stellt laufend auf diese Stelle scharf. 'single-shot' meldet Chrome zwar,
|
||||
* loest es auf Android aber nicht ein (kein AF-Trigger in VideoCaptureCamera2.java, der
|
||||
* Modus bleibt CONTINUOUS_PICTURE — im Emulator per dumpsys gemessen, 19.10.2026).
|
||||
* Frontkamera, Webcam am Tablet (X12) usw. melden meist nichts davon → kein Knopf, kein Antippen.
|
||||
*/
|
||||
const BLITZ_TEXT = { off: '⚡ Aus', auto: '⚡ Auto', flash: '⚡ An', torch: '🔦 Licht' };
|
||||
|
|
@ -3791,7 +3799,7 @@ async function openCameraModal(orderId) {
|
|||
let blitzModi = [];
|
||||
let blitz = 'off';
|
||||
let fotoBlitz = false; // kann takePhoto() blitzen (fillLightMode)?
|
||||
let fokusModus = ''; // 'single-shot' | 'continuous' | '' (kein Antippen)
|
||||
let fokusModus = ''; // 'continuous' | 'single-shot' | '' (kein Antippen)
|
||||
let tippHinweis = false;
|
||||
|
||||
function videoTrack() {
|
||||
|
|
@ -3800,7 +3808,7 @@ async function openCameraModal(orderId) {
|
|||
|
||||
async function kameraExtras(my) {
|
||||
imageCap = null; blitzModi = []; fotoBlitz = false; fokusModus = '';
|
||||
blitzBtn.hidden = true; fokusFest.hidden = true; fokusRing.hidden = true;
|
||||
blitzBtn.hidden = true; fokusRing.hidden = true;
|
||||
const track = videoTrack();
|
||||
if (!track) return;
|
||||
let caps = {};
|
||||
|
|
@ -3832,7 +3840,7 @@ async function openCameraModal(orderId) {
|
|||
}
|
||||
|
||||
const fm = Array.isArray(caps.focusMode) ? caps.focusMode : [];
|
||||
fokusModus = fm.includes('single-shot') ? 'single-shot' : (fm.includes('continuous') ? 'continuous' : '');
|
||||
fokusModus = fm.includes('continuous') ? 'continuous' : (fm.includes('single-shot') ? 'single-shot' : '');
|
||||
if (fokusModus && !tippHinweis) {
|
||||
tippHinweis = true;
|
||||
hint.textContent = 'Antippen stellt dort scharf';
|
||||
|
|
@ -3862,9 +3870,29 @@ async function openCameraModal(orderId) {
|
|||
try { localStorage.setItem(BLITZ_KEY, blitz); } catch (_) {}
|
||||
};
|
||||
|
||||
/* Chrome gibt pointsOfInterest UNGEDREHT an den Sensor weiter (Punkt × Sensorflaeche,
|
||||
* VideoCaptureCamera2.java) — das Sucherbild kommt aber schon gedreht an: Sensor quer,
|
||||
* Bild am Handy hochkant. Ohne Rueckdrehung stellte ein Tipp bei 67 % / 82 % auf 67 % / 82 %
|
||||
* des QUER liegenden Sensors scharf (Emulator, dumpsys afRegions) — also an falscher Stelle.
|
||||
* Drehung wie in Chrome: Rueckkamera Sensor − Bildschirmwinkel, Frontkamera Sensor + Winkel.
|
||||
* Sensorlage Rueckkamera 90° (Nothing A059: takePhoto-Drehmarke 6, KB #1494), Frontkamera 270°;
|
||||
* passt das nicht zum Bildformat (Tablet mit 0°-Sensor), ohne 90°-Anteil. */
|
||||
function sensorPunkt(x, y) {
|
||||
const winkel = (screen.orientation && typeof screen.orientation.angle === 'number') ? screen.orientation.angle : 0;
|
||||
const drehung = (sensor) => (facing === 'user' ? sensor + winkel : sensor - winkel + 360) % 360;
|
||||
let d = drehung(facing === 'user' ? 270 : 90);
|
||||
if ((d % 180 === 90) !== (video.videoHeight > video.videoWidth)) d = drehung(0);
|
||||
switch (d) {
|
||||
case 90: return { x: y, y: 1 - x };
|
||||
case 180: return { x: 1 - x, y: 1 - y };
|
||||
case 270: return { x: 1 - y, y: x };
|
||||
default: return { x, y };
|
||||
}
|
||||
}
|
||||
|
||||
stage.addEventListener('click', async (ev) => {
|
||||
const track = videoTrack();
|
||||
if (!track || !fokusModus || !video.videoWidth || ev.target === fokusFest) return;
|
||||
if (!track || !fokusModus || !video.videoWidth) return;
|
||||
// Antippstelle in Bildkoordinaten 0..1 — die Vorschau ist eingepasst (object-fit: contain)
|
||||
const r = video.getBoundingClientRect();
|
||||
const sk = Math.min(r.width / video.videoWidth, r.height / video.videoHeight);
|
||||
|
|
@ -3872,6 +3900,7 @@ async function openCameraModal(orderId) {
|
|||
const x = (ev.clientX - r.left - (r.width - w) / 2) / w;
|
||||
const y = (ev.clientY - r.top - (r.height - h) / 2) / h;
|
||||
if (x < 0 || x > 1 || y < 0 || y > 1) return;
|
||||
const punkt = sensorPunkt(x, y);
|
||||
|
||||
const sr = stage.getBoundingClientRect();
|
||||
fokusRing.style.left = (ev.clientX - sr.left) + 'px';
|
||||
|
|
@ -3883,7 +3912,7 @@ async function openCameraModal(orderId) {
|
|||
|
||||
let ok = false;
|
||||
try {
|
||||
await track.applyConstraints({ advanced: [{ pointsOfInterest: [{ x, y }], focusMode: fokusModus }] });
|
||||
await track.applyConstraints({ advanced: [{ pointsOfInterest: [punkt], focusMode: fokusModus }] });
|
||||
ok = true;
|
||||
} catch (_) {
|
||||
// Ohne Punktwahl wenigstens neu scharfstellen
|
||||
|
|
@ -3891,16 +3920,8 @@ async function openCameraModal(orderId) {
|
|||
}
|
||||
fokusRing.classList.toggle('ok', ok);
|
||||
setTimeout(() => { fokusRing.hidden = true; }, 900);
|
||||
if (ok && fokusModus === 'single-shot') fokusFest.hidden = false;
|
||||
});
|
||||
|
||||
fokusFest.onclick = async (ev) => {
|
||||
ev.stopPropagation();
|
||||
const track = videoTrack();
|
||||
fokusFest.hidden = true;
|
||||
if (track) { try { await track.applyConstraints({ advanced: [{ focusMode: 'continuous' }] }); } catch (_) {} }
|
||||
};
|
||||
|
||||
/* Echtes Kamerafoto in voller Sensoraufloesung.
|
||||
*
|
||||
* Ein Standbild aus dem Video-Stream hat hoechstens Stream-Aufloesung (hier bis 4K
|
||||
|
|
|
|||
Loading…
Reference in a new issue