核心库
- echarts
- lodash
- ResizeListener
代码
<!--
* @Author: your name
* @Date: 2020-11-04 10:39:39
* @LastEditTime: 2020-12-08 14:05:46
-->
<template>
<div class="charts" ref="charts"></div>
</template>
<script>
import echarts from 'echarts';
import { merge, cloneDeep } from 'lodash';
import ResizeListener from 'element-resize-detector';
export default {
name: 'ChartBar',
props: {
extraOption: { // 其他配置项
type: Object,
default: () => ({})
}
},
watch: {
extraOption: {
immediate: true,
deep: true,
handler () {
this.updateChartView();
}
},
},
data () {
return {
myChart: null, // 图表对象
option: { // 配置项
avoidLabelOverlap: true,
legend: {
itemHeight: 14,
itemWidth: 14,
icon: "circle",
orient: 'vertical',
zlevel: 999,
z: 999,
left: '62%',
top: '20%',
data: [],
formatter: (name) => {
const arr = [
'{aa|' + name + '}'
]
return arr.join('')
},
textStyle: {
rich: {
aa: {
fontSize: 14,
color: '#666666',
fontWeight: 'normal',
padding: [-2, 0, 0, 5],
lineHeight: 18
},
}
},
selectedMode: true, // 图例是否可点击
},
tooltip: {
confine: true, // 将图表限制在区域内
},
series: [
{
legendHoverLink: false, // 是否启用图例 hover 时的联动高亮
type: 'pie',
radius: ['0', '66%'],
center: ['30%', '52%'],
avoidLabelOverlap: true, // 是否启用防止标签重叠策略
hoverAnimation: true, // 鼠标移入的动画效果
hoverOffset: 4,
data: [],
}
],
color: ['#1fa776', '#f6b239', '#1fb8f1', '#ff9f7f', '#fb7293', '#67e0e3', '#fb7293', '#e062ae', '#e690d1', '#e7bcf3', '#9d96f5', '#8378ea', '#96bfff', '#859e41', '#9e7341', '#78419e', '#9e416d', '#414c9e'],
},
index: 0
}
},
methods: {
updateChartView () { // 更新视图
if (!this.myChart) return;
const fullOption = this.mergeDataToOption();
this.myChart.setOption(fullOption, true);
// 设置饼图默认选中一个
this.selectedOnePie();
},
mergeDataToOption () { // 合并并将数据加入到配置项
return merge(
{},
this.option,
this.extraOption
)
},
selectedOnePie () { // 默认选中一个饼图项
this.myChart.dispatchAction({ type: 'highlight', dataIndex: this.index }); // dataIndex属性为data传入的索引值
this.myChart.on('mouseover', (e) => { // 当鼠标移入的时候 使默认的索引值去除默认选中
if (e.dataIndex !== this.index) {
this.myChart.dispatchAction({ type: 'downplay', dataIndex: this.index });
}
});
this.myChart.on('mouseout', (e) => { // 当鼠标移出的时候,默认选中一项
this.myChart.dispatchAction({ type: 'highlight', dataIndex: this.index });
});
},
addChartResizeListener () { // 监听元素变化
// 创建实例带参
const instance = ResizeListener({
strategy: 'scroll',
callOnAdd: true
});
// 监听元素大小的变化
instance.listenTo(this.$refs.charts, () => {
if (!this.myChart) return;
this.myChart.resize();
});
},
handleClick () { // 点击图表触发
this.myChart.on('click', (event) => {
this.$emit('chart_click', event);
});
// 此处处理图例可点击且选中对应项问题
this.myChart.on('legendselectchanged', (event) => {
const arr = cloneDeep(event.selected);
const newArr = []; // 将图例的对象的key和值重新组合一个数组,以便于后期逻辑处理
for (const key in arr) {
newArr.push({
key: key,
value: arr[key]
})
}
this.myChart.dispatchAction({ type: 'downplay', dataIndex: this.index });
newArr.forEach((item, index) => {
if (item.key === event.name) {
if (item.value) { // 当前图例为true状态时,让当前项选中
this.myChart.dispatchAction({ type: 'highlight', dataIndex: index });
this.index = index;
} else {
// 如果当前点击图例为false的时候,默认让它的下一项选中,否则,再整个图例中查找选中的项目
if (newArr[index + 1] && newArr[index + 1].value) {
this.myChart.dispatchAction({ type: 'highlight', dataIndex: index + 1 });
this.index = index + 1;
} else {
let findIndex;
newArr.find((item, index) => {
if (item && item.value) {
findIndex = index;
}
})
this.myChart.dispatchAction({ type: 'highlight', dataIndex: findIndex });
this.index = findIndex;
}
}
}
})
});
}
},
mounted () {
if (!this.myChart) {
// 初始化图表
this.myChart = echarts.init(this.$refs.charts);
// 绘制图表
this.updateChartView();
// 设置饼图默认选中一个
this.selectedOnePie();
// 监听元素大小变化
this.addChartResizeListener();
// 绑定点击事件
this.handleClick();
}
},
}
</script>
<style lang="less" scoped>
.charts {
width: 100%;
height: 100%;
}
</style>
使用
<!--
* @Author: your name
* @Date: 2020-11-16 09:09:30
* @LastEditTime: 2020-12-08 11:16:00
* @LastEditors: Please set LastEditors
* @Description: 拆回原因统计
-->
<template>
<div>
<!-- 拆回原因统计 -->
<ChartPie :extraOption="extraOption" v-if="extraOption.series[0].data && extraOption.series[0].data.length > 0"></ChartPie>
<noDataChartsImg v-else></noDataChartsImg>
<div class="unit">单位:只</div>
</div>
</template>
<script>
import lodash from 'lodash';
import dateFormat from "dateformat";
import { getCauseStatistics } from '@/api/assetsAnalysisKanban/assetsDivestitureAnalysisQuery';
import ChartPie from '@/view/streamline/assetsAnalysisKanban/common/charts/ChartPie';
import noDataChartsImg from '../../common/chartsImg';
export default {
components: {
ChartPie,
noDataChartsImg
},
props: {
paramsGroup: {
type: Object,
default: () => {}
},
},
watch: {
paramsGroup: {
handler (val) {
if (!lodash.isEmpty(val)) {
this.getChartData();
}
},
deep: true
}
},
data () {
return {
extraOption: {
avoidLabelOverlap: true,
legend: {
data: [],
top: 'middle',
height: 190,
left: '56%',
type: 'scroll',
pageIconColor: '#2f4554', // 翻页按钮的颜色
pageIconInactiveColor: '#aaa', // 翻页按钮不激活时(即翻页到头时)的颜色
pageIconSize: 10, // 翻页按钮大小
pageFormatter: ({current, total}) => {
return `${current}/${total}`;
}, // 隐藏翻页的数字
pageButtonGap: 10, // 图例控制块和图例项之间的间隔
pageButtonPosition: 'end', // 'end' 'start
pageButtonItemGap: 6, // 翻页按钮的两个之间的间距
bottom: '12%',
formatter: (name, index) => {
let num = 0;
let text = '';
this.extraOption.series[0].data.forEach((item, index) => {
if (item.name === name) {
num = item.value
text = name.length > 3 ? name.substring(0, 3) + '...' : name;
}
})
const arr = [
'{aa|' + text + '}',
'{bb|' + num + '只}'
]
return arr.join('')
},
textStyle: {
rich: {
aa: {
fontSize: 14,
color: 'rgba(102, 102, 102, 1)',
fontWeight: 'normal',
padding: [-2, 0, 0, 5],
lineHeight: 18,
width: 50
},
bb: {
fontSize: 14,
color: 'rgba(51, 51, 51, 1)',
fontWeight: 'normal',
padding: [-2, 0, 0, 5],
lineHeight: 18
},
}
},
},
tooltip: {
trigger: 'item',
confine: true, // 将图表限制在区域内
formatter: function (params) { // 提示内容太多隔行显示内容
const str = `${params.marker} ${params.name} : ${params.value}只`
return str
},
},
series: [
{
radius: ['36%', '48%'],
center: ['27%', '50%'],
label: {
normal: {
show: false,
position: 'center',
formatter: (item) => {
const arr = [
'{a|' + item.percent + '}',
'{b|' + '%}\n',
'{c|' + (item.name.length > 8 ? item.name.substring(0, 8) + '...' : item.name) + '}'
]
return arr.join('')
},
rich: {
a: {
color: '#64879f',
fontSize: '24'
},
b: {
color: '#64879f',
fontSize: '24',
verticalAlign: 'middle'
},
c: {
color: '#666666',
fontSize: '13',
verticalAlign: 'middle',
padding: [0, 0, 5, 0],
}
}
},
emphasis: { // 高亮的图形样式和标签样式
show: true
},
},
data: [],
}
],
}
}
},
methods: {
getChartData () { // 获取图表数据
const params = {
orgNo: this.paramsGroup.deptCode,
statisDateStart: dateFormat(this.paramsGroup.statisDateStart, "yyyy-mm"),
statisDateEnd: dateFormat(this.paramsGroup.statisDateEnd, "yyyy-mm"),
}
getCauseStatistics(params).then((res) => {
const jsonData = res.data;
if (jsonData.status === 1 && jsonData.code === 200 && !lodash.isEmpty(jsonData.data)) {
const chartsData = jsonData.data.chartsData;
this.extraOption.series[0].data = [];
this.$nextTick(() => {
this.extraOption.legend.data = chartsData.legendData;
this.extraOption.series[0].data = chartsData.seriesData;
})
}
})
},
}
}
</script>
效果图