Moved to a single ResizeObserver to manage element resizing

This commit is contained in:
jtc42 2019-06-10 19:26:40 +01:00
parent 2327b9b8bf
commit b9651298fc

View file

@ -0,0 +1,215 @@
<template>
<div ref="streamDisplay" class="stream-display uk-width-1-1 uk-height-1-1 scrollTarget" id="stream-display">
<img class="uk-align-center uk-margin-remove-bottom" v-on:dblclick="clickmonitor" v-if="showStream" v-bind:src="streamImgUri" alt="Stream">
<div v-else-if="$store.state.waiting" class="uk-position-center">
<div uk-spinner="ratio: 4.5" ></div>
</div>
<div v-else-if="$store.state.globalSettings.disableStream" class="uk-position-center position-relative text-center">
Stream preview disabled
</div>
<div v-else class="uk-position-center position-relative text-center">
No active connection
</div>
</div>
</template>
<script>
import axios from 'axios'
// Export main app
export default {
name: 'stream-display',
data: function () {
return {
displaySize: [0, 0],
displayPosition: [0, 0],
GpuPreviewActive: false,
resizeTeimoutId: setTimeout(this.doneResizing, 500)
}
},
mounted() {
const context = this;
// A global signal listener to change the GPU preview state
this.$root.$on('globalTogglePreview', (state) => {
console.log(`Toggling preview to ${state}`)
this.previewRequest(state)
})
// Mutation observer
this.sizeObserver = new ResizeObserver(entries => {
context.handleResize() // For any element attached to the observer, run handleResize() on change
entries.forEach(entry => {}) // Optional: Run something per entry
});
// Fetch streamDisplay by ref
const streamDisplayElement = this.$refs.streamDisplay.parentNode;
// Attach streamDisplay to the size observer
this.sizeObserver.observe(streamDisplayElement);
},
created: function () {
// Watch for host 'ready'
this.$store.watch(
(state)=>{
return this.$store.getters.ready
},
(newValue, oldValue)=>{
// 'ready' changed, so do something
this.previewRequest(this.$store.state.globalSettings.autoGpuPreview)
}
)
},
beforeDestroy: function () {
// Disconnect the size observer
this.sizeObserver.disconnect()
},
methods: {
clickmonitor: function(event) {
// Calculate steps from event coordinates and store config FOV
var xCoordinate = event.offsetX;
var yCoordinate = event.offsetY;
var xRelative = (0.5*event.target.offsetWidth - xCoordinate)/event.target.offsetWidth;
var yRelative = (0.5*event.target.offsetHeight - yCoordinate)/event.target.offsetHeight;
var xSteps = xRelative * this.$store.state.apiConfig.fov[0];
var ySteps = yRelative * this.$store.state.apiConfig.fov[1];
// Emit a signal to move, acted on by panelNavigate.vue
this.$root.$emit('globalMoveEvent', xSteps, ySteps, 0, false)
},
handleResize: function(event) {
// Only fires resize event after no resize in 500ms (prevents resize event spam)
clearTimeout(this.resizeTeimoutId);
this.resizeTeimoutId = setTimeout(this.handleDoneResize, 500)
},
handleDoneResize: function() {
// Recalculate size
console.log("Recalculating frame size")
this.recalculateSize();
if (this.$store.state.globalSettings.autoGpuPreview == true && this.GpuPreviewActive == true) {
// Reload preview
this.$root.$emit('globalTogglePreview', true)
}
},
recalculateSize: function () {
console.log("Recalculating window dimensions...")
// Stacking parentNode is a hacky fix
// For some reason, when switching tabs, width was always half what it should be,
// until the size was recalculated at some later time. Probably something to do
// with tab transition. This parentNode stuff instead reads the size of the tab
// container, irrespective of WHICH tab is selected. It's nasty, but works.
console.log("ELEMENT:")
console.log(this.$refs.streamDisplay)
let element = this.$refs.streamDisplay.parentNode.parentNode;
let size = [element.clientWidth, element.clientHeight];
let elem_pos = [element.getBoundingClientRect().left, element.getBoundingClientRect().top];
let wind_pos = [window.screenX, window.screenY];
let navHeight = window.outerHeight - window.innerHeight;
let position = [Math.max(0, wind_pos[0] + elem_pos[0]), Math.max(0, wind_pos[1] + elem_pos[1] + navHeight)];
this.displaySize = size;
console.log(`Size: ${this.displaySize}`)
this.displayPosition = position;
console.log(`Position: ${this.displayPosition}`)
},
previewRequest: function(state) {
if (this.$store.getters.ready == true) {
// Create URI and set this.GpuPreviewActive depending on if starting or stopping preview
if (state == true) {
this.GpuPreviewActive = true
var requestUri = this.startPreviewUri;
}
else {
this.GpuPreviewActive = false;
var requestUri = this.stopPreviewUri;
}
// Generate payload if tracking window position
if (this.$store.state.globalSettings.trackWindow == true && state == true) {
// Recalculate frame dimensions and position
this.recalculateSize()
// Copy data into payload array
var payload = {
window : [
this.displayPosition[0],
this.displayPosition[1],
this.displaySize[0],
this.displaySize[1],
]
}
}
else {
var letpayload = {}
}
// Send preview request
axios.post(requestUri, payload)
.then(response => {
this.$store.dispatch('updateState'); // Update store state
})
.catch(error => {
this.modalError(error) // Let mixin handle error
})
}
},
},
computed: {
showStream: function () {
return this.$store.getters.ready && !this.$store.state.globalSettings.disableStream
},
streamImgUri: function () {
return this.$store.getters.uri + "/stream"
},
startPreviewUri: function () {
return this.$store.getters.uri + "/camera/preview/start"
},
stopPreviewUri: function () {
return this.$store.getters.uri + "/camera/preview/stop"
}
}
}
</script>
<style scoped lang="less">
.stream-display img {
height: 100%;
text-align: center;
object-fit: contain
}
.stream-display {
width: 100%;
height: 100%;
}
.position-relative {
position: relative !important;
}
.text-center {
text-align: center;
}
</style>