[2025]使用echarts制作一个漂亮的天气预报曲线图

发布于:2025-09-15 ⋅ 阅读:(19) ⋅ 点赞:(0)

内容概况

非常简洁漂亮的天气效果, echarts中使用到了xAxis.axisLabel. rich, 效果很满意, 只展示了静态代码, 保存为html后就可以直接运行

echarts数据基于易客云天气API返回的json制作, 有需要的可以自己对接, 下一篇文章我会发布一个PHP对接版本

技术点:rich负责定义模板, formatter负责输出格式化后的数据, xAxis赋值是个数组列表, 第一组position为top, 顶部展示日期和天气图标, 另一组position为bottom, 位于底部展示星期

rich 的本质是定义一套 “样式模板”,在 axisLabel.formatter 中通过 {模板名|内容} 的语法调用模板,实现标签内多元素的样式分离。
要添加图标,只需在 rich 模板中通过 backgroundColor 或 textStyle 配置图片(本地 / 在线图片均可),再与文字内容组合即可。

效果预览 点击在线预览HTML

html我已经做好了, 点击上面的链接可预览效果
在这里插入图片描述

rich的使用

每个模板是一个独立的样式对象,核心属性:
width/height:控制图标尺寸(必须设置,否则图片可能拉伸异常);
backgroundColor.image:指定图标地址(支持本地路径 ./icon.png 或在线 URL);
padding:控制图标与文字的间距(上右下左,此处仅右间距 5px);
textStyle:控制文字样式(可单独抽成 text 模板复用)。

formatter

通过 {模板名|内容} 语法组合多段内容:
图标模板(如 foodIcon)的 “内容” 为空({foodIcon|}),仅显示背景图片;
文字模板(text)的 “内容” 为 X 轴数据({text|美食}),实现文字样式统一;
用 switch 语句根据不同 value 匹配不同图标,实现差异化显示。

实现代码

代码全部复制,另存为html就可以打开看到效果, 希望对初学者有所帮助

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>ECharts天气预报 - tianqiapi.com</title>
  <!-- 引入 ECharts CDN -->
  <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
  <style>
    #temperatureChart { width: 1200px; height: 500px; margin: 20px auto; }
  </style>
