npm install @v3layout/vue3-grid-layout
key 为唯一值,自定义拖动位置修改 dragType= "customdrag"
<template>
<VGL
class="layout"
v-model="state.layout"
:cols="12"
:rowHeight="30"
:width="1200"
dragType="customdrag"
>
<div key="a">a</div>
<div key="b">b</div>
<div key="c">c</div>
</VGL>
</template>
<script>
import VGL from "@v3layout/vue3-grid-layout";
import { defineComponent, ref } from "vue";
export default defineComponent({
components: {
VGL,
},
setup() {
const layout = [
{ i: "a", x: 0, y: 0, w: 1, h: 2, static: true },
{ i: "b", x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 },
{ i: "c", x: 4, y: 0, w: 1, h: 2 },
];
const state = reactive({
layout,
});
return {
state,
};
},
});
</script>
您也可以选择直接在子对象上设置布局属性:
<template>
<GridLayout class="layout" :cols="12" :rowHeight="30" :width="1200">
<div key="a" :data-grid="{ x: 0, y: 0, w: 1, h: 2, static: true }">
a
</div>
<div key="b" :data-grid="{ x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }"">
b
</div>
<div key="c" :data-grid="{ x: 4, y: 0, w: 1, h: 2 }">
c
</div>
</GridLayout>
</template>
<script>
import VGL from "@v3layout/vue3-grid-layout";
import { defineComponent, ref } from 'vue';
export default defineComponent({
components: {
VGL
}
});
</script>
要使 VGL 响应,请使用“”元素:
<template>
<ResponsiveGridLayout
class="layout"
:layouts="state.layouts"
:breakpoints="{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }"
:cols="{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }"
>
<div
v-for="(l, i) in state.layouts.lg"
:key="i + 1"
:class="{ static: l.static }"
>
<span
v-if="l.static"
class="text"
title="This item is static and cannot be removed or resized."
>
Static - {{ i }}
</span>
<span v-else class="text">{{ i }}</span>
</div>
</ResponsiveGridLayout>
</template>
<script>
import { Responsive as ResponsiveGridLayout } from "@v3layout/vue3-grid-layout";
import { defineComponent, ref } from "vue";
export default defineComponent({
components: {
VGL,
},
setup() {
const generateLayout = () => {
return Array.from({ length: 10 }, (item, i) => {
const y = Math.ceil(Math.random() * 4) + 1;
return {
x: Math.round(Math.random() * 5) * 2,
y: Math.floor(i / 6) * y,
w: 2,
h: y,
i: (i + 1).toString(),
static: Math.random() < 0.05,
};
});
};
const state = {
layouts: { lg: generateLayout() },
};
return {
state,
};
},
});
</script>
在响应模式下,您应该通过“layouts”属性提供至少一个断点。
使用“布局”时,最好提供尽可能多的断点,尤其是最大的断点。 如果提供了最大值,VGL 将尝试插值其余值。
您还需要提供一个“宽度”,当使用“”时,建议您使用 HOC `WidthProvider”按照以下说明。
可以通过个人的“数据网格”属性提供默认映射 项目,以便在布局插值中考虑它们。
“”和“”都使用“宽度”来计算 拖动事件上的位置。在简单情况下,HOC“宽度提供者”可用于自动确定 初始化时的宽度和窗口大小调整事件。
<template>
<ResponsiveGridLayout
class="layout"
:layouts="state.layouts"
:breakpoints="{ lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 }"
:cols="{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }"
>
<div
v-for="(l, i) in state.layouts.lg"
:key="i + 1"
:class="{ static: l.static }"
>
<span
v-if="l.static"
class="text"
title="This item is static and cannot be removed or resized."
>
Static - {{ i }}
</span>
<span v-else class="text">{{ i }}</span>
</div>
</ResponsiveGridLayout>
</template>
<script>
import { Responsive, WidthProvider } from "@v3layout/vue-grid-layout";
import { defineComponent, ref } from "vue";
const ResponsiveGridLayout = WidthProvider(Responsive);
export default defineComponent({
components: {
VGL,
},
setup() {
const generateLayout = () => {
return Array.from({ length: 10 }, (item, i) => {
const y = Math.ceil(Math.random() * 4) + 1;
return {
x: Math.round(Math.random() * 5) * 2,
y: Math.floor(i / 6) * y,
w: 2,
h: y,
i: (i + 1).toString(),
static: Math.random() < 0.05,
};
});
};
const state = {
layouts: { lg: generateLayout() },
};
return {
state,
};
},
});
</script>
如果您需要更复杂的逻辑,这允许您轻松地用自己的 Provider HOC 替换“WidthProvider”。
`WidthProvider 接受单个道具“measureBeforeMount”。如果为“true”,则“WidthProvider”将测量 安装儿童之前的集装箱宽度。如果您想完全消除任何调整大小的动画,请使用此功能 在应用程序/组件安装时。
VGL 支持以下属性(详见源代码):
//
// 基础属性
//
// 宽度
width: number,
// 是否自定大小
autoSize?: boolean = true,
// 列数
cols?: number = 12,
// 取消文字
draggableCancel?: string = '',
// A CSS selector for tags that will act as the draggable handle.
// For example: draggableHandle:'.MyDragHandleClassName'
// If you forget the leading . it will not work.
draggableHandle?: string = '',
// Compaction type.
compactType?: ('vertical' | 'horizontal' | null) = 'vertical';
// 布局属性
layout?: Array<{i?: string, x: number, y: number, w: number, h: number}> = null, // If not provided, use data-grid props on children
// 间距属性
margin?: [number, number] = [10, 10],
// 内间距属性
containerPadding?: [number, number] = margin,
// 高度
rowHeight?: number = 150,
// Configuration of a dropping element. Dropping element is a "virtual" element
// which appears when you drag over some element from outside.
// It can be changed by passing specific parameters:
// i - id of an element
// w - width of an element
// h - height of an element
droppingItem?: { i: string, w: number, h: number }
//
// Flags
//
isDraggable?: boolean = true,
isResizable?: boolean = true,
isBounded?: boolean = false,
// Uses CSS3 translate() instead of position top/left.
// This makes about 6x faster paint performance
useCSSTransforms?: boolean = true,
// If parent DOM node of ResponsiveVueGridLayout or VueGridLayout has "transform: scale(n)" css property,
// we should set scale coefficient to avoid render artefacts while dragging.
transformScale?: number = 1,
// If true, grid can be placed one over the other.
// If set, implies `preventCollision`.
allowOverlap?: boolean = false,
// If true, grid items won't change position when being
// dragged over. If `allowOverlap` is still false,
// this simply won't allow one to drop on an existing object.
preventCollision?: boolean = false,
// If true, droppable elements (with `draggable={true}` attribute)
// can be dropped on the grid. It triggers "onDrop" callback
// with position and event object as parameters.
// It can be useful for dropping an element in a specific position
isDroppable?: boolean = false,
// Defines which resize handles should be rendered.
// Allows for any combination of:
// 's' - South handle (bottom-center)
// 'w' - West handle (left-center)
// 'e' - East handle (right-center)
// 'n' - North handle (top-center)
// 'sw' - Southwest handle (bottom-left)
// 'nw' - Northwest handle (top-left)
// 'se' - Southeast handle (bottom-right)
// 'ne' - Northeast handle (top-right)
//
resizeHandles?: Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se'],
// class to the `draggableCancel` prop.
resizeHandle?: VNode
| ((
resizeHandleAxis: ResizeHandleAxis,
ref: VueRef<HTMLElement>
) => VNode)
//
// Callbacks
//
// Callback so you can save the layout.
// Calls back with (currentLayout) after every drag or resize stop.
onLayoutChange: (layout: Layout) => void,
//
// All callbacks below have signature (layout, oldItem, newItem, placeholder, e, element).
// 'start' and 'stop' callbacks pass `undefined` for 'placeholder'.
//
type ItemCallback = (layout: Layout, oldItem: LayoutItem, newItem: LayoutItem,
placeholder: LayoutItem, e: MouseEvent, element: HTMLElement) => void,
// Calls when drag starts.
onDragStart: ItemCallback,
// Calls on each drag movement.
onDrag: ItemCallback,
// Calls when drag is complete.
onDragStop: ItemCallback,
// Calls when resize starts.
onResizeStart: ItemCallback,
// Calls when resize movement happens.
onResize: ItemCallback,
// Calls when resize is complete.
onResizeStop: ItemCallback,
// Calls when an element has been dropped into the grid from outside.
onDrop: (layout: Layout, e: Event, item?: LayoutItem) => void,
// Calls when an element is being dragged over the grid from outside as above.
// This callback should return an object to dynamically change the droppingItem size
// Return false to short-circuit the dragover
onDropDragOver: (e: DragEvent) => { w?: number; h?: number } | false;
// Ref for getting a reference for the grid's wrapping div.
innerRef?: Ref<"div">
可以改用响应式网格布局。它支持上述所有道具,除了“布局”。 新属性和更改如下:
// {name: pxVal}, e.g. {lg: 1200, md: 996, sm: 768, xs: 480}
// Breakpoint names are arbitrary but must match in the cols and layouts objects.
breakpoints?: Object = {lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0},
// # cols -> 设置
cols?: Object = {lg: 12, md: 10, sm: 6, xs: 4, xxs: 2},
// margin (in pixels). Can be specified either as horizontal and vertical margin, e.g. `[10, 10]` or as a breakpoint -> margin map, e.g. `{lg: [10, 10], md: [10, 10], ...}.
margin: [number, number],
// containerPadding (in pixels). Can be specified either as horizontal and vertical padding, e.g. `[10, 10]` or as a breakpoint -> containerPadding map, e.g. `{lg: [10, 10], md: [10, 10], ...}.
containerPadding: [number, number],
// layouts is an object mapping breakpoints to layouts.
// e.g. {lg: Layout, md: Layout, ...}
layouts,
//
// Emit
//
// 使用断点和新#cols进行回调
onBreakpointChange: (newBreakpoint: string, newCols: number) => void,
// 回调,以便保存布局。
// 所有布局都由断点设置关键帧。
onLayoutChange: (currentLayout: Layout, allLayouts) => void,
// 宽度更改时回调,以便您可以根据需要修改布局。
onWidthChange: (containerWidth: number, margin: [number, number], cols: number, containerPadding: [number, number]) => void;
VGL 支持网格项或布局项上的以下属性。当初始化网格时, 构建布局数组(如上面的第一个示例),或将此对象附加为“数据网格”属性 每个子元素(如第二个示例)。
如果在项目上提供了“数据网格”,则它将优先于“布局”中具有相同键(“i”)的项目。
请注意,如果提供了一个网格项但不完整(缺少“x、y、w 或 h”中的一个),则会出现错误 将被抛出,以便您更正布局。
如果没有为网格项提供属性,则将生成一个宽度和高度为“1”的属性。
您可以为每个维度设置最小值和最大值。这是为了调整大小;如果调整大小,当然没有效果 已禁用。如果你的分钟和最大值重叠不正确,或者你的初始尺寸不正确,就会抛出错误 超出范围。
直接定义的任何“”属性都将优先于全局设置的选项。For 例如,如果布局具有属性“isDraggable:false”,但网格项具有道具“isDraggable:true”,则该项 将是可拖动的,即使该项标记为“static:true”。
{
// 唯一key值
i: string,
// 这些都是网格单位,而不是像素
x: number,
y: number,
w: number,
h: number,
minW?: number = 0,
maxW?: number = Infinity,
minH?: number = 0,
maxH?: number = Infinity,
// 拖动位置和拖动尺寸都需要
static?: boolean = false,
// 是否是要拖动位置
isDraggable?: boolean = true,
// 是否需要拖动尺寸
isResizable?: boolean = true,
// 默认情况下,控制柄仅显示在右下角(东南角).
resizeHandles?: Array<'s' | 'w' | 'e' | 'n' | 'sw' | 'nw' | 'se' | 'ne'> = ['se']
// 若为true且可拖动,则项目将仅在网格内移动。
isBounded?: boolean = false
}
网格项宽度基于容器和列数。网格单元高度的大小基于“rowHeight”。
请注意,具有“h=2”的项的高度n 不是具有“h=1”的项高度的两倍,除非您没有“margin”!
为了使网格不参差不齐,当一个项目跨越网格单位时,它也必须跨越边距。因此,您必须为每个单位添加高度、宽度或边距。因此,实际像素高度为“(行高度h)+(边距 h(h-1)”。
例如,当“rowHeight=30”、“margin=[10,10]”和高度为 4 的单位时,计算结果为“(304)+(103)”`
如果这对您来说是个问题,请设置margin=[0,0]
,并在元素内容内处理元素之间的视觉间距。
MIT