From 1f25a75cec5fb95f3fd75f6264d3442c7160d6fe Mon Sep 17 00:00:00 2001 From: Justin Georgi Date: Wed, 6 Mar 2024 14:36:27 -0700 Subject: [PATCH] Split detect.vue (#122) Closes: #112 New mixins for camera and detection (remote and local) and new css for detection page. Reviewed-on: https://gitea.azgeorgis.net/ALVINN/ALVINN_f7/pulls/122 --- src/css/detect.css | 183 +++++++++++ src/pages/camera-mixin.js | 45 +++ src/pages/detect.vue | 305 ++---------------- .../{local-detect.js => detection-mixin.js} | 65 ++++ 4 files changed, 312 insertions(+), 286 deletions(-) create mode 100644 src/css/detect.css create mode 100644 src/pages/camera-mixin.js rename src/pages/{local-detect.js => detection-mixin.js} (54%) diff --git a/src/css/detect.css b/src/css/detect.css new file mode 100644 index 0000000..7fba46f --- /dev/null +++ b/src/css/detect.css @@ -0,0 +1,183 @@ +/*Styles for the structure detection page*/ +/*Basic style*/ +.detect-grid { + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr 56px auto min-content; + grid-template-areas: + "image-view" + "result-view" + "detect-settings" + "menu-view"; + justify-items: center; + height: calc(100% - var(--f7-navbar-height) - var(--f7-safe-area-top) - var(--f7-safe-area-bottom)); + max-height: calc(100% - var(--f7-navbar-height) - var(--f7-safe-area-top) - var(--f7-safe-area-bottom)); +} + +.image-container { + grid-area: image-view; + width: 100%; + height: 100%; + min-width: 0; + min-height: 0; + position: relative; + display: flex; + align-self: stretch; +} + +.popover-button-menu { + max-width: 90vw; + max-height: 90vh; + width: auto; +} + +.segment-button-menu { + flex-wrap: nowrap; + flex-direction: column; + max-height: 100%; + min-height: 0px; +} + +.chip-media { + background-color: var(--chip-media-background) !important; +} + +.chip-results { + display: flex; + flex-wrap: wrap; + gap: 5px; + padding: 10px; + --f7-chip-border-radius: 16px; + --f7-chip-media-size: 32px; + --f7-chip-font-weight: normal; + overflow-y: auto; + max-height: 100%; +} + +.chip-results .chip { + padding-left: 8px; +} + +.selected-chip { + font-weight: 500; + box-shadow: 4px 4px 1px var(--avn-theme-color); + transform: translate(-2px, -2px); +} + +.detect-inputs { + display: flex; + align-items: center; + margin: 5px; + width: 100%; + max-width: 400px; + min-width: 192px; +} + +.level-slide-vert { + display: none; +} + +.image-menu { + grid-area: menu-view; + margin: 5px; + max-width: 400px; + min-width: 192px; +} + +.image-menu .button { + aspect-ratio: 1; + height: auto; + padding: 5px; + flex: 1 1 0%; +} + +.image-menu > .button > svg { + aspect-ratio: 1; + height: auto; + width: 100%; +} + +.segment-button-menu .button { + padding: 8px; + aspect-ratio: 1; + width: auto; + flex: 1 1 0%; + max-height: 100px; + max-width: 100px; +} + +/*Additional styles for small format landscape orientation*/ +@media (max-height: 450px) and (orientation: landscape) { + .detect-grid { + grid-template-columns: minmax(0,1fr) minmax(56px,max-content) auto auto; + grid-template-rows: calc(100vh - var(--f7-navbar-height) - var(--f7-safe-area-top) - var(--f7-safe-area-bottom) - 64px); + grid-template-areas: + "image-view result-view detect-settings menu-view"; + justify-items: stretch; + align-items: stretch; + height: calc(100% - var(--f7-navbar-height) - var(--f7-safe-area-top) - var(--f7-safe-area-bottom)); + max-height: calc(100% - var(--f7-navbar-height) - var(--f7-safe-area-top) - var(--f7-safe-area-bottom)); + position: relative; + } + + .chip-results { + flex-direction: column; + max-height: 100%; + justify-self: start; + flex-wrap: nowrap; + } + + .detect-inputs { + flex-direction: column; + min-width: 0; + max-width: 72px; + } + + .level-slide-horz { + display: none; + } + + .level-slide-vert { + display: block; + } + + + .image-container { + flex-direction: column; + } + + .image-menu { + flex-direction: column; + aspect-ratio: .25; + width: auto; + min-width: 0; + height: 100%; + } + + .image-menu .button { + aspect-ratio: 1; + width: auto; + height: 100%; + flex: 1 1 0%; + border-bottom: 1px solid var(--f7-segmented-raised-divider-color); + border-bottom-left-radius: 0px !important; + } + + .segment-button-menu { + flex-direction: row; + max-height: 100%; + min-height: 0px; + } + + .segment-button-menu .button { + height: auto; + flex: 1 1 0%; + max-height: 100px; + max-width: 100px; + } + + .button > svg { + width: 100%; + height: auto; + } +} diff --git a/src/pages/camera-mixin.js b/src/pages/camera-mixin.js new file mode 100644 index 0000000..a40539a --- /dev/null +++ b/src/pages/camera-mixin.js @@ -0,0 +1,45 @@ +export default { + methods: { + async openCamera() { + var cameraLoaded = false + const devicesList = await navigator.mediaDevices.enumerateDevices() + this.videoDeviceAvailable = devicesList.some( d => d.kind == "videoinput") + if (this.videoDeviceAvailable) { + navigator.mediaDevices.getUserMedia({video: true}) + var vidConstraint = { + video: { + width: { + ideal: 1920 + }, + height: { + ideal: 1080 + }, + facingMode: 'environment' + }, + audio: false + } + const stream = await navigator.mediaDevices.getUserMedia(vidConstraint); + cameraLoaded = true + this.cameraStream = stream + } + return cameraLoaded + }, + closeCamera () { + this.cameraStream.getTracks().forEach( t => t.stop()) + this.videoAvailable = false + }, + captureVidFrame() { + const vidViewer = this.$refs.vid_viewer + vidViewer.pause() + let tempCVS = document.createElement('canvas') + tempCVS.height = vidViewer.videoHeight || parseInt(vidViewer.style.height) + tempCVS.width = vidViewer.videoWidth || parseInt(vidViewer.style.width) + const tempCtx = tempCVS.getContext('2d') + tempCtx.drawImage(vidViewer, 0, 0) + this.getImage(tempCVS.toDataURL()) + }, + async videoStream() { + //TODO + } + } +} \ No newline at end of file diff --git a/src/pages/detect.vue b/src/pages/detect.vue index 5800a42..d46a385 100644 --- a/src/pages/detect.vue +++ b/src/pages/detect.vue @@ -99,189 +99,7 @@ - +