</head>
<body>
  <div id="temperatureChart" class="w-full h-full" style="user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); position: relative;"><div style="position: relative; width: 720px; height: 400px; padding: 0px; margin: 0px; border-width: 0px; cursor: default;"><canvas data-zr-dom-id="zr_0" width="1440" height="800" style="position: absolute; left: 0px; top: 0px; width: 720px; height: 400px; user-select: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); padding: 0px; margin: 0px; border-width: 0px;"></canvas></div></div>
  <p align="center" style="color:#666; font-size:14px;">数据来源:tianqiapi.com</p>

  <script>
    // 未来7天的天气数据
        const weatherData = {
            days: ['星期六', '星期日', '星期一', '星期二', '星期三', '星期四', '星期五'],
            dates: ['2025-09-13', '2025-09-14', '2025-09-15', '2025-09-16', '2025-09-17', '2025-09-18', '2025-09-19'],
            highTemp: [29, 30, 25, 27, 25, 24, 24],
            lowTemp: [19, 18, 19, 17, 16, 16, 17],
            weather: ['多云', '晴转多云', '小雨', '晴', '晴', '多云', '多云'],
            icons: ['sun-o', 'cloud-sun-o', 'cloud', 'cloud', 'cloud', 'cloud-rain', 'sun-o'],
            humidity: [45, 50, 55, 65, 70, 85, 40],
            wind: ['3级', '3-4级', '4级', '4-5级', '3级', '3-4级', '2级']
        };

        // 初始化ECharts图表
        function initTemperatureChart() {
            // 获取图表容器
            const chartDom = document.getElementById('temperatureChart');
            const myChart = echarts.init(chartDom);

            // 配置图表
            const option = {
                backgroundColor: 'transparent',
                tooltip: {
                    trigger: 'axis',
                    backgroundColor: 'rgba(255, 255, 255, 0.9)',
                    borderColor: '#eee',
                    borderWidth: 1,
                    textStyle: { color: '#333' },
                    formatter: function(params) {
                        let param = params[0];
                        return `<div class="font-medium">${weatherData.dates[param.dataIndex]}</div>
                            <div>最高温度: ${weatherData.highTemp[param.dataIndex]}°C</div>
                            <div>最低温度: ${weatherData.lowTemp[param.dataIndex]}°C</div>
                            <div>天气: ${weatherData.weather[param.dataIndex]}</div>`;
                    }
                },
                legend: {
                    data: ['最高温度', '最低温度'],
                    top: 0,
                    textStyle: { color: '#666' }
                },
                grid: {
                    left: '3%',
                    right: '4%',
                    bottom: '3%',
                    containLabel: true
                },
                xAxis: [{
                    type: 'category',
                    boundaryGap: false,
                    data: weatherData.days.map((day, i) => `${weatherData.days[i]}`),
            axisLine: {
                lineStyle: {
                    color: '#ddd'
                }
            },
            position: 'top',
                    axisLabel: {
                lineHeight: 30,
                        color: '#666',
                        rich: {
                    // 模板1:美食图标(本地/在线图片均可,此处用在线图标)
                    icon_qing: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/qing.png' // 图标地址
                        }
                    },
                    icon_yun: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/yun.png' // 图标地址
                        }
                    },
                    icon_yin: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/yin.png' // 图标地址
                        }
                    },
                    icon_lei: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/lei.png' // 图标地址
                        }
                    },
                    icon_xue: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/xue.png' // 图标地址
                        }
                    },
                    icon_shachen: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/shachen.png' // 图标地址
                        }
                    },
                    icon_wu: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/wu.png' // 图标地址
                        }
                    },
                    icon_bingbao: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/bingbao.png' // 图标地址
                        }
                    },
                    icon_yu: {
                        width: 25, // 图标宽度
                                height: 25, // 图标高度
                                backgroundColor: {
                            image: 'http://widget.tianqiapi.com/static/skin/peach/yu.png' // 图标地址
                        }
                    }
                },
                // 2. 调用 rich 模板,组合“图标+文字”
                formatter: function(value) {
                    // 根据 X 轴数据(value)匹配对应的图标模板
                    switch (value) {
                        case '星期六':
                            return '2025-09-13\n{icon_yun|}\n多云\n';
                        case '星期日':
                            return '2025-09-14\n{icon_yun|}\n晴转多云\n';
                        case '星期一':
                            return '2025-09-15\n{icon_yu|}\n小雨\n';
                        case '星期二':
                            return '2025-09-16\n{icon_qing|}\n晴\n';
                        case '星期三':
                            return '2025-09-17\n{icon_qing|}\n晴\n';
                        case '星期四':
                            return '2025-09-18\n{icon_yun|}\n多云\n';
                        case '星期五':
                            return '2025-09-19\n{icon_yun|}\n多云\n';

                        default:
                            return value;
                    }
                },
                // 标签横向对齐(避免图标偏移)
                align: 'center'
            }
        }, {
                type: 'category',
                        boundaryGap: false,
                        data: weatherData.days.map((day, i) => `${weatherData.days[i]}`),
                axisLine: {
                    lineStyle: {
                        color: '#ddd'
                    }
                },
                position: 'bottom',
                        axisLabel: {
                    lineHeight: 20,
                            color: '#666'
                }
            }, ],
            yAxis: {
                type: 'value',
                        name: '',
                        nameTextStyle: { color: '#666' },
                axisLine: {
                    lineStyle: { color: '#ddd' }
                },
                splitLine: {
                    lineStyle: { color: '#f0f0f0' }
                },
                axisLabel: {
                    formatter: '{value}',
                            color: '#666'
                },
                min: function(value) {
                    return value.min - 2; // 最小值向下调整2度
                },
                max: function(value) {
                    return value.max + 2; // 最大值向上调整2度
                }
            },
            series: [
                {
                    name: '最高温度',
                    type: 'line',
                    data: weatherData.highTemp,
                    symbol: 'circle',
                    symbolSize: 8,
                    lineStyle: {
                        width: 3,
                        color: '#F56C6C' // 暖色调
                    },
                    itemStyle: {
                        color: '#F56C6C',
                        borderWidth: 2,
                        borderColor: '#fff',
                        shadowBlur: 4,
                        shadowColor: 'rgba(245, 108, 108, 0.5)'
                    },
                    emphasis: {
                        scale: true,
                        symbolSize: 10
                    },
                    areaStyle: {
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            { offset: 0, color: 'rgba(245, 108, 108, 0.3)' },
                            { offset: 1, color: 'rgba(245, 108, 108, 0)' }
                        ])
                    }
                },
                {
                    name: '最低温度',
                    type: 'line',
                    data: weatherData.lowTemp,
                    symbol: 'circle',
                    symbolSize: 8,
                    lineStyle: {
                        width: 3,
                        color: '#4E5BA6' // 冷色调
                    },
                    itemStyle: {
                        color: '#4E5BA6',
                        borderWidth: 2,
                        borderColor: '#fff',
                        shadowBlur: 4,
                        shadowColor: 'rgba(78, 91, 166, 0.5)'
                    },
                    emphasis: {
                        scale: true,
                        symbolSize: 10
                    },
                    areaStyle: {
                        color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                            { offset: 0, color: 'rgba(78, 91, 166, 0.3)' },
                            { offset: 1, color: 'rgba(78, 91, 166, 0)' }
                        ])
                    }
                }
            ]
        };

            // 设置图表配置项
            myChart.setOption(option);

            // 响应窗口大小变化
            window.addEventListener('resize', function() {
                myChart.resize();
            });
        }
        document.addEventListener('DOMContentLoaded', function() {
            initTemperatureChart();
        });
  </script>
</body>
</html>