<template>
|
<div class="population-distribution">
|
<div class="title">
|
<div class="left-box">人口分布</div>
|
</div>
|
<!-- 饼图 -->
|
<div class="container">
|
<div class="chartsGl" ref="charts"></div>
|
<!-- 饼图下面的底座 -->
|
<div class="buttomCharts"></div>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
//引入echart
|
import * as echarts from "echarts";
|
import "echarts-gl";
|
|
import { getPie3D, getParametricEquation } from "./chart"; //工具类js,页面路径自己修改
|
|
export default {
|
name: "Zysjg",
|
data() {
|
return {
|
optionData: [
|
{
|
name: "常驻人口", //名称
|
value: 23, //值
|
itemStyle: {
|
//颜色
|
color: "rgba(44, 247, 18, 0.8)",
|
},
|
},
|
{
|
name: "陌生人",
|
value: 46.2,
|
itemStyle: {
|
color: "rgba(67, 190, 252, 0.7)",
|
},
|
},
|
{
|
name: "搬离住户",
|
value: 10,
|
itemStyle: {
|
color: "rgba(253, 223, 52,0.6)",
|
},
|
},
|
{
|
name: "新入住户",
|
value: 20.8,
|
itemStyle: {
|
color: "rgba(3, 40, 250,0.4)",
|
},
|
},
|
],
|
statusChart: null,
|
option: {},
|
selectPeriod: 1,
|
};
|
},
|
created() {
|
// this.setLabel();
|
},
|
mounted() {
|
this.$nextTick(() => {
|
this.init();
|
//根据窗口变化自动调节图表大小
|
const that = this;
|
window.onresize = function () {
|
that.changeSize();
|
};
|
});
|
},
|
methods: {
|
// 初始化label样式
|
setLabel() {
|
this.optionData.forEach((item, index) => {
|
item.label = {
|
show: true,
|
position: "center",
|
formatter: ["{b|{b}}", "{d|{d}%}"].join("\n"), // 用\n来换行
|
rich: {
|
b: {
|
fontSize: 22,
|
color: "#fff",
|
textShadowColor: "#1c90a6",
|
textShadowOffsetX: 0,
|
textShadowOffsetY: 2,
|
textShadowBlur: 5,
|
},
|
d: {
|
// color: color[index],
|
align: "left",
|
},
|
},
|
};
|
});
|
},
|
//初始化构建
|
init() {
|
//构建3d饼状图
|
let chartDom = this.$refs["charts"];
|
this.statusChart = echarts.init(chartDom);
|
// let myChart = this.$echarts.init(document.getElementById("charts"));
|
// 传入数据生成 option ; getPie3D(数据,透明的空心占比(调节中间空心范围的0就是普通饼1就很镂空))
|
this.option = getPie3D(this.optionData, 0.85, 160, 25, 15);
|
|
//将配置项设置进去
|
this.statusChart.setOption(this.option);
|
//鼠标移动上去特效效果
|
// this.bindListen(myChart);
|
this.option.series.push({
|
name: "电梯状态", //自己根据场景修改
|
backgroundColor: "transparent",
|
type: "pie",
|
label: {
|
opacity: 1,
|
show: true,
|
position: "center",
|
formatter: ["{d|{d}%}", "{b|{b}}"].join("\n"), // 用\n来换行
|
rich: {
|
d: {
|
fontSize: 22,
|
color: "#fff",
|
textShadowColor: "#1c90a6",
|
textShadowOffsetX: 0,
|
textShadowOffsetY: 2,
|
textShadowBlur: 5,
|
},
|
b: {
|
color: "#fff",
|
align: "center",
|
},
|
},
|
},
|
startAngle: -40, // 起始角度,支持范围[0, 360]。
|
clockwise: false, // 饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
|
radius: ["20%", "50%"],
|
// center: ["50%", "50%"],
|
data: this.optionData,
|
itemStyle: {
|
opacity: 0, //这里必须是0,不然2d的图会覆盖在表面
|
},
|
});
|
this.statusChart.setOption(this.option);
|
},
|
// 监听鼠标事件,实现饼图选中效果(单选),近似实现高亮(放大)效果。
|
bindListen(myChart) {
|
let that = this;
|
let selectedIndex = "";
|
let hoveredIndex = "";
|
// 监听点击事件,实现选中效果(单选)
|
myChart.on("click", function (params) {
|
// 从 option.series 中读取重新渲染扇形所需的参数,将是否选中取反。
|
let isSelected =
|
!that.option.series[params.seriesIndex].pieStatus.selected;
|
let isHovered =
|
that.option.series[params.seriesIndex].pieStatus.hovered;
|
let k = that.option.series[params.seriesIndex].pieStatus.k;
|
let startRatio =
|
that.option.series[params.seriesIndex].pieData.startRatio;
|
let endRatio = that.option.series[params.seriesIndex].pieData.endRatio;
|
// 如果之前选中过其他扇形,将其取消选中(对 option 更新)
|
if (selectedIndex !== "" && selectedIndex !== params.seriesIndex) {
|
that.option.series[selectedIndex].parametricEquation =
|
getParametricEquation(
|
that.option.series[selectedIndex].pieData.startRatio,
|
that.option.series[selectedIndex].pieData.endRatio,
|
false,
|
false,
|
k,
|
that.option.series[selectedIndex].pieData.value
|
);
|
that.option.series[selectedIndex].pieStatus.selected = false;
|
}
|
// 对当前点击的扇形,执行选中/取消选中操作(对 option 更新)
|
that.option.series[params.seriesIndex].parametricEquation =
|
getParametricEquation(
|
startRatio,
|
endRatio,
|
isSelected,
|
isHovered,
|
k,
|
that.option.series[params.seriesIndex].pieData.value
|
);
|
that.option.series[params.seriesIndex].pieStatus.selected = isSelected;
|
// 如果本次是选中操作,记录上次选中的扇形对应的系列号 seriesIndex
|
isSelected ? (selectedIndex = params.seriesIndex) : null;
|
// 使用更新后的 option,渲染图表
|
myChart.setOption(that.option);
|
});
|
// 监听 mouseover,近似实现高亮(放大)效果
|
myChart.on("mouseover", function (params) {
|
// 准备重新渲染扇形所需的参数
|
let isSelected;
|
let isHovered;
|
let startRatio;
|
let endRatio;
|
let k;
|
// 如果触发 mouseover 的扇形当前已高亮,则不做操作
|
if (hoveredIndex === params.seriesIndex) {
|
return;
|
// 否则进行高亮及必要的取消高亮操作
|
} else {
|
// 如果当前有高亮的扇形,取消其高亮状态(对 option 更新)
|
if (hoveredIndex !== "") {
|
// 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 false。
|
isSelected = that.option.series[hoveredIndex].pieStatus.selected;
|
isHovered = false;
|
startRatio = that.option.series[hoveredIndex].pieData.startRatio;
|
endRatio = that.option.series[hoveredIndex].pieData.endRatio;
|
k = that.option.series[hoveredIndex].pieStatus.k;
|
// 对当前点击的扇形,执行取消高亮操作(对 option 更新)
|
that.option.series[hoveredIndex].parametricEquation =
|
getParametricEquation(
|
startRatio,
|
endRatio,
|
isSelected,
|
isHovered,
|
k,
|
that.option.series[hoveredIndex].pieData.value
|
);
|
that.option.series[hoveredIndex].pieStatus.hovered = isHovered;
|
// 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
|
hoveredIndex = "";
|
}
|
// 如果触发 mouseover 的扇形不是透明圆环,将其高亮(对 option 更新)
|
if (
|
params.seriesName !== "mouseoutSeries" &&
|
params.seriesName !== "pie2d"
|
) {
|
// 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
|
isSelected =
|
that.option.series[params.seriesIndex].pieStatus.selected;
|
isHovered = true;
|
startRatio =
|
that.option.series[params.seriesIndex].pieData.startRatio;
|
endRatio = that.option.series[params.seriesIndex].pieData.endRatio;
|
k = that.option.series[params.seriesIndex].pieStatus.k;
|
// 对当前点击的扇形,执行高亮操作(对 option 更新)
|
that.option.series[params.seriesIndex].parametricEquation =
|
getParametricEquation(
|
startRatio,
|
endRatio,
|
isSelected,
|
isHovered,
|
k,
|
that.option.series[params.seriesIndex].pieData.value + 5
|
);
|
that.option.series[params.seriesIndex].pieStatus.hovered =
|
isHovered;
|
// 记录上次高亮的扇形对应的系列号 seriesIndex
|
hoveredIndex = params.seriesIndex;
|
}
|
// 使用更新后的 option,渲染图表
|
myChart.setOption(that.option);
|
}
|
});
|
// 修正取消高亮失败的 bug
|
myChart.on("globalout", function () {
|
// 准备重新渲染扇形所需的参数
|
let isSelected;
|
let isHovered;
|
let startRatio;
|
let endRatio;
|
let k;
|
if (hoveredIndex !== "") {
|
// 从 option.series 中读取重新渲染扇形所需的参数,将是否高亮设置为 true。
|
isSelected = that.option.series[hoveredIndex].pieStatus.selected;
|
isHovered = false;
|
k = that.option.series[hoveredIndex].pieStatus.k;
|
startRatio = that.option.series[hoveredIndex].pieData.startRatio;
|
endRatio = that.option.series[hoveredIndex].pieData.endRatio;
|
// 对当前点击的扇形,执行取消高亮操作(对 option 更新)
|
that.option.series[hoveredIndex].parametricEquation =
|
that.getParametricEquation(
|
startRatio,
|
endRatio,
|
isSelected,
|
isHovered,
|
k,
|
that.option.series[hoveredIndex].pieData.value
|
);
|
that.option.series[hoveredIndex].pieStatus.hovered = isHovered;
|
// 将此前记录的上次选中的扇形对应的系列号 seriesIndex 清空
|
hoveredIndex = "";
|
}
|
// 使用更新后的 option,渲染图表
|
myChart.setOption(that.option);
|
});
|
},
|
// 自适应宽高
|
changeSize() {
|
this.statusChart.resize();
|
},
|
// 周期点击回调
|
selectPeriodClick(val) {
|
this.selectPeriod = val;
|
},
|
},
|
};
|
</script>
|
<style lang="scss" scoped>
|
//饼图(外面的容器)
|
.container {
|
width: 90%;
|
height: calc(100% - 20px);
|
padding-top: 15px;
|
}
|
//饼图的大小
|
.chartsGl {
|
height: 100%;
|
width: 100%;
|
// background: rgba(3, 40, 250, 0.3);
|
}
|
//饼图底座(我也想给你们底座图片 可是我不知道咋给)
|
.buttomCharts {
|
// background: center top url("../imgs/u111.png") no-repeat;
|
background-size: 100% 100%;
|
height: 95px;
|
width: 204px;
|
margin-top: -141px;
|
margin-left: 21%;
|
}
|
|
.title {
|
position: absolute;
|
top: 0;
|
left: 0;
|
height: 40px;
|
width: 100%;
|
background: #20426a;
|
font-size: 20px;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
color: #01c2ff;
|
.left-box {
|
margin-left: 20px;
|
}
|
.right-box {
|
margin-right: 20px;
|
display: flex;
|
.common {
|
margin-left: 10px;
|
height: 50px;
|
line-height: 50px;
|
cursor: pointer;
|
}
|
}
|
}
|
.fontsize20 {
|
font-size: 20px;
|
}
|
.fontsize16 {
|
font-size: 16px;
|
}
|
.population-distribution {
|
overflow-y: auto;
|
padding: 10px;
|
height: 100%;
|
box-sizing: border-box;
|
border: 1px solid #40a1f7;
|
position: relative;
|
background: rgba(3, 10, 14, 0.7);
|
}
|
</style>
|