Files
schisandra-cloud-album-front/src/components/MyUI/TreeChart/TreeChart.vue
landaiqing 33d76461f1 refine MyUI
2024-11-07 21:39:16 +08:00

286 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup lang="ts">
import {computed, onMounted, ref, watch} from 'vue';
/*
按需引入
*/
// 使用 ECharts 提供的按需引入的接口来打包必须的组件
// 引入 echarts 核心模块,核心模块提供了 echarts 使用必须要的接口
import * as echarts from 'echarts/core';
// 引入树图图表,图表后缀都为 Chart
import {TreeChart} from 'echarts/charts';
// 引入提示框,组件后缀都为 Component
import {TooltipComponent} from 'echarts/components';
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
import {CanvasRenderer} from 'echarts/renderers';
// 注册必须的组件
echarts.use([TreeChart, TooltipComponent, CanvasRenderer]);
/*
全部引入
*/
// import * as echarts from 'echarts'
/*
需要注意的是为了保证打包的体积是最小的ECharts 按需引入的时候不再提供任何渲染器,
所以需要选择引入 CanvasRenderer 或者 SVGRenderer 作为渲染器。这样的好处是假如
你只需要使用 svg 渲染模式,打包的结果中就不会再包含无需使用的 CanvasRenderer 模块
*/
const chart = ref();
const treeChart = ref();
var option: any;
interface Tree {
name: string // 数据项名称
value?: number // 数据值
[propName: string]: any // 添加一个字符串索引签名,用于包含带有任意数量的其他属性
}
interface Props {
treeData: Tree[] // 树图数据源
width?: string | number // 容器宽度
height?: string | number // 容器高度
themeColor?: string // 主题色
edgeShape?: 'curve' | 'polyline' // 树图边的形状有曲线curve和折线polyline两种只有正交布局下生效
}
const props = withDefaults(defineProps<Props>(), {
treeData: () => ([]),
width: '100%',
height: '100%',
themeColor: '#1677FF',
edgeShape: 'curve'
});
const chartWidth = computed(() => {
if (typeof props.width === 'number') {
return props.width + 'px';
} else {
return props.width;
}
});
const chartHeight = computed(() => {
if (typeof props.height === 'number') {
return props.height + 'px';
} else {
return props.height;
}
});
onMounted(() => {
initChart(); // 初始化图标示例
});
watch(
() => props.treeData,
(to) => {
// 监听并更新图例数据
option.series[0].data = to;
treeChart.value.setOption(option);
},
{
deep: true
}
);
watch(
() => [props.width, props.height, props.themeColor, props.edgeShape],
() => {
if (treeChart.value) {
treeChart.value.dispose(); // 销毁实例
}
initChart(); // 重新初始化实例
},
{
deep: true,
flush: 'post'
}
);
// const loadingConfig = {
// text: 'loading',
// color: '#c23531',
// textColor: '#000',
// maskColor: 'rgba(255, 255, 255, 0.8)',
// zlevel: 0,
// 字体大小。从 `v4.8.0` 开始支持。
// fontSize: 12,
// 是否显示旋转动画spinner。从 `v4.8.0` 开始支持。
// showSpinner: true,
// 旋转动画spinner的半径。从 `v4.8.0` 开始支持。
// spinnerRadius: 20,
// 旋转动画spinner的线宽。从 `v4.8.0` 开始支持。
// lineWidth: 5,
// 字体粗细。从 `v5.0.1` 开始支持。
// fontWeight: 'normal',
// 字体风格。从 `v5.0.1` 开始支持。
// fontStyle: 'normal',
// 字体系列。从 `v5.0.1` 开始支持。
// fontFamily: 'sans-serif'
// }
function showLoading(config: any) {
treeChart.value.showLoading('default', {text: '', color: props.themeColor, ...config}); // 显示加载动画效果
}
function hideLoading() {
treeChart.value.hideLoading(); // 隐藏动画加载效果
}
defineExpose({
showLoading,
hideLoading
});
const emit = defineEmits(['clickNode']);
function onClick(e: any) {
emit('clickNode', e.data);
}
function initChart() {
// 等价于使用 Canvas 渲染器默认echarts.init(containerDom, null, { renderer: 'canvas' })
treeChart.value = echarts.init(chart.value);
option = {
tooltip: { // 提示框浮层设置
trigger: 'item',
triggerOn: 'mousemove', // 提示框触发条件
enterable: true, // 鼠标是否可进入提示框浮层中默认false
confine: true, // 是否将tooltip框限制在图表的区域内
formatter: function (params: any) { // 提示框浮层内容格式器,支持字符串模板和回调函数两种形式
// console.log('params:', params)
return params.marker + params.name + '<br/>' + '$ ' + (params.value || '--');
},
// valueFormatter: function (value) { // tooltip 中数值显示部分的格式化回调函数
// return '$' + value.toFixed(2)
// },
backgroundColor: '#FFF', // 提示框浮层的背景颜色
borderColor: props.themeColor, // 提示框浮层的边框颜色
borderWidth: 1, // 提示框浮层的边框宽
borderRadius: 8, // 提示框浮层圆角
padding: [6, 8], // 提示框浮层的内边距
textStyle: { // 提示框浮层的文本样式
color: '#333', // 文字颜色
fontWeight: 400, // 字体粗细
fontSize: 16, // 字体大小
lineHeight: 20, // 行高
width: 60, // 文本显示宽度
// 文字超出宽度是否截断或者换行只有配置width时有效
overflow: 'breakAll', // truncate截断并在末尾显示ellipsis配置的文本默认为...;break换行;breakAll换行并强制单词内换行
ellipsis: '...'
},
extraCssText: 'box-shadow: 0 0 9px rgba(0, 0, 0, 0.3); text-align: right;' // 额外添加到浮层的css样式
},
series: [
{
type: 'tree',
data: props.treeData,
name: '树图',
top: '1%', // 组件离容器上侧的距离像素值20或相对容器的百分比20%
left: '10%', // 组件离容器左侧的距离
bottom: '1%', // 组件离容器下侧的距离
right: '16%', // 组件离容器右侧的距离
layout: 'orthogonal', // 树图的布局正交orthogonal和径向radial两种
orient: 'LR', // 树图中正交布局的方向,'LR','RL','TB','BT',只有布局是正交时才生效
edgeShape: props.edgeShape, // 树图边的形状有曲线curve和折线polyline两种只有正交布局下生效
roam: false, // 是否开启鼠标缩放或平移默认false
initialTreeDepth: 2, // 树图初始的展开层级深度根节点是0不设置时全部展开
// symbol: 'arrow', // 标记的图形默认是emptyCircle;circle,rect,roundRect,triangle,diamond,pin,arrow,none
// symbolRotate: 270, // 配合arrow图形使用效果较好
symbolSize: 16, // 大于0时是圆圈等于0时不展示标记的大小
itemStyle: { // 树图中每个节点的样式
color: props.themeColor, // 节点未展开时的填充色
borderColor: 'rgba(255, 144, 0, 1)', // 图形的描边颜色
borderWidth: 1, // 描边线宽为0时无描边
borderType: 'dotted', // 描边类型
borderCap: 'square', // 指定线段末端的绘制方式butt方形结束round圆形结束square
shadowColor: 'rgba(0,121,221,0.3)', // 阴影颜色
shadowBlur: 16, // 图形阴影的模糊大小
opacity: 1 // 图形透明度
},
label: { // 每个节点对应的文本标签样式
show: true, // 是否显示标签
distance: 8, // 文本距离图形元素的距离
position: 'left', // 标签位置
verticalAlign: 'middle', // 文字垂直对齐方式默认自动topmiddlebottom
align: 'center', // 文字水平对齐方式默认自动leftrightcenter
fontSize: 16, // 字体大小
color: '#333', // 字体颜色
backgroundColor: '#F0F5FA', // 文字块的背景颜色
borderColor: props.themeColor, // 文字块边框颜色
borderWidth: 1, // 文字块边框宽度
borderType: 'solid', // 文字块边框描边类型 solid dashed dotted
borderRadius: 4, // 文字块的圆角
padding: [6, 12], // 文字块内边距
shadowColor: 'rgba(0,121,221,0.3)', // 文字块的背景阴影颜色
shadowBlur: 6, // 文字块的背景阴影长度
width: 60,
// 文字超出宽度是否截断或者换行只有配置width时有效
overflow: 'truncate', // truncate截断并在末尾显示ellipsis配置的文本默认为...;break换行;breakAll换行并强制单词内换行
ellipsis: '...'
},
lineStyle: { // 树图边的样式
color: 'rgba(0,0,0,.35)', // 树图边的颜色
width: 2, // 树图边的宽度
curveness: 0.5, // 树图边的曲度
shadowColor: 'rgba(0, 0, 0, 0.5)', // 阴影颜色
shadowBlur: 10 // 图形阴影的模糊大小
},
emphasis: { // 树图中图形和标签高亮的样式
disabled: false, // 是否关闭高亮状态默认false
// 在高亮图形时,是否淡出其它数据的图形已达到聚焦的效果
focus: 'self', // none不淡出其他图形默认self只聚焦当前高亮的数据图形series聚焦当前高亮的数据所在系列的所有图形ancestor聚焦所有祖先节点descendant聚焦所有子孙节点relative聚焦所有子孙和祖先节点
blurScope: 'coordinateSystem', // 开启focus时配置淡出的范围coordinateSystem淡出范围为坐标系默认series淡出范围为系列global淡出范围为全局
itemStyle: { // 该节点的样式
color: props.themeColor, // 图形的颜色
// 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: 8,
// color: props.themeColor,
position: 'right',
verticalAlign: 'middle',
align: 'left'
},
itemStyle: {}, // 叶子节点的样式
emphasis: {}, // 叶子节点高亮状态的配置
blur: {}, // 叶子节点淡出状态的配置
select: {} // 叶子节点选中状态的配置
},
animation: true, // 是否开启动画
expandAndCollapse: true, // 子树折叠和展开的交互,默认打开
animationDuration: 550, // 初始动画的时长
animationEasing: 'linear', // 初始动画的缓动效果
animationDelay: 0, // 初始动画的延迟
animationDurationUpdate: 750, // 数据更新动画的时长
animationEasingUpdate: 'cubicInOut', // 数据更新动画的缓动效果
animationDelayUpdate: 0 // 数据更新动画的延迟
}
]
};
if (option) {
treeChart.value.setOption(option);
}
// 监听树图节点的点击事件
treeChart.value.on('click', onClick);
}
</script>
<template>
<div ref="chart" :style="`width: ${chartWidth}; height: ${chartHeight};`"></div>
</template>