开发工作中有个需要展示气温(折线)、天气(图片)、风羽(字体图标)的图表展示需求,之前用过highcharts的关于类似的chart,里面的风雨用的是自带的图片,但是现在要求风羽需要用字体图标渲染,于是我选择了比较熟悉的Echarts制作这个图表。
难点
- 风羽(字体图标)不仅需要显示,还需要旋转,但是旋转的时,风羽会偏移
- 各类元素之间需要分层显示
代码
/**
* SouthAsiaViewHighImpactWeatherSingleAirportChart.vue 逐3小时天气预报图
* @Author ZhangJun
* @Date 2024/6/19 10:18
**/
<template><div class="w-full h-full"></div>
</template>
<script>
import * as echarts from 'echarts';
import CanvasGridUtils from "@/utils/leaflet/CanvasGridUtils";
import moment from "moment/moment";export default {name: 'SouthAsiaViewHighImpactWeatherSingleAirportChart',data() {return {chartOption: {grid: {left: '5%',right: '5%',bottom: '3%',top: '5px',containLabel: true},tooltip: {trigger: 'axis',backgroundColor: 'rgba(0, 38, 72, 0.9)',borderColor: 'rgba(141, 180, 255, 0.31)',borderWidth: 2,formatter: (params) => {let [temperatureParams, weatherParams, windParams, levelParams] = params;let date = moment(temperatureParams?.name, 'YYYYMMDDHHmm').format('YYYY-MM-DD HH:mm');//温度值let temperatureValue = `${temperatureParams?.value}℃`;let temperatureMarker = temperatureParams?.marker;//天气let weatherValue = weatherParams?.value?.[2];let weatherMarker = weatherParams?.data.symbol;//风向/风力let windMarker = CanvasGridUtils.GetWindChar(windParams?.value?.[1]);let rotate = windParams?.data.label.rotate;let levelValue = `${levelParams?.value?.[1]}级`;return [`<div style="font-size: 14px; color: #FFFFFF;font-weight: bold;">${date}</div>`,`<div style="display: flex; justify-content: space-between; align-items: center;"><div style="padding: 0 10px;">${temperatureMarker}</div><div style="font-size: 12px; color: #FFFFFF;">${temperatureValue}</div></div>`,`<div style="display: flex; justify-content: space-between; align-items: center;"><img src="${weatherMarker.replace('image://', '')}" alt="${weatherValue}" style="width: 30px; height: 30px;"><div style="font-size: 12px; color: #FFFFFF;">${weatherValue}</div></div>`,`<div style="display: flex; justify-content: space-between; align-items: center;"><div style="transform: rotate(${rotate}deg);font-size: 30px;font-weight: bold;color: #FFFFFF;">${windMarker}</div><div style="font-size: 12px; color: #FFFFFF;">${levelValue}</div></div>`].join('');}},xAxis: {type: 'category',boundaryGap: false,axisLine: {show: false},axisTick: {show: false},splitLine: {show: false},axisLabel: {fontFamily: 'D-DIN,SAN-SERIF',fontSize: '12px',fontWeight: 'normal',color: '#FFFFFF',formatter: (value) => {return value ? moment(value, 'YYYYMMDDHHmm').format('HH:mm') : '';},},//日期数据data: ['202406280000', '202406280300', '202406280600', '202406280900', '202406281200', '202406281500', '202406281800', '202406282100']},yAxis: [{type: 'value',axisLine: {show: false},axisTick: {show: false},axisLabel: {show: false},splitLine: {show: false},min: -120,max: 60,},{type: 'value',axisLine: {show: false},axisTick: {show: false},axisLabel: {show: false},splitLine: {show: false},min: 0,max: 100,}],series: [{name: '温度',type: 'line',yAxisIndex: 0,label: {show: true,color: '#fff',align: 'center',formatter: '{c}℃'},lineStyle: {color: '#FFBC1E'},labelLayout(params) {return {x: params.rect.x - params.rect.width,y: params.rect.y < params.rect.height * 2 ? params.rect.y + params.rect.height * 3 : params.rect.y - params.rect.height,verticalAlign: 'middle',align: 'left'}},data: [-10, -12, 11, 13, 60, 23, 21, 11]},//天气{name: 'weather',type: 'pictorialBar',yAxisIndex: 1,symbolSize: 30,symbolOffset: [0, -65],label: {show: true,fontSize: 12,color: '#fff',offset: [0, -10],formatter: ({value}) => {return value?.[2];},},data: [{value: ['202406280000', 0, '晴'],symbol: `image://${require('@/assets/images/weather/晴.png')}`,},{value: ['202406280300', 0, '晴'],symbol: `image://${require('@/assets/images/weather/晴.png')}`,},{value: ['202406280600', 0, '多云'],symbol: `image://${require('@/assets/images/weather/多云.png')}`,},{value: ['202406280900', 0, '晴'],symbol: `image://${require('@/assets/images/weather/晴.png')}`,},{value: ['202406281200', 0, '晴'],symbol: `image://${require('@/assets/images/weather/晴.png')}`,},{value: ['202406281500', 0, '阵雨'],symbol: `image://${require('@/assets/images/weather/阵雨.png')}`,},{value: ['202406281800', 0, '阴'],symbol: `image://${require('@/assets/images/weather/阴.png')}`,},{value: ['202406282100', 0, '晴'],symbol: `image://${require('@/assets/images/weather/晴.png')}`,},]},//绘制风羽{name: 'winBarb',type: 'pictorialBar',yAxisIndex: 1,symbolSize: [0, 65],label: {show: true,fontFamily: 'iconfont',fontSize: 30,fontWeight: 'bold',color: '#fff',formatter: ({value}) => {return CanvasGridUtils.GetWindChar(value?.[1]);},},data: [{value: ['202406280000', 10],label: {rotate: 180,},}, {value: ['202406280300', 10],label: {rotate: 0,},}, {value: ['202406280600', 10],label: {rotate: 90,},}, {value: ['202406280900', 10],label: {rotate: 200,},}, {value: ['202406281200', 10],label: {rotate: 180,},}, {value: ['202406281500', 10],label: {rotate: 180,},}, {value: ['202406281800', 10],label: {rotate: 180,},}, {value: ['202406282100', 10],label: {rotate: 180,},}]},// 绘制风力等级图标{name: 'winLevel',type: 'pictorialBar',yAxisIndex: 1,symbolSize: [0, 20],label: {show: true,fontSize: 12,fontFamily: 'MiSans, sans-serif',color: '#fff',align: 'center',formatter: ({value}) => {let level = value?.[1];return `${level}级`;},},data: [['202406280000', 3],['202406280300', 3],['202406280600', 4],['202406280900', 5],['202406281200', 4],['202406281500', 3],['202406281800', 4],['202406282100', 3],]}]}}},methods: {/*** 初始化图表*/initChart() {echarts.init(this.$el).setOption(this.chartOption);},},mounted() {this.$nextTick(() => {this.initChart();});}
}
</script>