项目中遇到要做一个报表的仪表盘,每一个卡片内是一个报表,报表有不同类型,每一种类型有其特定的尺寸。允许选择报表并添加到仪表盘。允许通过拖拽调整每个卡片位置和卡片的大小。最终可以保存布局好的仪表盘。
vue-grid-layout通过维护一个数组(layout)实现拖拽布局,每一个卡片为一个item,每一个item含有坐标,宽高等信息。
因此添加卡片时向数组中添加一个item即可,但是这样新item的坐标总是(0, 0),会将已经布局好的卡片挤走,无法实现选择可容纳卡片的空位添加新元素。
卡片对象有以下属性,其中x, y, w, h是用于记录卡片位置和大小的关键信息,i是卡片的id,需要保证在添加时不出现重复卡片。minW和minH用于规定卡片的最小尺寸,type用于标记该卡片的类型。
// 卡片对象
{
"i":"card1",
"x": 0,
"y": 0,
"w":4,
"h":2,
"minW": 3,
"minH":2,
"type":"typeA"
}
要实现选择可容纳该卡片的空位添加卡片,实际上就是根据现有布局(layout)和新卡片的大小(w和h),算出新卡片的坐标(x和y)。
可分为以下步骤:
<!-- grid-layout组件调用 -->
<grid-layout
:layout.sync="layout"
:col-num="12"
:row-height="72"
:is-draggable="true"
:is-resizable="true"
:is-mirrored="false"
:vertical-compact="true"
:margin="[10, 10]"
:autoSize="true"
: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"
:minW="item.minW"
:minH="item.minH"
:key="item.i">
<!-- 插入你的组件 -->
</grid-item>
</grid-layout>
/* 新增元素方法**/
function addItem(item, itemId, layout) {
// 初始化元素
let newItem = {
...item,
"i": itemId,
"x": 0,
"y": 0,
"w": item.w,
"h": item.h
}
// 确定边界
let Ys = [], maxX = 0, maxY = 0, edgeX = 0, edgeY = 0
layout.map(item => {
Ys.push(item.y + item.h)
})
maxY = Ys.length && Math.max.apply(null, Ys) || 1
edgeX = 12
edgeY = maxY
// 使用二维数组生成地图
let gridMap = new Array()
for (let x = 0; x < edgeX; x++) {
gridMap[x] = new Array()
for (let y = 0; y < edgeY; y++) {
gridMap[x][y] = 0
}
}
// 标记占位
layout.map(item => {
// 将layout中卡片所占区域标记为1
for (let x = item.x; x < (item.x + item.w); x++) {
for (let y = item.y; y < (item.y + item.h); y++) {
gridMap[x][y] = 1
}
}
})
// 遍历地图,申请位置
for (let y = 0; y < edgeY; y++) {
for (let x = 0; x < edgeX; x++) {
// 申请所需空间
if (edgeX - x >= item.w && edgeY - y >= item.h) {
let itemSignArr = []
for (let a = x; a < (x + item.w); a++) {
for (let b = y; b < (y + item.h; b++)) {
itemSignArr.push(gridMap[x][y])
}
}
if (itemSignArr.indexOf(1) < 0) {
newItem.x = x
newItem.y = y
layout.push(newItem)
return
}
}
}
}
// 无满足条件
newItem.x = 0
newItem.y = edgeY + 1
layout.push(newItem)
}
该方法的关键在于申请空间:
在遍历地图上每一个栅格时,首先需要确定横向和纵向所剩空间是否能容纳下卡片。
如果不能,直接跳出,在可布局边界的最后一行添加元素即可。
如果可以容纳,考察新元素所需空间的每一个栅格是否被占用(地图gridMap中标记"1"位占用),这里借助一个数组itemSignArr记录占用情况。如果这个数组中没有出现"1",即表示所需空间是"空"的,可以再次插入卡片。否则进入下一个栅格重复申请过程。
相关阅读:vue-grid-layout文档
拖拽,拖放事件可以通过拖拽实现数据传递,达到良好的交互效果,如:从操作系统拖拽文件实现文件选择,拖拽实现元素布局的修改。原生Js实现元素拖拽、图片到指定区域进行预览的方法实现
当我们需要对Dom元素进行底层操作的时候,这时候我们就需要使用vue的自定义指令。这篇文章将讲解:如何注册Vue自定义指令?Vue的钩子函数,vue钩子函数参数,vue实现拖拽功能,实现图片加载功能,Vue自定义指令集成第三方插件 ...
移动端的拖拽有两种主流的实现方案:1. 将元素设置为固定定位,然后在拖拽的时候修改其定位,实现拖拽的效果;2. 使用 transform 中的平移 translate 属性实现拖拽。
正巧在之前面试中遇到问实现拖拽效果。当时面试的时候简单回答了实现的方式与逻辑。现在闲来无事,把这个东西实现了一下。原理很简单,写的很方便。
如果要设置物体拖拽,必须使用三个事件,分别是:1、onmousedown:鼠标按下事件2、onmousemove:鼠标移动事件3、onmouseup:鼠标抬开事件
如何拖拽图片到指定位置,具体方法如下,在从本地上传图片的时候,如果使用拖拽效果,想想应该是更加的高大上,下面直接上js代码
ngDraggable.js是一款比较简单实用的angularJS拖拽插件,借助于封装好的一些自定义指令,能够快速的进行一些拖拽应用开发。首先先介绍一些基本的概念;ng-drop:是否允许放入拖拽元素
拖放是一种非常流行的用户界面模式。它的概念很简单:点击某个对象,并按住鼠标按钮不放,将鼠标移到到另一个区域,然后释放按钮将对象放到这里。
最近重读Vue官方文档,在列表的排序过渡这一小节,文档提到,<transition-group> 组件有一个特殊的地方,不仅可以实现进入和离开动画,还可以改变定位,官网示例如下
运营小姐姐说想要可以直接拖拽排序的功能,原来在序号六的广告可能会因为金主爸爸加钱换到序号一的位置,拖拽操作就很方便;实现方式:template部分、script部分
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!