记录使⽤echarts的graph类型绘制流程图全过程(⼀)-x,y位
置的计算
先说下本次案例业务需求,输⼊2个节点,获取数据后绘制出2个节点间的路径,之前使⽤的是⽹状图,但是⽹状图的效果不佳,需要转换成流程图的模式:
那么如何在不修改数据的情况下,实现类似效果尼?
看了下echarts的graph类型,可以实现类似的,下⾯是官⽅的实例
从实例中可以看出,难点在于节点的显⽰位置x,y和曲线的设置。业务数据中:
1、节点的数量不定,关系的数量不定,
2、后台返回的数据只有单独的节点信息和关系信息
实现思路:
1、分析数据,获取前后节点关系,获得⾏数位置(节点的xIndex信息)
在节点数组中到开始节点并设置xIndex 为1,然后从它开始第⼆层的节点
// 获取节点的x轴顺序
setNodeOrder () {
if (item.id === this.startNode) {
item.xIndex = 1;
}
// 设置⼀个对象,记录节点信息,⽤于后⾯查询信息,⽐数组查询来的快
});
this.findNodeOrder(2, this.startNode);
}
/
/ ⼴度遍历--按顺序到第index层的数据,并设置对应的参数,再层层递进
findNodeOrder (xIndex, sId){
}
想⼀下,如果是第⼆层的节点,那么应该是关系中,源是startNode或者⽬的节点是startNode,如此类推,层层递进,
这⾥需要使⽤⼴度遍历⽽不是深度遍历,设定2个数组,currentQueue记录当前层的节点,afterQueue记录下⼀层的节点,当currentQueue 层遍历完后,将afterQueue变成currentQueue,继续遍历,直⾄结束,核⼼代码如下:
......
let nextIds = [];
// 源
if (item.source === sId) {
if (!desObj[item.target].xIndex) {
nextIds.push(item.target);
}
}
// ⽬的
if (item.target === sId) {
if (!desObj[item.source].xIndex) {
nextIds.push(item.source);
}
}
});
let nextIdsLen = nextIds.length;
// 1、没有当前的队列,没有后续的队列,有nextIds
if (
!this.currentQueue.length &&
!this.afterQueue.length &&
nextIdsLen
) {
this.currentQueue = nextIds;
this.currentXindex = this.currentXindex + 1;
this.setNextOrder();
} else if (this.currentQueue.length && nextIdsLen) {
// 2、有当前的队列在遍历,排队
this.afterQueue = at(nextIds);
} else if (!this.currentQueue.length && this.afterQueue.length) {
// 3、没有当前的队列了,有排队的队列,则排队的进去
if (nextIdsLen) {
this.afterQueue = at(nextIds);
}
this.currentQueue = JSON.parse(JSON.stringify(this.afterQueue));
this.afterQueue = [];
this.currentXindex = this.currentXindex + 1;
}
setNextOrder函数:
setNextOrder () {
while (this.currentQueue.length) {
let id = this.currentQueue.shift();
this.findNodeOrder(this.currentXindex, id);
}
}
2、根据⾏数信息设置列数的位置(节点的yIndex层的信息)
先排序第⼀层和第⼆层的顺序,因为第⼀层就⼀个节点,第⼆层和第⼀层的关系都是⼀样的,所以顺序⽆所谓,可以直接遇到就叠加
// 排完了x,再排列y
// 先排第⼀和⼆⾏的元素的y,按顺序排
let maxXindex = 1;
let secondYIndexObj = {};
for (let i desObj) {
let item = desObj[i];
if (!item.yIndex) {
maxXindex = item.xIndex > maxXindex ? item.xIndex : maxXindex;
if (item.xIndex === 1) {
item.yIndex = 1;
this.yIndexObj[item.id] = {
xIndex: 1,
yIndex: 1
};
}
if (item.xIndex === 2) {
if (!secondYIndexObj[item.xIndex]) {
item.yIndex = 1;
// 记录当前的y轴上的节点个数
secondYIndexObj[item.xIndex] = 1;
this.yIndexObj[item.id] = {
xIndex: 2,
yIndex: 1
};
} else {
item.yIndex = secondYIndexObj[item.xIndex] + 1;
secondYIndexObj[item.xIndex] = item.yIndex;
this.yIndexObj[item.id] = {
xIndex: 2,
yIndex: item.yIndex
};
while语句流程图怎么画}
}
}
}
但是从第三层开始就要注意了,不能再按照第⼆层的递增顺序的⽅法来控制。因为第⼆层与第三层的关系和数量都不⼀定,如果随机排列会导致线很乱,最好的⽅法是根据第⼆层的顺序,获取第三层的顺序。即将第⼆层第N个节点有关的的节点设置在第N层。这样如果第⼆层的数量与第三层的数量相等,那么就完全在⼀条直线上了。如果数量不等,也不⾄于那么混乱但是如果第三层有多个节点与第⼆层的同⼀个节点有关系,这个时候我选择的是随机选择层级了
// 从第三层开始
if (maxXindex > 2) {
// 后⾯列的排序根据前⼀列为准(尽量保证在⼀条直线上)
for (let j = 3; j <= maxXindex; j++) {
for (let i desObj) {
let item = desObj[i];
while (item.xIndex === j && !item.yIndex) {
// 先看跟它⼀层的节点有多少个
if (!deOrders[j]) {
let totals = this.findYtotal(j);
for (let i = 1; i <= totals; i++) {
}
}
// 第⼆层中的对应的层级
let findX = j - 1;
// 到所有的层级
let findYs = this.findLinkNode(item.id, findX);
// 到还有的层级
let sameArr = findYs.filter(x =>
);
let findY;
// 不到按顺序抽取了
if (!sameArr.length) {
// 只能随机选择⼀个了
let ran = Math.floor(
Math.random() * deOrders[j].length
);
findY = deOrders[j][ran];
} else {
findY = sameArr[0];
// 去除该顺序
let order;
if (num === findY) {
order = k;
return true;
}
});
}
this.yIndexObj[item.id] = {
xIndex: j,
yIndex: findY
};
item.yIndex = findY;
}
}
}
}
3、设置具体的位置信息
获取图表的中⼼位置centerY,将起点和终点的y位置放在中间,其他的根据上⾯获取的xIndex和yIndex的还有根据情况设置的间距(gapX,gapY)及节点的⼤⼩(size)计算出每个节点的x和y信息
// 设置节点的位置x,y
setNodesPositon () {
for (let i desObj) {
let item = desObj[i];
if (item.id === this.startNode) {
item.y = Y;
item.x = 1;
}
if (!item.x) {
item.x = this.gapX * (item.xIndex - 1) + this.size / 2;
}
if (!item.y && !al) {
if (al === 1) {
item.y = Y;
} else {
let middleNum = al / 2;
let ceilNum = il(middleNum);
let topGap;
let bottomGap;
let ty = (ceilNum - item.yIndex) * (this.gapY + this.size);
let by = (item.yIndex - ceilNum) * (this.gapY + this.size);
if (al % 2 === 1) {
topGap = Y - ty;
bottomGap = Y + by;
} else {
topGap = Y - (ty + this.gapY + 0.5 * this.size);
bottomGap = Y + (by - 0.5 * this.size); }
if (item.yIndex <= middleNum) {
item.y = topGap;
} else {
item.y = bottomGap;
}
// 奇数
if (al % 2 === 1) {
if (item.yIndex === ceilNum) {
item.y = Y;
}
}
}
}
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论