mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-21 01:01:41 +00:00
Take Snapshots from PhotonClient (#940)
This commit is contained in:
@@ -4,13 +4,14 @@ import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
|
||||
import { useStateStore } from "@/stores/StateStore";
|
||||
import loadingImage from "@/assets/images/loading.svg";
|
||||
import type { StyleValue } from "vue/types/jsx";
|
||||
import CvIcon from "@/components/common/cv-icon.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
streamType: "Raw" | "Processed";
|
||||
id?: string;
|
||||
}>();
|
||||
|
||||
const src = computed<string>(() => {
|
||||
const streamSrc = computed<string>(() => {
|
||||
const port =
|
||||
useCameraSettingsStore().currentCameraSettings.stream[props.streamType === "Raw" ? "inputPort" : "outputPort"];
|
||||
|
||||
@@ -20,25 +21,74 @@ const src = computed<string>(() => {
|
||||
|
||||
return `http://${inject("backendHostname")}:${port}/stream.mjpg`;
|
||||
});
|
||||
const alt = computed<string>(() => `${props.streamType} Stream View`);
|
||||
|
||||
const style = computed<StyleValue>(() => {
|
||||
const streamDesc = computed<string>(() => `${props.streamType} Stream View`);
|
||||
const streamStyle = computed<StyleValue>(() => {
|
||||
if (useStateStore().colorPickingMode) {
|
||||
return { cursor: "crosshair" };
|
||||
} else if (src.value !== loadingImage) {
|
||||
return { cursor: "pointer" };
|
||||
return { width: "100%", cursor: "crosshair" };
|
||||
} else if (streamSrc.value !== loadingImage) {
|
||||
return { width: "100%", cursor: "pointer" };
|
||||
}
|
||||
|
||||
return {};
|
||||
return { width: "100%" };
|
||||
});
|
||||
|
||||
const handleClick = () => {
|
||||
if (!useStateStore().colorPickingMode && src.value !== loadingImage) {
|
||||
window.open(src.value);
|
||||
const overlayStyle = computed<StyleValue>(() => {
|
||||
if (useStateStore().colorPickingMode || streamSrc.value == loadingImage) {
|
||||
return { display: "none" };
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
|
||||
const handleStreamClick = () => {
|
||||
if (!useStateStore().colorPickingMode && streamSrc.value !== loadingImage) {
|
||||
window.open(streamSrc.value);
|
||||
}
|
||||
};
|
||||
const handleCaptureClick = () => {
|
||||
if (props.streamType === "Raw") {
|
||||
useCameraSettingsStore().saveInputSnapshot();
|
||||
} else {
|
||||
useCameraSettingsStore().saveOutputSnapshot();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img :id="id" crossorigin="anonymous" :src="src" :alt="alt" :style="style" @click="handleClick" />
|
||||
<div class="stream-container">
|
||||
<img
|
||||
:id="id"
|
||||
crossorigin="anonymous"
|
||||
:src="streamSrc"
|
||||
:alt="streamDesc"
|
||||
:style="streamStyle"
|
||||
@click="handleStreamClick"
|
||||
/>
|
||||
<div class="stream-overlay" :style="overlayStyle">
|
||||
<cv-icon
|
||||
icon-name="mdi-camera-image"
|
||||
tooltip="Capture and save a frame of this stream"
|
||||
class="ma-1 mr-2"
|
||||
@click="handleCaptureClick"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.stream-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.stream-overlay {
|
||||
opacity: 0;
|
||||
transition: 0.1s ease;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.stream-container:hover .stream-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -384,7 +384,7 @@ const endCalibration = () => {
|
||||
color="secondary"
|
||||
style="width: 100%"
|
||||
:disabled="!settingsValid"
|
||||
@click="isCalibrating ? useCameraSettingsStore().takeCalibrationSnapshot(true) : startCalibration()"
|
||||
@click="isCalibrating ? useCameraSettingsStore().takeCalibrationSnapshot() : startCalibration()"
|
||||
>
|
||||
{{ isCalibrating ? "Take Snapshot" : "Start Calibration" }}
|
||||
</v-btn>
|
||||
|
||||
@@ -41,7 +41,7 @@ const fpsTooLow = computed<boolean>(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<v-card class="mb-3 pr-6 pb-3 pa-4" color="primary" dark>
|
||||
<v-card class="mb-3 pb-3 pa-4" color="primary" dark>
|
||||
<v-card-title
|
||||
class="pb-0 mb-2 pl-4 pt-1"
|
||||
style="min-height: 50px; justify-content: space-between; align-content: center"
|
||||
@@ -133,16 +133,16 @@ th {
|
||||
.stream {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 512px) and (max-width: 960px) {
|
||||
.stream-container {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.stream {
|
||||
width: 50%;
|
||||
max-width: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user