可拖拽流程图组件开发

2,264 阅读1分钟

效果

在这里插入图片描述

说在前面

因为自己有需求,想要一个可以自由拖拽排序的流程图组件,在网上没有找到合适的demo,所以便自己动手做了这样一个雏形。

组件设计

首先需要设计好配置参数,然后就是讲配置参数融入到样式的设计处理上,最后是实现组件拖动并实时展示效果。

参数

整体参数

参数描述
title标题(String)
dragAble是否可拖拽(Boolean)
width图标最小宽度(number)
radius是否圆角(Boolean)
data流程项(Array)

data流程项参数

结构如下

[
	{
		icon:require('@/assets/logo.png'),//图标
		text:'准备'//文字
	},
	{
		icon:require('@/assets/1.png'),
		text:'开始'
	},
]

功能

监听鼠标事件

//是否可拖拽
if(this.chartData.dragAble){
	window.addEventListener('mouseup',this.handleMouseup);
	window.addEventListener('mouseover',this.handleMouseover);
}

初始化数据

//初始化数据
initData(){
	let data = this.vChartDataList;
	let res = [],flag = true,temp = [];
	for(let i = 1; i <= data.length; i++){
		data[i - 1].id = 'item' + '-' + res.length + '-' + (i - 1);
		if(flag) temp.push(data[i - 1]);
		else temp.unshift(data[i - 1]);
		if(i % this.itemNum == 0 || i == data.length){
			res.push([...temp]);
			temp = [];
			flag = !flag;
		}
	}
	this.chartDataList = res;
}

拖拽功能

//item点击事件
itemClick(index1,index,id,item){
	if(!this.chartData.dragAble) return;
	this.selectedItem = {...item};
	this.selectedItem.opacity = '0.5';
	let num = parseInt(id.split('-')[2]);
	let dom = document.getElementById('moveDiv');
	let dom1 = document.getElementById(id);//展示的节点
	let d = document.getElementById('chartContent');
	d.style.border="dashed 1px blue";
	// this.vChartDataList.splice(num,1);
	this.oldInd = num;
	this.initData();
	this.operateDom = dom;//记录操作的节点
	this.operateDomNum = num;
	this.startX = dom1.offsetLeft;
	this.startY = dom1.offsetTop;
	dom.style.visibility = 'inherit';
	dom.style.position = 'fixed';
	dom.style.left = dom1.offsetLeft;
	dom.style.top = dom1.offsetTop;
},
//移动时实时展示效果
handleMouseover(event){
	if(this.vChartDataList.length < this.chartData.data.length){
		this.vChartDataList.unshift({...this.chartData.data[0]});
	}
	if(this.operateDom != null){
		const w = this.operateDom.offsetWidth,h = this.operateDom.offsetHeight;
		let x = event.pageX,y = event.pageY;
		this.operateDom.style.position = 'fixed';
		this.operateDom.style.opacity = '0.5';
		this.operateDom.style.left = x - w / 2 + 'px';
		this.operateDom.style.top = y - h / 2 + 'px';
		let {tx,ty} = this.getItemCoords(x,y);
		let oldInd = this.oldInd;
		if(oldInd >= 0){
			this.vChartDataList.splice(oldInd,1);
			this.initData();
		}
		let nty = (parseInt(ty) % 2 == 0 ? parseInt(tx) : this.itemNum - parseInt(tx));
		nty = Math.min(nty,this.itemNum);
		nty = Math.max(nty,0);
		oldInd = parseInt(ty) * this.itemNum + nty;
		oldInd = Math.min(this.chartData.data.length - 1,oldInd);
		oldInd = Math.max(0,oldInd);
		this.oldInd = oldInd;
		if(oldInd < 0) return;
		this.vChartDataList.splice(oldInd,0,{...this.selectedItem});
		this.initData();
	}
},
//确定最终位置
handleMouseup(event){
	const chartContent = document.getElementById('chartContent');
	const dom = document.getElementById('moveDiv');
	const w = chartContent.offsetWidth,
		h = chartContent.offsetHeight,
		l = chartContent.offsetLeft,
		t = chartContent.offsetTop;
	const x = event.pageX,y = event.pageY;
	dom.style.visibility = 'hidden';
	// if(x > l && x < (l + w) && y > t && y < (t + h)){
		
	// }else{ 
		
	// }
	if(this.vChartDataList[this.oldInd]) this.vChartDataList[this.oldInd].opacity = 1;
	chartContent.style.border='none';
	this.operateDom = null;
	this.operateDomNum = null;
	this.oldInd = null;
},

代码

Gitee地址:gitee.com/zheng_yongt…

预览地址

jyeontu.xyz/jvuewheel/#…