vue-grid-layout是一个vue栅格拖动布局的组件.
官网
栅格布局,即网格布局,是一种新的
CSS
布局模型,比较擅长将一个页面划分为几个主要区域,以及定义这些区域的大小、位置、层次等关系。
与flex布局的区别:
-
Flexbox 是一维布局系统,适合做局部布局,比如导航栏组件。
-
网格布局是二维布局系统,可以更好的操作行和列,通常用于整个页面的规划。
-
虽然 Flexbox 也可以用于大的页面布局,但是没有 网格布局强大和灵活。二者结合使用更加轻松。二者从应用场景来说并不冲突。
-
flex 布局一次只能处理一个维度上的元素布局,一行或者一列(flex-direction)。网格布局是将容器划分成了“行”和“列”,产生了一个个的网格,我们可以将网格元素放在与这些行和列相关的位置上,从而达到我们布局的目的。
vue-grid-layout优点:
-
元素可拖动
-
元素可调整大小
-
边界检查拖动和调整大小
-
可以添加或删除窗口小部件而无需重建网格
-
布局可以
序列化
-
响应式布局
属性 GridLayout常用参数:
参数
|
含义
|
数据类型
|
layout
|
栅格的初始布局
|
Array
|
colNum
|
栅格系统的列数
|
Number 默认 12
|
rowHeight
|
每行的高度
|
Number 默认是单位是 px
|
isDraggable
|
栅格中的元素是否可拖拽
|
Boolean
|
isResizable
|
是否可以改变大小
|
Boolean
|
margin
|
栅格中的元素边距
|
Array
|
属性GridItem参数:
参数
|
含义
|
类型
|
i
|
id
|
类型不限
|
x
|
格元素位于第几列
|
Number
|
y
|
元素位于第几行
|
Number
|
w
|
占几块(元素的初始宽度,值为
colWidth
的倍数)
|
Number
|
h
|
元素的初始高度,值为
rowHeight
的倍数。
|
Number
|
isDraggable
|
元素是否可拖拽
|
Boolean
|
isResizable
|
元素是否可以改变大小
|
Boolean
|
static
|
是否为静态的(无法拖拽、调整大小或被其他元素移动)
|
Boolean
|
每一个栅格元素grid-item上都可以添加监听器,用于监听移动和调整大小事件,这样父级Vue对象就可以收到通知。
GridLayout:
事件
|
含义
|
layoutCreatedEvent
|
对应Vue生命周期的created
|
layoutBeforeMountEvent
|
对应Vue生命周期的beforeMount
|
layoutMountedEvent
|
对应Vue生命周期的mounted
|
layoutReadyEvent
|
当完成mount中的所有操作时生成的事件
|
layoutUpdatedEvent
|
布局updated事件
|
GridItem:
事件
|
含义
|
moveRvent
|
移动时的事件
|
resizeRvent
|
调整大小时的事件
|
mocedRvent
|
移动后的事件
|
resizedRvent
|
调整大小后的事件
|
containerResizedRvent
|
栅格元素/栅格容器更改大小的事件(浏览器窗口或其他)
|
<grid-layout
:layout.sync="layout"
:col-num="12"
:row-height="30"
:is-draggable="true"
:is-resizable="true"
:is-mirrored="false"
:vertical-compact="true"
:margin="[10, 10]"
:use-css-transforms="true"
<grid-item v-for="item in layout"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
:i="item.i"
:key="item.i">
<span class="text">{{item.i}}</span>
<span class="remove" @click="removeItem(item.i)">x</span>
</grid-item>
</grid-layout>
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"},
源码解析:
1、栅格布局实现逻辑:
往grid-item上面放style样式,当标识是否使用CSS属性 useCssTransforms为true时,则使用
transform来定位;(默认为true)
export function setTransform(top, left, width, height): Object {
// Replace unitless items with px
const translate = 'translate3d(' + left + 'px,' + top + 'px, 0)'
return {
transform: translate,
WebkitTransform: translate,
MozTransform: translate,
msTransform: translate,
OTransform: translate,
width: width + 'px',
height: height + 'px',
position: 'absolute',
否则使用position定位,设置子元素的top、 left值;
export function setTopLeft(top, left, width, height): Object {
return {
top: top + 'px',
left: left + 'px',
width: width + 'px',
height: height + 'px',
position: 'absolute',
2、拖拽、缩放等交互;
使用的前端拖拽插件interact.js,提供拖,放,调整尺寸和多点触摸手势功能。
grid-item 通过interact的on方法,监听拖放、调整尺寸等事件。
//将当前拖动元素经过interact实例化之后,即可监听相应的事件
//拖拽事件
this.interactObj.on('dragstart dragmove dragend', function (event) {
self.handleDrag(event)
//缩放事件
this.interactObj.on('resizestart resizemove resizeend',function (event) {
self.handleResize(event)
//元素拖拽时
handleDrag(event) {
//如果禁止拖拽、调整大小则reture
if (this.static) return
if (this.isResizing) return
const position = getControlPosition(event) // 从事件中获取当前拖动点。这是用作偏移量的。
// Get the current drag point from the event. This is used as the offset.
if (position === null) return // not possible but satisfies flow
const { x, y } = position
// let shouldUpdate = false;
let newPosition = { top: 0, left: 0 }
//通过监听拖拽事件,将拖拽的位置赋值给newPosition
switch (event.type) {
case 'dragstart': {
this.previousX = this.innerX
this.previousY = this.innerY
//元素的父级视图定位
let parentRect =event.target.offsetParent.getBoundingClientRect()//offsetParent为离自身最近且经过定位的父元素
//元素的视图定位
let clientRect = event.target.getBoundingClientRect()
//是否为镜像反转
//计算出当前模块left与top的距离
if (this.renderRtl) {
newPosition.left = (clientRect.right - parentRect.right) * -1
} else {
newPosition.left = clientRect.left - parentRect.left
newPosition.top = clientRect.top - parentRect.top
this.dragging = newPosition
console.log('dragstart====', this.dragging)
this.isDragging = true
break
case 'dragend': {
if (!this.isDragging) return
let parentRect = event.target.offsetParent.getBoundingClientRect()
let clientRect = event.target.getBoundingClientRect()
// Add rtl support
if (this.renderRtl) {
newPosition.left = (clientRect.right - parentRect.right) * -1
} else {
newPosition.left = clientRect.left - parentRect.left
newPosition.top = clientRect.top - parentRect.top
// console.log("### drag end => " + JSON.stringify(newPosition));
// console.log("### DROP: " + JSON.stringify(newPosition));
this.dragging = null
console.log('dragend====', this.dragging)
this.isDragging = false
// shouldUpdate = true;
break
case 'dragmove': {
const coreEvent = createCoreData(this.lastX, this.lastY, x, y)
// Add rtl support
if (this.renderRtl) {
newPosition.left = this.dragging.left - coreEvent.deltaX
} else {
newPosition.left = this.dragging.left + coreEvent.deltaX
newPosition.top = this.dragging.top + coreEvent.deltaY
this.dragging = newPosition
console.log('dragmove====', this.dragging)
break
// Get new XY
//根据left与top的计算出当前模块在XY的值(通过四舍五入的方式)
let pos
if (this.renderRtl) {
pos = this.calcXY(newPosition.top, newPosition.left)
} else {
pos = this.calcXY(newPosition.top, newPosition.left)
this.lastX = x
this.lastY = y
//仅用来打印
if (this.innerX !== pos.x || this.innerY !== pos.y) {
this.$emit('move', this.i, pos.x, pos.y)
event.type === 'dragend' &&
(this.previousX !== this.innerX || this.previousY !== this.innerY)
this.$emit('moved', this.i, pos.x, pos.y)
//将拖动时的位置数据传给容器,容器对layout与占位空间赋值
this.eventBus.$emit(
'dragEvent',
event.type,
this.i,
pos.x,
pos.y,
this.innerH,
this.innerW
// 拖渲染页面
dragEvent: function (eventName, id, x, y, h, w) {
//获取到当前的拖动的元素
let l = getLayoutItem(this.layout, id)
//GetLayoutItem sometimes returns null object
if (l === undefined || l === null) {
l = { x: 0, y: 0 }
//当拖动为dragmove、dragstart时,赋值占位符的位置
if (eventName === 'dragmove' || eventName === 'dragstart') {
this.placeholder.i = id
this.placeholder.x = l.x
this.placeholder.y = l.y
this.placeholder.w = w
this.placeholder.h = h
this.$nextTick(function () {
this.isDragging = true
//this.$broadcast("updateWidth", this.width);
this.eventBus.$emit('updateWidth', this.width)
} else {
this.$nextTick(function () {
this.isDragging = false
// Move the element to the dragged location.
//获取到其他元素的级联动作,将元素移动到拖动位置。
this.layout = moveElement(
this.layout,
true,
this.preventCollision//防止碰撞属性
compact(this.layout, this.verticalCompact)
// needed because vue can't detect changes on array element properties
//让vue检测到数组元素属性的变化
this.eventBus.$emit('compact')
this.updateHeight()
if (eventName === 'dragend') this.$emit('layout-updated', this.layout)
相关问题:
- 标识栅格元素是否可拖拽(isDraggable)该属性只能将元素向下排,并不能形成左右替换的形式,并且在该组件中也没有元素互相替换位置这种属性;
- GridItem的XY参数,只能为整数;
- 没有下边界,发生碰撞的时候块会无限的往下移动;
视图页面中每一个面板都可拖拽,可随意放大放小,体验还是不错的。
vue-grid-layout是一个vue栅格拖动布局的组件.官网特点: 元素可拖动 元素可调整大小 边界检查拖动和调整大小 可以添加或删除窗口小部件而无需重建网格 布局可以序列化 标识栅格元素是否可拖拽该属性只能将元素向下排,并不能形成左右替换的形式 属性 GridLayout常用参数:参数 含义 数据类型 colNum 将一行分为多少块 数字 默认 12 rowHeight 行高 ...
布局//上半部分
<com.example.lenovo.pandachannel.base.GridLayout
android:id="@+id/drable_grid1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
and...
最近领导要求系统首页布局改一下,类似于自助建站那种首页可以实现模块的自定义拖拽,并可以实现保存等功能,一下让我这种VUE新手有点慌张,上网上搜一下也没有对应的结局方案,那就自己写吧。不过最终磕磕绊绊也算是实现了。废话不多说,先上功能。
首先首页实现功能卡片定义,并可自定义调整大小存储等,卡片内容随意定义
多种布局可选,布局也可以随意定义
功能卡片的增删等功能(基于layout面板上存在卡片展...
<div :style="setLeftStyle()" class="view"></div>
<div id="line" class="line"></div>
<div :style="setRightStyle()" class="view"></div>
$ npm install @geospoc/v-grid-layout
import VueGridLayout from '@geospoc/v-grid-layout' ;
添加到其他Vue组件
export default {
components : {
GridLayout : VueGridLayout . G
npm install vue-responsive-grid-layout
import {VueResponsiveGridLayout, VueGridItem, VueGridLayout } from 'vue-responsive-grid-layout'
Vue.component
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
有关工作原理的详细说明,请查看的和。
vue-grid-layout
一个可以拖拽的 vue 布局方案
https://www.cnblogs.com/yasoPeng/p/9961732.html // 地址
install with npm
npm install vue-grid-layout --save
install with yarn
yarn add vue-grid-layout
import Vue...
http://www.eoeandroid.com/thread-71624-1-1.html
自定义
gridview 自定义view 自定义adapter ,其中
gridview自定义参照了论坛中代码 我改了蛮多 加上了详细的中文注释,
Vue-grid-layout 是一个基于 Vue.js 的响应式网格布局系统,可以帮助你轻松地实现桌面拖拽布局功能。下面是一个简单的例子:
1. 首先,你需要安装 vue-grid-layout:
npm install vue-grid-layout
2. 在 Vue 组件中引入 vue-grid-layout:
```javascript
import VueGridLayout from 'vue-grid-layout';
3. 在 template 中使用 vue-grid-layout:
```html
<vue-grid-layout :layout="layout" :col-num="12" :row-height="30" :is-draggable="true" :is-resizable="true">
<div v-for="item in layout" :key="item.i">{{ item.i }}</div>
</vue-grid-layout>
其中,`layout` 是一个数组,用于定义每个网格的位置和大小。`col-num` 定义了网格布局的列数,`row-height` 定义了每行网格的高度,`is-draggable` 和 `is-resizable` 分别表示是否可拖拽和可调整大小。
4. 在 JavaScript 中定义 `layout` 数组:
```javascript
data() {
return {
layout: [
{ i: 'a', x: 0, y: 0, w: 1, h: 2 },
{ i: 'b', x: 1, y: 0, w: 3, h: 2 },
{ i: 'c', x: 4, y: 0, w: 1, h: 2 }
其中,`i` 表示网格的 ID,`x` 和 `y` 表示网格的左上角坐标,`w` 和 `h` 表示网格的宽度和高度。
这样,你就可以实现一个简单的网格布局,并且可以拖拽和调整网格的大小。更多详细的用法可以参考 vue-grid-layout 的官方文档。