Compare commits
2 Commits
4d572b55ca
...
f3a4c1af05
| Author | SHA1 | Date | |
|---|---|---|---|
|
f3a4c1af05
|
|||
|
616f615d7c
|
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "tools-app",
|
||||
"version": "0.6.8",
|
||||
"version": "0.6.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "tools-app",
|
||||
"version": "0.6.8",
|
||||
"version": "0.6.9",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"barcode-detector": "^3.1.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "tools-app",
|
||||
"private": true,
|
||||
"version": "0.6.8",
|
||||
"version": "0.6.9",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
||||
@@ -8,7 +8,7 @@ const scannedCodes = ref([])
|
||||
const hasMultipleCameras = ref(false)
|
||||
const isFullscreen = ref(false)
|
||||
const videoAspect = ref(1)
|
||||
const isFront = computed(() => facingMode.value === 'user')
|
||||
const isMirrored = ref(false)
|
||||
const wrapperRef = ref(null)
|
||||
const bgCanvas = ref(null)
|
||||
let bgRafId = null
|
||||
@@ -65,31 +65,27 @@ const paintDetections = (codes) => {
|
||||
}
|
||||
|
||||
const scale = drawWidth / vw
|
||||
const isMirrored = isFront.value
|
||||
// Canvas is mirrored via CSS if isMirrored is true, so no manual coordinate mirroring needed
|
||||
|
||||
// Styles
|
||||
const styles = getComputedStyle(document.documentElement)
|
||||
const accent = styles.getPropertyValue('--primary-accent').trim() || '#00f2fe'
|
||||
// Styles
|
||||
const styles = getComputedStyle(document.documentElement)
|
||||
const accent = styles.getPropertyValue('--primary-accent').trim() || '#00f2fe'
|
||||
|
||||
ctx.lineWidth = 4
|
||||
ctx.strokeStyle = accent
|
||||
ctx.fillStyle = accent
|
||||
ctx.lineWidth = 4
|
||||
ctx.strokeStyle = accent
|
||||
ctx.fillStyle = accent
|
||||
|
||||
codes.forEach(code => {
|
||||
const points = code.cornerPoints
|
||||
if (!points || points.length < 4) return
|
||||
codes.forEach(code => {
|
||||
const points = code.cornerPoints
|
||||
if (!points || points.length < 4) return
|
||||
|
||||
ctx.beginPath()
|
||||
ctx.beginPath()
|
||||
|
||||
const transform = (p) => {
|
||||
let x = p.x * scale + startX
|
||||
let y = p.y * scale + startY
|
||||
|
||||
if (isMirrored) {
|
||||
x = width - x
|
||||
}
|
||||
return { x, y }
|
||||
}
|
||||
const transform = (p) => {
|
||||
let x = p.x * scale + startX
|
||||
let y = p.y * scale + startY
|
||||
return { x, y }
|
||||
}
|
||||
|
||||
const p0 = transform(points[0])
|
||||
ctx.moveTo(p0.x, p0.y)
|
||||
@@ -203,6 +199,23 @@ const startScan = async () => {
|
||||
|
||||
stream = await navigator.mediaDevices.getUserMedia(constraints)
|
||||
|
||||
// Detect actual facing mode to mirror front camera correctly
|
||||
const videoTrack = stream.getVideoTracks()[0]
|
||||
if (videoTrack) {
|
||||
const settings = videoTrack.getSettings()
|
||||
if (settings.facingMode) {
|
||||
isMirrored.value = settings.facingMode === 'user'
|
||||
} else {
|
||||
// Fallback: check label for desktop cameras or assume requested mode
|
||||
const label = videoTrack.label ? videoTrack.label.toLowerCase() : ''
|
||||
if (label.includes('front') || label.includes('facetime') || label.includes('macbook')) {
|
||||
isMirrored.value = true
|
||||
} else {
|
||||
isMirrored.value = facingMode.value === 'user'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (videoRef.value) {
|
||||
videoRef.value.srcObject = stream
|
||||
// Wait for metadata to play
|
||||
@@ -464,7 +477,7 @@ const isUrl = (string) => {
|
||||
|
||||
<div
|
||||
class="camera-wrapper"
|
||||
:class="{ 'clickable': !isFullscreen, 'is-front': isFront }"
|
||||
:class="{ 'clickable': !isFullscreen, 'is-mirrored': isMirrored }"
|
||||
:style="desktopFullscreenStyle"
|
||||
ref="wrapperRef"
|
||||
@click="!isFullscreen && toggleFullscreen()"
|
||||
@@ -472,13 +485,13 @@ const isUrl = (string) => {
|
||||
<video
|
||||
ref="videoRef"
|
||||
class="camera-feed"
|
||||
:class="{ 'is-front': isFront }"
|
||||
:class="{ 'is-mirrored': isMirrored }"
|
||||
autoplay
|
||||
playsinline
|
||||
muted
|
||||
></video>
|
||||
|
||||
<canvas ref="overlayCanvas" class="scan-overlay-canvas"></canvas>
|
||||
<canvas ref="overlayCanvas" class="scan-overlay-canvas" :class="{ 'is-mirrored': isMirrored }"></canvas>
|
||||
|
||||
<div v-if="error" class="error-overlay">
|
||||
<p>{{ error }}</p>
|
||||
@@ -632,7 +645,7 @@ const isUrl = (string) => {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.camera-feed.is-front {
|
||||
.camera-feed.is-mirrored {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
@@ -646,6 +659,10 @@ const isUrl = (string) => {
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.scan-overlay-canvas.is-mirrored {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
/* front mirror canvas removed */
|
||||
|
||||
.error-overlay {
|
||||
|
||||
Reference in New Issue
Block a user