1
1
<template >
2
- <div class =" qrcode-stream-wrapper" >
3
- <!--
4
- Note, the following DOM elements are not styled with z-index.
5
- If z-index is not defined, elements are stacked in the order they appear in the DOM.
6
- The first element is at the very bottom and subsequent elements are added on top.
7
- -->
2
+ <div :style =" wrapperStyle" >
3
+ <!--
4
+ All immediate children of the wrapper div are stacked upon each other.
5
+ The z-index is implicitly given by the (inverse) element order.
6
+
7
+ The video element is at the very bottom, the pause frame canvas is above it,
8
+ the tracking layer is yet above and finally at the very top is the slot
9
+ overlay.
10
+ -->
11
+
8
12
<video
9
13
ref =" videoRef"
10
- :class =" { 'qrcode-stream-camera--hidden': !shouldScan }"
11
- class =" qrcode-stream-camera"
14
+ :style =" videoElStyle"
12
15
autoplay
13
16
muted
14
17
playsinline
15
18
/>
16
19
17
- <canvas ref =" pauseFrameRef" v-show =" !shouldScan" class = " qrcode-stream-camera " />
20
+ <canvas id = " qrcode-stream-pause-frame " ref =" pauseFrameRef" v-show =" !shouldScan" :style = " cameraStyle " />
18
21
19
- <canvas ref =" trackingLayerRef" class = " qrcode-stream-overlay " />
22
+ <canvas id = " qrcode-stream-tracking-layer " ref =" trackingLayerRef" :style = " overlayStyle " />
20
23
21
- <div class = " qrcode-stream-overlay " >
24
+ <div :style = " overlayStyle " >
22
25
<slot />
23
26
</div >
24
27
</div >
25
28
</template >
26
29
27
30
<script setup lang="ts">
28
31
import type { DetectedBarcode , BarcodeFormat } from ' @sec-ant/barcode-detector/pure'
29
- import { onUnmounted , computed , onMounted , ref , toRefs , watch , type PropType } from ' vue'
32
+ import { onUnmounted , computed , onMounted , ref , toRefs , watch , type PropType , type CSSProperties } from ' vue'
30
33
31
34
import { keepScanning , setScanningFormats } from ' ../misc/scanner'
32
35
import * as cameraController from ' ../misc/camera'
@@ -261,33 +264,37 @@ const onLocate = (detectedCodes: DetectedBarcode[]) => {
261
264
props .track (adjustedCodes , ctx )
262
265
}
263
266
}
264
- </script >
265
267
266
- <style lang="css" scoped>
267
- .qrcode-stream-wrapper {
268
- width : 100% ;
269
- height : 100% ;
268
+ /**
269
+ * Styling is all inline to avoid generating an external style.css file.
270
+ * Component users shouldn't have to figure out how to setup their bundler to
271
+ * import external CSS.
272
+ */
270
273
271
- position : relative ;
272
- z-index : 0 ;
274
+ const wrapperStyle : CSSProperties = {
275
+ " width" : " 100%" ,
276
+ " height" : " 100%" ,
277
+ " position" : " relative" ,
278
+ // notice that we use z-index only once for the wrapper div.
279
+ // If z-index is not defined, elements are stacked in the order they appear in the DOM.
280
+ // The first element is at the very bottom and subsequent elements are added on top.
281
+ " z-index" : " 0" ,
273
282
}
274
283
275
- .qrcode-stream-overlay {
276
- width : 100% ;
277
- height : 100% ;
278
-
279
- position : absolute ;
280
- top : 0 ;
281
- left : 0 ;
284
+ const overlayStyle : CSSProperties = {
285
+ " width" : " 100%" ,
286
+ " height" : " 100%" ,
287
+ " position" : " absolute" ,
288
+ " top" : " 0" ,
289
+ " left" : " 0" ,
282
290
}
283
291
284
- .qrcode-stream-camera {
285
- width : 100% ;
286
- height : 100% ;
287
-
288
- display : block ;
289
- object-fit : cover ;
292
+ const cameraStyle : CSSProperties = {
293
+ " width" : " 100%" ,
294
+ " height" : " 100%" ,
295
+ " object-fit" : " cover"
290
296
}
297
+
291
298
/* When a camera stream is loaded, we assign the stream to the `video`
292
299
* element via `video.srcObject`. At this point the element used to be
293
300
* hidden with `v-show="false"` aka. `display: none`. We do that because
@@ -300,8 +307,17 @@ const onLocate = (detectedCodes: DetectedBarcode[]) => {
300
307
* element was hidden with `display: none`. Using `visibility: hidden`
301
308
* instead seems to have fixed the problem though.
302
309
*/
303
- .qrcode-stream-camera--hidden {
304
- visibility : hidden ;
305
- position : absolute ;
306
- }
307
- </style >
310
+ const videoElStyle = computed <CSSProperties >(() => {
311
+ if (shouldScan .value ) {
312
+ return cameraStyle
313
+ } else {
314
+ return {
315
+ ... cameraStyle ,
316
+
317
+ " visibility" : " hidden" ,
318
+ " position" : " absolute" ,
319
+ }
320
+ }
321
+ })
322
+
323
+ </script >
0 commit comments