vue使用echarts畫組織結(jié)構(gòu)圖
昨天,寫了一篇關(guān)于圓環(huán)進(jìn)度條的博客(請(qǐng)移步:Vue圓環(huán)進(jìn)度條),已經(jīng)煩不勝煩,今天又遇到了需要展示類似公司的組織結(jié)構(gòu)圖的功能需求,要冒了?。?!
這種需求,自己用div+css也是可以實(shí)現(xiàn)的,但是沒有什么動(dòng)畫效果,我的css3又很差勁,而且項(xiàng)目中已經(jīng)使用到了折線圖、餅狀圖、柱狀圖之類的圖表,用的還是百度的echarts,所以這個(gè)組織結(jié)構(gòu)圖之類的需求也就用了百度的echarts來實(shí)現(xiàn)了。
以前用echarts寫折線圖、柱狀圖、餅狀圖的較多,它的API還算比較熟悉,但是畫組織結(jié)構(gòu)這樣的樹狀圖就很苦逼了,沒用過啊,而且設(shè)計(jì)給的樹狀圖的展示效果跟echarts樹狀圖的展示效果相去甚遠(yuǎn),我滴孩,又得一通費(fèi)時(shí)費(fèi)力的研究,設(shè)計(jì)圖如下:

如圖所示,一個(gè)樹節(jié)點(diǎn)中可能會(huì)有兩種不同的背景色,還有兩種不同的文字顏色,每個(gè)節(jié)點(diǎn)展示的還是圓角矩形。有同學(xué)說了,echarts有設(shè)置圓角的API啊,直接設(shè)置不就完事了。我想說的是,它是提供的有這樣的API,但是按照正常的套路實(shí)現(xiàn)不了啊。
從圖上還可以看到一個(gè)幾乎實(shí)現(xiàn)不了的效果,就是連接每個(gè)節(jié)點(diǎn)之間的線的拐角處都是直角而不是平滑的,而且echarts沒有給出可以設(shè)置拐角處是直角的API,只是給了一個(gè)curveness(API的描述是樹圖邊的曲度),這玩意兒使用了之后,也還是實(shí)現(xiàn)不了的。
從網(wǎng)上查了資料,有人說可以修改echarts的源碼,這種解決辦法我不推薦,是因?yàn)樵趘ue或react項(xiàng)目中,echarts是需要通過安裝在package.json中的,如果是多人并行開發(fā),那么別人安裝的echarts就不是你修改后的echarts,這就是問題所在。
最后用echarts畫出來的效果還是很不錯(cuò)的,唯一沒有實(shí)現(xiàn)的就是連接每個(gè)節(jié)點(diǎn)的線的拐角處不是直角,有好的解決辦法的,還望不吝賜教,謝謝!展示一下最終的成果:

