@v3layout/vue3-grid-layout
TypeScript icon, indicating that this package has built-in type declarations

1.0.4 • Public • Published

vue3 draggable Layout

## 安装
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”按照以下说明。

可以通过个人的“数据网格”属性提供默认映射 项目,以便在布局插值中考虑它们。

Providing Grid Width

“”和“”都使用“宽度”来计算 拖动事件上的位置。在简单情况下,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”将测量 安装儿童之前的集装箱宽度。如果您想完全消除任何调整大小的动画,请使用此功能 在应用程序/组件安装时。

Grid Layout Props

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">

Responsive Grid Layout Props

可以改用响应式网格布局。它支持上述所有道具,除了“布局”。 新属性和更改如下:

// {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;

Grid Item Props

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
}

Grid Item Heights 和 Widths

网格项宽度基于容器和列数。网格单元高度的大小基于“rowHeight”。

请注意,具有“h=2”的项的高度n 不是具有“h=1”的项高度的两倍,除非您没有“margin”

为了使网格不参差不齐,当一个项目跨越网格单位时,它也必须跨越边距。因此,您必须为每个单位添加高度、宽度或边距。因此,实际像素高度为“(行高度h)+(边距 h(h-1)”。

例如,当“rowHeight=30”、“margin=[10,10]”和高度为 4 的单位时,计算结果为“(304)+(103)”`

如果这对您来说是个问题,请设置margin=[0,0],并在元素内容内处理元素之间的视觉间距。

License

MIT

Readme

Keywords

Package Sidebar

Install

npm i @v3layout/vue3-grid-layout

Weekly Downloads

15

Version

1.0.4

License

MIT

Unpacked Size

206 kB

Total Files

17

Last publish

Collaborators

  • zjy-web