| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489 |
- <template>
- <div id="main" class="echarts-container" />
- </template>
- <script>
- import { TreeChart } from "echarts/charts";
- import { TooltipComponent } from "echarts/components";
- import * as echarts from "echarts/core";
- import { CanvasRenderer } from "echarts/renderers";
- echarts.use([TooltipComponent, TreeChart, CanvasRenderer]);
- // let this.myChart;
- let option;
- var treeNodePadding = 50; //节点间最小间隔
- var treeTopPadding = 120; //tree距顶端的距离
- var rightNode; //最右侧节点,用于计算偏移量
- export default {
- name: "TreeChart",
- data() {
- return {
- myChart: null,
- centerLoca: [],
- fontSize: 6,
- chartWidth: 0,
- chartHeight: 0,
- center: [this.chartWidth, "50%"],
- };
- },
- props: {
- treeData: {
- type: Object,
- default: () => {
- return {};
- },
- },
- topDeep: Number,
- type: String,
- clickNodeList: Array,
- },
- watch: {
- clickNodeList: {
- handler(newValue, old) {
- if (newValue) {
- this.init();
- }
- },
- },
- treeData: {
- handler(newValue, old) {
- console.log(newValue);
- if (newValue) {
- this.init();
- }
- },
- },
- chartWidth: {
- handler(newValue, old) {
- console.log(newValue);
- if (newValue) {
- this.init();
- }
- },
- },
- },
- mounted() {
- this.init();
- // 监听树图节点的点击事件
- this.myChart.on("click", (e) => {
- console.log("e:", e);
- this.$emit("clickNode", e);
- });
- },
- methods: {
- init() {
- const that = this;
- // console.log('$el:', this.$el)
- that.myChart = echarts.init(this.$el);
- that.myChart.clear();
- option = {
- tooltip: {
- // 提示框浮层设置
- trigger: "item",
- triggerOn: "mousemove", // 提示框触发条件
- enterable: true, // 鼠标是否可进入提示框浮层中,默认false
- confine: true, // 是否将tooltip框限制在图表的区域内
- padding: [5, 10],
- formatter: function (params) {
- // 提示框浮层内容格式器,支持字符串模板和回调函数两种形式
- const relationStr =
- "<div style='display: flex;flex-direction: column;'>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.numberLayers") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- (Number(params.data.TOP_NETWORK_DEEP) - Number(that.topDeep)) +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.memberCode") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.USER_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.name") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.REAL_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.level") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.DEC_LV_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.highest") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.EMP_LV_NAME +
- "," +
- params.data.CROWN_LV_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.periodNumber") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.PERIOD_AT +
- "</span>" +
- "</div>" +
- "</div>";
- const networkStr =
- "<div style='display: flex;flex-direction: column;'>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.memberCode") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.USER_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.name") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.REAL_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.level") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.DEC_LV_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.highest") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.EMP_LV_NAME +
- "," +
- params.data.CROWN_LV_NAME +
- "</span>" +
- "</div>" +
- "<div>" +
- '<span style="color: #606266;">' +
- that.$t("atlas.periodNumber") +
- ": " +
- "</span>" +
- '<span style="color: #000000;">' +
- params.data.PERIOD_AT +
- "</span>" +
- "</div>" +
- "</div>";
- return that.type === "placement" ? relationStr : networkStr;
- },
- // valueFormatter: function (value) { // tooltip 中数值显示部分的格式化回调函数
- // return '$' + value.toFixed(2)
- // },
- backgroundColor: "rgba(250,250,250,0.99)", // 提示框浮层的背景颜色
- borderColor: "#1890FF", // 提示框浮层的边框颜色
- borderWidth: 0.5, // 提示框浮层的边框宽
- borderRadius: 8, // 提示框浮层圆角
- textStyle: {
- // 提示框浮层的文本样式
- color: "#333", // 文字颜色
- // fontWeight: 400, // 字体粗细
- // fontSize: that.fontSize, // 字体大小
- // lineHeight: 20, // 行高
- // width: 60, // 文本显示宽度
- // 文字超出宽度是否截断或者换行;只有配置width时有效
- overflow: "breakAll", // truncate截断,并在末尾显示ellipsis配置的文本,默认为...;break换行;breakAll换行,并强制单词内换行
- ellipsis: "...",
- },
- extraCssText:
- "min-height:100px;box-shadow: 0 0 9px rgba(0, 0, 0, 0.3);text-align: left;", // 额外添加到浮层的css样式
- axisPointer: {
- type: "shadow",
- shadowStyle: {
- color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
- { offset: 0, color: "rgba(255, 255, 255, 0)" },
- { offset: 1, color: "rgba(37, 107, 230, 0.18)" },
- ]),
- },
- },
- },
- series: [
- {
- width: that.chartWidth + "px",
- height: "100%",
- type: "tree",
- data: [this.treeData],
- name: "树图",
- top: "1%", // 组件离容器上侧的距离,像素值20,或相对容器的百分比
- left: "1%", // 组件离容器左侧的距离
- bottom: "1%", // 组件离容器下侧的距离
- right: "1%", // 组件离容器右侧的距离
- layout: "orthogonal", // 树图的布局,正交orthogonal和径向radial两种
- orient: "TB", // 树图中正交布局的方向,'LR','RL','TB','BT',只有布局是正交时才生效
- edgeShape: "polyline", // 树图边的形状,有曲线curve和折线polyline两种,只有正交布局下生效
- // edgeForkPosition:"10%",
- roam: true, // 是否开启鼠标缩放或平移,默认false
- zoom: 0.5,
- scaleLimit: {
- min: 0.5,
- max: 10,
- },
- center: that.center || null,
- // center: [5, 5],
- initialTreeDepth: -1, // 树图初始的展开层级(深度),根节点是0,不设置时全部展开
- // symbol: 'emptyCircle', // 标记的图形,默认是emptyCircle;circle,rect,roundRect,triangle,diamond,pin,arrow,none
- symbol: function (value, params) {
- // params.data节点的所有数据
- if (params.data.leaf == true) {
- return "emptyCircle";
- } else if (params.data.leaf == false) {
- return "circle";
- }
- },
- // symbolRotate: 270, // 配合arrow图形使用效果较好
- symbolSize: 10, // 大于0时是圆圈,等于0时不展示,标记的大小
- itemStyle: {
- // 树图中每个节点的样式
- color: "#1890FF", // 节点未展开时的填充色
- borderColor: "rgba(255, 144, 0, 1)", // 图形的描边颜色
- borderWidth: 0.5, // 描边线宽,为0时无描边
- borderType: "dotted", // 描边类型
- borderCap: "square", // 指定线段末端的绘制方式butt方形结束,round圆形结束,square
- shadowColor: "rgba(0,121,221,0.3)", // 阴影颜色
- shadowBlur: 12, // 图形阴影的模糊大小
- opacity: 1, // 图形透明度
- },
- label: {
- // 每个节点对应的文本标签样式
- show: true, // 是否显示标签
- // distance: 22, // 文本距离图形元素的距离
- position: "bottom", // 标签位置
- verticalAlign: "middle", // 文字垂直对齐方式,默认自动,top,middle,bottom
- align: "center", // 文字水平对齐方式,默认自动,left,right,center
- fontSize: that.fontSize, // 字体大小
- color: "#333", // 字体颜色
- backgroundColor: "#F0F5FA", // 文字块的背景颜色
- borderColor: "#1890FF", // 文字块边框颜色
- borderWidth: 0.5, // 文字块边框宽度
- borderType: "solid", // 文字块边框描边类型 solid dashed dotted
- borderRadius: 6, // 文字块的圆角
- padding: [5, 6], // 文字块内边距
- shadowColor: "rgba(0,121,221,0.6)", // 文字块的背景阴影颜色
- shadowBlur: 6, // 文字块的背景阴影长度
- width: 80,
- // 文字超出宽度是否截断或者换行;只有配置width时有效
- overflow: "truncate", // truncate截断,并在末尾显示ellipsis配置的文本,默认为...;break换行;breakAll换行,并强制单词内换行
- ellipsis: "...",
- formatter: function (params) {
- return (
- params.data.USER_NAME + "\n" + "\n" + params.data.REAL_NAME
- );
- // return params.data.REAL_NAME
- },
- },
- lineStyle: {
- // 树图边的样式
- color: "rgba(0,0,0,.35)", // 树图边的颜色
- width: 1, // 树图边的宽度
- curveness: 0.5, // 树图边的曲度
- shadowColor: "rgba(0, 0, 0, 0.5)", // 阴影颜色
- shadowBlur: 10, // 图形阴影的模糊大小
- },
- emphasis: {
- // 树图中图形和标签高亮的样式
- disabled: false, // 是否关闭高亮状态,默认false
- // 在高亮图形时,是否淡出其它数据的图形已达到聚焦的效果
- focus: "relative", // none不淡出其他图形(默认);self只聚焦当前高亮的数据图形;series聚焦当前高亮的数据所在系列的所有图形;ancestor聚焦所有祖先节点;descendant聚焦所有子孙节点;relative聚焦所有子孙和祖先节点
- blurScope: "coordinateSystem", // 开启focus时,配置淡出的范围,coordinateSystem淡出范围为坐标系(默认);series淡出范围为系列;global淡出范围为全局
- itemStyle: {
- // 该节点的样式
- color: "#1890FF", // 图形的颜色
- // borderColor: 'rgba(255, 144, 0, 1)', // 图形的描边颜色
- // borderWidth: 1, // 描边线宽,为0时无描边
- borderType: "solid", // 描边类型 solid dashed dotted
- borderCap: "square", // 指定线段末端的绘制方式butt方形结束,round圆形结束,square
- shadowColor: "rgba(0,121,221,0.3)", // 阴影颜色
- shadowBlur: 12, // 图形阴影的模糊大小
- opacity: 1, // 图形透明度
- },
- lineStyle: {
- // 树图边的样式
- color: "rgba(0,0,0,.45)", // 树图边的颜色
- width: 2, // 树图边的宽度
- curveness: 0.5, // 树图边的曲度
- shadowColor: "rgba(0, 0, 0, 0.5)", // 阴影颜色
- shadowBlur: 6, // 图形阴影的模糊大小
- },
- label: {
- // 高亮标签的文本样式
- color: "#333",
- fontWeight: 600,
- },
- },
- blur: {
- // 淡出状态的相关配置,开启emphasis.focus后有效
- itemStyle: {}, // 节点的样式
- lineStyle: {}, // 树图边的样式
- label: {}, // 淡出标签的文本样式
- },
- leaves: {
- // 叶子节点的特殊配置
- label: {
- // 叶子节点的文本标签样式
- // distance: 22,
- // color: '#1890FF',
- position: "bottom",
- verticalAlign: "middle",
- align: "center",
- },
- itemStyle: {}, // 叶子节点的样式
- emphasis: {}, // 叶子节点高亮状态的配置
- blur: {}, // 叶子节点淡出状态的配置
- select: {}, // 叶子节点选中状态的配置
- },
- animation: true, // 是否开启动画
- expandAndCollapse: true, // 子树折叠和展开的交互,默认打开
- animationDuration: 500, // 初始动画的时长
- animationEasing: "linear", // 初始动画的缓动效果
- animationDelay: 0, // 初始动画的延迟
- animationDurationUpdate: 500, // 数据更新动画的时长
- animationEasingUpdate: "cubicInOut", // 数据更新动画的缓动效果
- animationDelayUpdate: 0, // 数据更新动画的延迟
- },
- ],
- };
- option && that.myChart.setOption(option, true);
- that.resize();
- // that.adjustTreeView();
- that.myChart.getZr().off("mousewheel");
- that.myChart.getZr().on("mousewheel", (param) => {
- let currentOption = that.myChart.getOption();
- // console.log(currentOption);
- if (currentOption.series[0]) {
- let zoom = currentOption.series[0].zoom;
- // that.fontSize = 10 * zoom
- currentOption.textStyle.fontSize = 10 * zoom;
- currentOption.series[0].label.fontSize = 8 * zoom;
- currentOption.series[0].label.width = 110 * zoom;
- currentOption.series[0].label.distance = 18 * zoom;
- currentOption.series[0].leaves.distance = 18 * zoom;
- option && that.myChart.setOption(currentOption);
- }
- });
- },
- resize() {
- let elesArr = Array.from(
- new Set(this.myChart._chartsViews[0]._data._graphicEls)
- );
- console.log(elesArr.length)
- let dep = this.myChart._chartsViews[0]._data.tree.root.height; //获取树高
- console.log(dep);
- let layer_height = 90; //层级之间的高度
- let currentHeight = layer_height * (dep + 1) || layer_height;
- let newHeight = Math.max(currentHeight, layer_height);
- this.chartHeight = newHeight + "px";
- let layer_width = 90; // 兄弟节点之间的距离
- let currentWidth = layer_width * (elesArr.length - 1) || layer_width;
- let newWidth = Math.max(currentWidth, layer_width);
- console.log(newWidth);
- if (newWidth < 200) {
- this.center[0] = '-70%';
- this.center[1] = (dep * 2) + '0%';
- }else if (newWidth > 200 && newWidth < 500) {
- this.center[0] = '-56%';
- this.center[1] = (dep * 1.5) + '0%';
- }else if (newWidth > 500 && newWidth < 1000) {
- this.center[0] = '-30%';
- this.center[1] = (dep) + '0%';
- } else if (newWidth > 1000){
- this.center[0] = elesArr.length > 60 ? newWidth * 1.5 : newWidth * 1.2;
- this.center[1] = (dep ) + '0%';
- }
- this.chartWidth = newWidth;
- window.addEventListener("resize", () => {
- this.myChart.resize();
- });
- },
- doGlobalTreeChart(ec, data) {
- // this.myChart.setOption(getGlobalTreeOption());
- //生成图表后做调整
- this.adjustTreeView();
- },
- //调整tree显示
- adjustTreeView() {
- var zr = this.myChart.getZr();
- var domWidth = zr.painter.getWidth();
- var treeWidth = this.getTreeWidth(zr);
- if (treeWidth <= domWidth) return;
- },
- //计算最左边节点和最右边节点(symbol为image或icon)的间隔即为树图宽度
- getTreeWidth(zr) {
- var nodes = zr.storage._roots;
- console.log(nodes);
- let max = 0;
- let min = 0;
- for (var i = 0; i < nodes.length; i++) {
- if (nodes[i].type == "image" || nodes[i].type == "icon") {
- var nodeX = nodes[i].style.x;
- if (nodeX > max) {
- max = nodeX;
- rightNode = nodes[i];
- continue;
- }
- if (nodeX < min) {
- min = nodeX;
- }
- }
- }
- return max - min;
- },
- },
- };
- </script>
- <style lang="scss" scoped>
- .echarts-container {
- width: 100%;
- height: calc(100vh - 105px);
- }
- </style>
|