81 lines
2.1 KiB
Vue
81 lines
2.1 KiB
Vue
<template>
|
|
<div ref="containerElement" class="container">
|
|
<slot ref="containerElement"></slot>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue, Emit } from 'vue-property-decorator';
|
|
import { throttle } from './Throttle';
|
|
|
|
@Component
|
|
export default class Responsive extends Vue {
|
|
private width: number;
|
|
private height: number;
|
|
private observer: ResizeObserver;
|
|
private get container(): HTMLElement { return this.$refs.containerElement as HTMLElement; }
|
|
|
|
public async mounted() {
|
|
this.width = this.container.offsetWidth;
|
|
this.height = this.container.offsetHeight;
|
|
const resizeCallback = throttle(() => this.updateSize(), 200);
|
|
|
|
if ('ResizeObserver' in window === false) {
|
|
const module = await import('@juggle/resize-observer');
|
|
window.ResizeObserver = module.ResizeObserver;
|
|
}
|
|
|
|
this.observer = new window.ResizeObserver(resizeCallback);
|
|
this.observer.observe(this.container);
|
|
this.fireChangeEvents();
|
|
}
|
|
public updateSize() {
|
|
let sizeChanged = false;
|
|
if (this.isWidthChanged()) {
|
|
this.updateWidth(this.container.offsetWidth);
|
|
sizeChanged = true;
|
|
}
|
|
if (this.isHeightChanged()) {
|
|
this.updateHeight(this.container.offsetHeight);
|
|
sizeChanged = true;
|
|
}
|
|
if (sizeChanged) {
|
|
this.$emit('sizeChanged');
|
|
}
|
|
}
|
|
@Emit('widthChanged') public updateWidth(width: number) {
|
|
this.width = width;
|
|
}
|
|
@Emit('heightChanged') public updateHeight(height: number) {
|
|
this.height = height;
|
|
}
|
|
public destroyed() {
|
|
if (this.observer) {
|
|
this.observer.disconnect();
|
|
}
|
|
}
|
|
|
|
private fireChangeEvents() {
|
|
this.updateWidth(this.container.offsetWidth);
|
|
this.updateHeight(this.container.offsetHeight);
|
|
this.$emit('sizeChanged');
|
|
}
|
|
private isWidthChanged(): boolean {
|
|
return this.width !== this.container.offsetWidth;
|
|
}
|
|
private isHeightChanged(): boolean {
|
|
return this.height !== this.container.offsetHeight;
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.container {
|
|
width: 100%;
|
|
height: 100%;
|
|
display: inline-block; // if inline then it has no height or weight
|
|
}
|
|
</style>
|
|
|