本文主要記錄在使用echarts的graph類型繪制流程圖時候遇到的2個問題:對於圓形圖片的剪切和多層關系的設置
圖片的設置
如果用echarts默認的symbol參數來顯示圖片,會顯示圖片的原始狀態,即圓形就顯示圓形的,矩形就顯示矩形的,而案例中的圖片是矩形的(如上圖所示)。但是尼,我們在流程圖的繪制過程中,一般用到的又是圓形,所以這時候就需要我們自己進行剪切了。主要運用cavans的clip功能,以下是具體的代碼實現:
let picList = [];
let tempNodes = [];
for (let i in this.nodesObj) {
let item = this.nodesObj[i];
// 設置已知的信息
let obj = {
x: item.x,
y: item.y,
name: item.name,
id: item.id,
symbolSize: this.size,
category:
item.id === this.startNode || item.id === this.endNode ? 0 : 1
};
// 如果有圖標信息,進行圖片處理,沒有的直接放到節點信息中
if (item.icon) {
let p = this.getImgData(item.icon);
picList.push(p);
tempNodes.push(obj);
} else {
this.nodes.push(obj);
}
}
// 將圖片處理放在promise中,然后使用promise.all,當所有的圖片都剪切完畢后,賦值
if (picList.length > 0) {
let that = this;
Promise.all(picList).then(images => {
for (let i = 0, len = tempNodes.length; i < len; i++) {
tempNodes[i].symbol = 'image://' + images[i];
that.nodes.push(tempNodes[i]);
}
// console.log(this.nodes);
// 再設置節點
that.setLinks();
// 把數據設置到Echart中data
if (this.graphChart) {
var option = this.graphChart.getOption();
option.series[0].nodes = this.nodes;
option.series[0].links = this.links;
this.graphChart.setOption(option);
}
});
} else {
// 設置節點
this.setLinks();
}
// 獲取icon的圖片信息
getImgData (imgSrc) {
var fun = function (resolve) {
const canvas = document.createElement('canvas');
const contex = canvas.getContext('2d');
const img = new Image();
img.crossOrigin = '';
img.onload = function () {
// 設置圖形寬高比例
let center = {
x: img.width / 2,
y: img.height / 2
};
let diameter = img.width;
let radius = diameter / 2; // 半徑
canvas.width = diameter;
canvas.height = diameter;
contex.clearRect(0, 0, diameter, diameter);
contex.save();
contex.beginPath();
contex.arc(radius, radius, radius, 0, 2 * Math.PI); // 畫出圓
contex.clip();
contex.drawImage(
img,
center.x - radius,
center.y - radius,
diameter,
diameter,
0,
0,
diameter,
diameter
); // 在剛剛裁剪的園上畫圖
contex.restore(); // 還原狀態
resolve(canvas.toDataURL('image/png', 1));
};
img.src = imgSrc;
};
var promise = new Promise(fun);
return promise;
}
實現效果:
多關系合並
echarts的關系最多支持2條顯示,所以當2個節點之間存在多個關系的時候,可以把同一個指向的關系合並到一起如下圖,周傑倫與劉德華的關系是偶像和同窗,劉德華和周傑倫的關系是好友
也就是獲取兩個節點之間同方向的線條的關系,然后進行合並,再顯示在一條關系線上即可。
// 設置線條
setLinks () {
this.links = [];
this.relationList.forEach(item => {
let obj = {
source: item.source,
target: item.target,
value: item.relName,
label: {
show: true,
formatter: '{c}'
}
};
if (item.sameTotal >= 2) {
let hasLink = this.links.find(link => {
if (link.source === item.source && link.target === item.target) {
return true;
}
});
if (!hasLink) {
let res = this.findSameLinkRelation(
item.source,
item.target,
item.sameTotal
);
obj.value = res.value;
if (res.setLineStyle) {
obj.lineStyle = {
normal: {
curveness: 0.2
}
};
}
this.links.push(obj);
}
} else {
this.links.push(obj);
}
});
}
findSameLinkRelation (sid, tid, total) {
let value = [];
let setLineStyle = true;
this.relationList.forEach(item => {
if (item.source === sid && item.target === tid) {
value.push(item.relName);
}
});
if (total === value.length) {
setLineStyle = false;
}
value = value.join('、');
return {
value,
setLineStyle
};
}