說了那么多,還是上代碼吧,該代碼是基于vue的,如果要使用在react中,稍微修改一下就可以了。
組件tree.vue:
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import echarts from "echarts";
require("echarts/theme/macarons");
import { debounce } from "@/utils";
export default {
props: {
className: {
type: String,
default: "chart"
},
width: {
type: String,
default: "100%"
},
height: {
type: String,
default: "500px"
},
chartData: {
type: Object,
required: true
}
},
data() {
return {
chart: null,
};
},
watch: {
chartData: {
deep: true,
handler(val) {
this.setOptions(val);
}
}
},
mounted() {
this.initChart();
//是否需要自適應(yīng)-加了防抖函數(shù)
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize();
}
}, 100);
window.addEventListener("resize", this.__resizeHandler);
// 監(jiān)聽側(cè)邊欄的變化以實(shí)現(xiàn)自適應(yīng)縮放
const sidebarElm = document.getElementsByClassName("sidebar-container")[0];
sidebarElm.addEventListener("transitionend", this.sidebarResizeHandler);
},
beforeDestroy() {
if (!this.chart) {
return;
}
window.removeEventListener("resize", this.__resizeHandler);
this.chart.dispose();
this.chart = null;
const sidebarElm = document.getElementsByClassName("sidebar-container")[0];
sidebarElm.removeEventListener("transitionend", this.sidebarResizeHandler);
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, "macarons");
this.setOptions(this.chartData);
const nodes = this.chart._chartsViews[0]._data._graphicEls;
let allNode = 0;
for(let index = 0; index < nodes.length; index++) {
const node = nodes[index];
if (node === undefined) {
continue
}
allNode++;
}
const height = window.innerHeight;
const width = window.innerWidth - 1000;
const currentHeight = 85 * allNode;
const currentWidth = 220 * allNode;
const newHeight = Math.max(currentHeight, height);
const newWidth = Math.max(currentWidth, width);
const tree_ele = this.$el;
// tree_ele.style.height = newHeight + 'px'; //設(shè)置高度自適應(yīng)
tree_ele.style.width = newWidth + 'px'; //設(shè)置寬度自適應(yīng)
this.chart.resize();
this.chart.on('click', this.chartData.clickCallback); //節(jié)點(diǎn)點(diǎn)擊事件
},
setOptions(data) {
this.chart.setOption({
//提供數(shù)據(jù)視圖、還原、下載的工具
// toolbox: {
// show : true,
// feature : {
// mark : {show: true},
// dataView : {show: true, readOnly: false},
// restore : {show: true},
// saveAsImage : {show: true}
// }
// },
series: [
{
name: "統(tǒng)一授信視圖",
type: "tree",
orient: "TB", //豎向或水平 TB代表豎向 LR代表水平
top: '10%',
initialTreeDepth: 10, //樹圖初始展開的層級(jí)(深度)
expandAndCollapse: false, //點(diǎn)擊節(jié)點(diǎn)時(shí)不收起子節(jié)點(diǎn),default: true
symbolSize: [135, 65],
itemStyle: {
color: 'transparent',
borderWidth: 0,
},
lineStyle: {
color: '#D5D5D5',
width: 1,
curveness: 1,
},
data: [data]
}
]
});
},
sidebarResizeHandler(e) {
if (e.propertyName === "width") {
this.__resizeHandler();
}
}
}
};
</script>
使用tree.vue的方法:
<template>
<tree :chartData="treeData" />
</template>
<script>
import tree from './tree';
export default {
data() {
return {
treeData: {
label: {
backgroundColor: '#F4F4F4',
borderRadius: [0, 0, 5, 5],
formatter: [
'{first|綜合授信額度}',
'{second|(CR20190912000013)\n獲批金額:100\n幣種:人民幣}',
].join('\n'),
rich: {
first: {
backgroundColor: '#078E34',
color: '#fff',
align: 'center',
width: 135,
height: 30,
borderRadius: [5, 5, 0, 0],
},
second: {
color: '#888',
align: 'center',
lineHeight: 17,
},
}
},
children: [
{
label: {
formatter: [
'{first|渠道額度}',
].join('\n'),
rich: {
first: {
backgroundColor: '#3AC082',
color: '#fff',
align: 'center',
width: 135,
height: 65,
borderRadius: 5,
},
}
},
children: [{
label: {
formatter: [
'{first|保理額度}',
].join('\n'),
rich: {
first: {
backgroundColor: '#3AC082',
color: '#fff',
align: 'center',
width: 135,
height: 65,
borderRadius: 5,
},
}
},
children: [{
label: {
backgroundColor: '#F4F4F4',
borderRadius: [0, 0, 5, 5],
formatter: [
'{first|反向保理}',
'{second|(CR20190912000013)\n獲批金額:100\n幣種:人民幣}',
].join('\n'),
rich: {
first: {
backgroundColor: '#078E34',
color: '#fff',
align: 'center',
width: 135,
height: 30,
borderRadius: [5, 5, 0, 0],
},
second: {
color: '#888',
align: 'center',
lineHeight: 17,
},
}
},
}]
}]
},
{
label: {
formatter: [
'{first|擔(dān)保/(樂)集團(tuán)/其他額度}',
].join('\n'),
rich: {
first: {
backgroundColor: '#3AC082',
color: '#fff',
align: 'center',
width: 135,
height: 65,
borderRadius: 5,
},
}
},
children: [{
label: {
formatter: [
'{first|保理額度}',
].join('\n'),
rich: {
first: {
backgroundColor: '#3AC082',
color: '#fff',
align: 'center',
width: 135,
height: 65,
borderRadius: 5,
},
}
},
children: [{
label: {
backgroundColor: '#F4F4F4',
borderRadius: [0, 0, 5, 5],
formatter: [
'{first|正向保理}',
'{second|(CR20190912000013)\n獲批金額:100\n幣種:人民幣}',
].join('\n'),
rich: {
first: {
backgroundColor: '#B8D87E',
color: '#fff',
align: 'center',
width: 135,
height: 30,
borderRadius: [5, 5, 0, 0],
},
second: {
color: '#888',
align: 'center',
lineHeight: 17,
},
}
},
}]
},
{
label: {
formatter: [
'{first|租賃額度}',
].join('\n'),
rich: {
first: {
backgroundColor: '#3AC082',
color: '#fff',
align: 'center',
width: 135,
height: 65,
borderRadius: 5,
},
}
},
children: [
{
label: {
backgroundColor: '#F4F4F4',
borderRadius: [0, 0, 5, 5],
formatter: [
'{first|車輛租賃}',
'{second|(CR20190912000013)\n獲批金額:100\n幣種:人民幣}',
].join('\n'),
rich: {
first: {
backgroundColor: '#FF6C6A',
color: '#fff',
align: 'center',
width: 135,
height: 30,
borderRadius: [5, 5, 0, 0],
},
second: {
color: '#888',
align: 'center',
lineHeight: 17,
},
}
},
},
]
}]
}
]
}
}
},
components: {
tree,
}
};
</script>
看著代碼不多,但是實(shí)現(xiàn)起來,各種查echarts的API和網(wǎng)上的資料,而且,由于效果圖中一個(gè)節(jié)點(diǎn)處的文字可能會(huì)換行,文字的顏色也不同,同時(shí)有些節(jié)點(diǎn)處的背景色還會(huì)有兩種,以及每個(gè)節(jié)點(diǎn)處顯示的樣式和文字都是不固定的,所以我們可能還要面臨著將接口返回的數(shù)據(jù)再改造處理成我們想要的數(shù)據(jù)的繁瑣問題,就如同傳遞給樹節(jié)點(diǎn)的treeData的格式一樣,相當(dāng)麻煩,如果每個(gè)節(jié)點(diǎn)的樣式都是一樣的,那就好辦多了,如官網(wǎng)的一個(gè)樹狀圖的例子:https://www.echartsjs.com/examples/zh/editor.html?c=tree-vertical
從echarts的v4.7.0版本開始,給配置項(xiàng)series中加入一個(gè)API:edgeShape:'polyline'可實(shí)現(xiàn)樹形圖表連接每個(gè)節(jié)點(diǎn)的線的拐角處呈直角。
以上就是vue使用echarts畫組織結(jié)構(gòu)圖的詳細(xì)內(nèi)容,更多關(guān)于vue 畫組織結(jié)構(gòu)圖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Vue項(xiàng)目如何引入bootstrap、elementUI、echarts
- vue中echarts的用法及與elementui-select的協(xié)同綁定操作
- VUE+elementui組件在table-cell單元格中繪制微型echarts圖
- vue中使用element ui的彈窗與echarts之間的問題詳解
- VUE2.0+Element-UI+Echarts封裝的組件實(shí)例
- vue.js集成echarts時(shí)遇到的一些問題總結(jié)
- vue+echarts實(shí)現(xiàn)中國地圖流動(dòng)效果(步驟詳解)
- vue中使用echarts的示例
- 在vue項(xiàng)目中封裝echarts的步驟
- Vue Element前端應(yīng)用開發(fā)之echarts圖表
相關(guān)文章
vue如何設(shè)置輸入框只能輸入數(shù)字且只能輸入小數(shù)點(diǎn)后兩位,并且不能輸入減號(hào)
這篇文章主要介紹了vue如何設(shè)置輸入框只能輸入數(shù)字且只能輸入小數(shù)點(diǎn)后兩位,并且不能輸入減號(hào)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
Vue用v-for給循環(huán)標(biāo)簽自身屬性添加屬性值的方法
這篇文章主要介紹了Vue用v-for給循環(huán)標(biāo)簽自身屬性添加屬性值的方法,文中大家給大家列舉了三種方法 ,需要的朋友可以參考下2018-10-10
vue阻止頁面回退的實(shí)現(xiàn)方法(瀏覽器適用)
這篇文章主要介紹了vue阻止頁面回退的實(shí)現(xiàn)方法(瀏覽器適用),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05
vue2.0實(shí)戰(zhàn)之使用vue-cli搭建項(xiàng)目(2)
這篇文章主要為大家詳細(xì)介紹了vue2.0實(shí)戰(zhàn)第二篇使用vue-cli搭建項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
基于Vue實(shí)現(xiàn)一個(gè)textarea幽靈建議功能
不知道你有沒有發(fā)現(xiàn)Bing AI聊天有個(gè)輸入提示功能,在用戶輸入部分內(nèi)容時(shí)后面會(huì)給出灰色提示文案,用戶只要按下tab鍵就可以快速添加提示的后續(xù)內(nèi)容,我將這個(gè)功能稱為幽靈建議,接下來我將用Vue框架來實(shí)現(xiàn)這個(gè)功能,需要的朋友可以參考下2023-09-09
Vue.js實(shí)現(xiàn)一個(gè)自定義分頁組件vue-paginaiton
這篇文章主要為大家詳細(xì)介紹了Vue.js實(shí)現(xiàn)一個(gè)自定義分頁組件vue-paginaiton的具體代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09

