echarts 南丁格尔图 -- 拯救极小值
<template><div :id="id" :class="className" :style="{ height:height, width:width }" /></template><script>import { mapGetters } from "vuex";import "./themes/classic.js";export de
·
1. 理想状态
ECharts 中的饼图也支持通过设置 roseType 显示成南丁格尔图。
roseType: 'angle'
南丁格尔图会通过半径表示数据的大小,下图是官方示例的效果图:
感觉棒棒哒,有没有?😜
2. 现实光景
在实际使用时,就会发现一些问题。比如下面这个:由于数据值之间的差距多大,而南丁格尔图会通过半径表示数据的大小
,这就会造成极小值在图表中,半价会非常非常的小,如下图中的那一个“小红点”,十分尴尬:
在实际使用中,由于数据是从后台动态获取的,我们并不能保证数据的均匀性。因此,仅仅依靠 echarts 中关于南丁格尔图各个部分半径的默认设置,是不能完全满足合理展示数据这一基本需求的。
3. 放大数据
可以通过放大数据
, 解决上面那个问题。
基本思路如下:
放大数据:
选用一个合适的数字 additional 来放大要呈现的数据(如:最大的数据项的二分之一),原始数据项加上 additional ;设置图表数据:
将经过放大处理后的数据,用于设置图表的 series 的 data;计算tooltip使用的数据:
如果图表的 tooltip 中涉及数据项的显示,还需要将数据项“还原”(数据项的值减去第一步增加的值)。
其中,需要特别注意:数据值为0的项,是不需要进行放大和还原的处理了。
理清思路后,实现起来就比较容易了,下面是经过放大处理后的图表效果图(最小值:1,最大值:1967):
极小值 1 的显示,没有像之前那么迷你了!
关闭其它所有非 0 数据后,针对数据项 0 的显示也是正确的 – 没有出现负数的 tooltip 文字。
下面是这个图表组件的部分代码:
<template>
<div :id="id" :class="className" :style="{ height:height, width:width }" />
</template>
<script>
import { mapGetters } from "vuex";
import "./themes/classic.js";
let chart = null;
export default {
name: "StockPieChart",
props: {
className: {
type: String,
default: "chart",
},
id: {
type: String,
default: "chart",
},
width: {
type: String,
default: "200px",
},
height: {
type: String,
default: "200px",
},
},
data() {
return {
legendLabels: [...this.$store.getters.stockLegendLabels],
data: [...this.$store.getters.stockData],
};
},
computed: {
...mapGetters(["stockLegendLabels", "stockData"]),
},
watch: {
stockLegendLabels(newValue) {
if (newValue.length === 0) {
this.legendLabels = [];
}
for (let i = 0; i < newValue.length; i++) {
this.$set(this.legendLabels, i, newValue[i]);
}
this.$nextTick(() => {
this.paint();
});
},
stockData(newValue) {
if (newValue.length === 0) {
this.data = [];
}
for (let i = 0; i < newValue.length; i++) {
this.$set(this.data, i, newValue[i]);
}
this.$nextTick(() => {
this.paint();
});
},
},
mounted() {
this.drawChart();
},
beforeDestroy() {
if (!chart) {
return;
}
// 清空 resize 事件处理函数
window.removeEventListener("resize", this.resize);
window.removeEventListener('beforeunload', this.clearChart);
// 组件销毁前,回收图表
chart.dispose();
// chart.clear();
chart = null;
},
methods: {
drawChart() {
// 1. 创建图表实例
if (!chart) {
chart = this.$echarts.init(
document.getElementById(this.id),
"classic",
{
renderer: "svg",
}
);
}
this.paint();
window.addEventListener('beforeunload', this.clearChart);
// 4.设置图表在页面尺寸变化时,图表重新渲染排布
window.addEventListener("resize", this.resize);
},
// 绘制图表
paint() {
// 2. 设置图表基本配置
this.initChart();
// 3.获取图表数据并填入图表
this.setChartData();
},
initChart() {
chart.setOption({
baseOption: {
tooltip: {
trigger: "item",
position: "top",
formatter: "{b}: {c} ({d}%)",
},
legend: {
orient: "horizontal",
top: 0,
left: 30,
},
series: [
{
name: "库存状态",
type: "pie",
radius: ["40%", "70%"],
center: ["50%", "56%"],
avoidLabelOverlap: false,
label: {
show: false,
position: "center",
},
emphasis: {
label: {
show: true,
fontSize: "20",
fontWeight: "bold",
},
},
labelLine: {
show: false,
},
},
],
},
media: [
{
query: {
minAspectRatio: 1.5,
minWidth: 400,
},
option: {
legend: {
orient: "vertical",
},
},
},
],
});
},
setChartData() {
chart.showLoading();
chart.setOption({
legend: {
data: this.legendLabels,
},
series: [
{
data: this.data,
},
],
});
chart.hideLoading();
},
resize() {
chart.resize();
},
clearChart(){
this.$destroy();
}
},
};
</script>
在其它组件中,引入并注册后使用:
<stock-pie-chart id="stock" width="30vw" height="60vh" />
🎉🎉🎉🌹🌹🌹
更多推荐
已为社区贡献8条内容
所有评论(0)