VUE3使用echars的雷达图绘制风向玫瑰图。
一、介绍风向玫瑰图
风向玫瑰图(Wind rose diagram)是一种用于显示风向和风速数据的图表。因为实际情况风向是0到360度任意一个值,在使用echars绘图的时候不可能绘制每一个方向,一般来说会按照第二张图的范围将方向归为16组绘制
二、代码:
1.容器代码
<el-card class="card-custom-body">
<!-- 为Echars准备一个定义宽高的DOM -->
<div ref="RoseChart" style="width: 100%; height: 500px; margin: 0 auto"></div>
</el-card>
const RoseChart = ref(null); // 创建DOM引用
const roseInfosList = ref([]); // 玫瑰风向图数据
function getList() {
getWindRoseGraphByConditions(queryParams.value).then((res) => {
if (res.code === 200) {
/* 由于echars雷达图绘制数据是逆时针的,而后端给我的数据是顺时针的
因此这里需要将之转换为逆时针,原理是数组除第一个数据其余数组倒置 */
// 1.获取玫瑰风图数据
const RoseOriginData = res.data.roseInfos;
// 获取数组第一个数据和其余数据
const [RoseFirstData, ...rest] = RoseOriginData;
roseInfosList.value = [RoseFirstData, ...rest.reverse()];
// 2.由于时间不确认,所以风图最大值不确认,因此需要根据数组设置最大值(雷达图必须设置每个轴的最大值)
const roseArrayMaxValue = Math.max(...RoseOriginData);
// 玫瑰图有5层,如果数组最大数不是5的倍数,那么刻度值就会有小数点,这里需要除5并向上取整,再成5,变成5的倍数,避免刻度有小数点的情况
const roseMaxValue = Math.ceil(roseArrayMaxValue / 5) * 5;
init(roseInfosList.value, roseMaxValue);
}
});
}
// 通过鼠标坐标计算鼠标在哪个轴
function getAxisIndex(angle) {
// 将角度转换为弧度
angle = (angle * Math.PI) / 180;
// 将极角的取值范围调整为 [0, 2 * Math.PI)
angle = (angle + 2 * Math.PI) % (2 * Math.PI);
// 计算角度所在的轴
let axisCount = 16; // 轴的数量
let axisIndex =
Math.floor((angle + Math.PI / axisCount) / (Math.PI / (axisCount / 2))) % axisCount;
// console.log('轴', axisIndex);
return axisIndex;
}
let myaxisIndex = undefined;
function getPosition(mychart) {
mychart.on('mousemove', function (params) {
if (params.event && params.event.offsetX && params.event.offsetY) {
const point = {
x: params.event.offsetX - mychart.getWidth() / 2,
y: mychart.getHeight() / 2 - params.event.offsetY,
};
const radius = Math.sqrt(Math.pow(point.x, 2) + Math.pow(point.y, 2));
const angle = Math.atan2(point.y, point.x);
const degree = (angle * 180) / Math.PI;
// console.log(`Radius: ${radius}, Angle: ${degree}`);
myaxisIndex = getAxisIndex(degree);
}
});
}
function init(RoseData, roseMaxValue) {
// 基于准备好的dom,初始化echars实例
var mychart = echarts.init(RoseChart.value);
// 指定图表的配置项和数据
var option = {
title: {
text: '玫瑰风向图',
left: 'center',
},
tooltip: {
trigger: 'item', // 触发类型
show: true,
formatter: function (params) {
getPosition(mychart);
const direction = [ '正北', '北西北', '西北', '西西北', '正西', '西西南', '西南', '南西南', '正南', '南东南', '东南', '东东南', '正东', '东东北', '东北', '北东北', ];
return `${direction[myaxisIndex]}风:${params.value[myaxisIndex]}`;
},
},
radar: {
axisLine: {
lineStyle: {
color: '#ddd',
width: 2,
},
},
// 将雷达图周围分为 5 个圆圈
splitNumber: 5,
// 设置圈圈样式
splitLine: {
lineStyle: {
color: '#ddd',
width: 2,
},
},
// shape: 'circle',
indicator: [
{ name: 'N', max: roseMaxValue, axisLabel: { show: true, color: '#000' } },
{ name: 'NNW', max: roseMaxValue },
{ name: 'NW', max: roseMaxValue },
{ name: 'WNW', max: roseMaxValue },
{ name: 'W', max: roseMaxValue },
{ name: 'WSW', max: roseMaxValue },
{ name: 'SW', max: roseMaxValue },
{ name: 'SSW', max: roseMaxValue },
{ name: 'S', max: roseMaxValue },
{ name: 'SSE', max: roseMaxValue },
{ name: 'SE', max: roseMaxValue },
{ name: 'ESE', max: roseMaxValue },
{ name: 'E', max: roseMaxValue },
{ name: 'ENE', max: roseMaxValue },
{ name: 'NE', max: roseMaxValue },
{ name: 'NNE', max: roseMaxValue },
],
},
series: [
{
type: 'radar',
symbol: 'circle', // set the symbol to circle
symbolSize: 8, // adjust the symbol size
itemStyle: {
color: '#1890ff',
borderColor: '#1890ff',
borderWidth: 2,
},
lineStyle: {
width: 2,
},
data: [
{
value: RoseData,
},
],
},
],
};
mychart.setOption(option);
}
3.绘制风向玫瑰图,一定要在组件挂载到 DOM 上后再调用,不然连容器都没有怎么绘制。
onMounted(() => {
getList();
});