我找到了一个解决方案,可以根据可用空间修复网格布局高度。为此,我使用了以下道具:max-rows、row-height、margins、autoSize=false
ResizeObserver 将在窗口调整大小后根据可用高度调整网格布局行高。另请注意,我使用了一些 Bootstrap 类进行样式化
<template>
<div class="flex-grow-1 w-100">
<grid-layout
:layout="layout"
:col-num="colCount"
:maxRows="rowCount"
:row-height="rowHeight"
:autoSize="false"
:is-draggable="true"
:is-resizable="true"
:is-mirrored="false"
:preventCollision="true"
:vertical-compact="false"
:margin="margin"
:use-css-transforms="true"
>
<grid-item
v-for="item in layout"
class="bg-primary"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:key="item.i"
>
<span class="remove" @click="removeItem(item.i)">x</span>
</grid-item>
</grid-layout>
</div>
</template>
<script lang="ts">
import { defineComponent } from '@vue/runtime-core';
interface GridItem {
x: number;
y: number;
w: number;
h: number;
i: string;
}
interface State {
layout: GridItem[];
index: number;
colCount: number;
rowCount: number;
rowHeight: number;
observer: null | ResizeObserver;
margin: number[];
}
export default defineComponent({
name: 'VideoWall',
data(): State {
return {
layout: [
{ x: 0, y: 0, w: 2, h: 2, i: '0' },
{ x: 2, y: 0, w: 2, h: 4, i: '1' },
{ x: 4, y: 0, w: 2, h: 5, i: '2' },
{ x: 6, y: 0, w: 2, h: 3, i: '3' },
{ x: 8, y: 0, w: 2, h: 3, i: '4' },
],
index: 0,
colCount: 36,
rowCount: 36,
rowHeight: 40,
margin: [5, 5],
observer: null,
};
},
mounted() {
this.observer = new ResizeObserver(this.onResize);
if (this.$el instanceof Element) {
this.observer.observe(this.$el);
} else {
console.log('VideoWall: Failed to bind observer');
}
},
unmounted() {
if (this.observer) {
this.observer.disconnect();
}
},
methods: {
onResize(entries: ResizeObserverEntry[]): void {
this.rowHeight =
Math.floor(entries[0].contentRect.height / this.rowCount) -
this.margin[1];
},
},
});
</script>