墨迹api实现天气预测

news2024/12/26 22:32:37

文章目录

  • 需求背景
  • 解决效果
  • 接口地址
  • index.vue
    • weather.vue
    • 图标文件
  • 视频效果

需求背景

使用墨迹天气api实现天气预报,空气质量预报功能

解决效果

在这里插入图片描述
在这里插入图片描述

接口地址

墨迹天气

index.vue

<template>
  <div class="dqhjjc-wrap">
    <div class="first_level_heading">
      <span>大气环境检测</span>
      <el-select v-model="curCity" placeholder="站点类型" size="mini" style="width:130px" @change="getlist">
        <el-option v-for="item in citys" :label="item.label" :value="item.value"></el-option>
      </el-select>
    </div>
    <div class="main-con">
      <weather :sunSetHour="sunSetHour" :sunRiseHour="sunRiseHour" :hourlys="hourlys" :forecasts="forecasts"/>
    </div>
  </div>
</template>
<script>
import Weather from './weather'
import Real from './real'
import SiteAir from './siteAir'
import Wind from './wind'
import qs from 'qs'
import {
  data24hours,
  day15Data,
  aqis
} from './weatherData'

export default {
  name: 'YuxiEnvironmentalDqhjjc',
  components: {
    Weather,
    Real,
    SiteAir,
    Wind
  },
  data() {
    return {
      sunSetHour: 22,//日落小时
      sunRiseHour: 6,//日出小时
      hourlys: [],// 24小时天气数据
      forecasts: [],// 15天天气数据
      headers: {},
      citys: [
        { label: '玉溪市', value: 2851 },
        { label: '江川县', value: 2852 },
        { label: '澄江市', value: 2853 },
        { label: '通海县', value: 2854 },
        { label: '华宁县', value: 2855 },
        { label: '易门县', value: 2856 },
        { label: '峨山彝族自治县', value: 2857 },
        { label: '新平彝族傣族自治县', value: 2858 },
        { label: '元江哈尼族彝族傣族自治县', value: 2859 }
      ],
      curCity: 2851
    }
  },
  methods: {
    getlist() {
      // 天气实况
      fetch('http://aliv18.data.moji.com/whapi/json/alicityweather/condition', {
        method: 'POST',
        headers: this.headers,
        body: qs.stringify({ cityId: this.curCity })
      }).then(response => response.json()).then(res => {
        this.sunSetHour = new Date(res.data.condition.sunSet).getHours()
        this.sunRiseHour = new Date(res.data.condition.sunRise).getHours()
      })
      // 天气预报24小时
      fetch('http://aliv18.data.moji.com/whapi/json/alicityweather/forecast24hours', {
        method: 'POST',
        headers: this.headers,
        body: qs.stringify({ cityId: this.curCity })
      }).then(response => response.json()).then(res => {
        this.hourlys = res.data.hourly
      })
      // 天气预报15天
      fetch('http://aliv18.data.moji.com/whapi/json/alicityweather/forecast15days', {
        method: 'POST',
        headers: this.headers,
        body: qs.stringify({ cityId: this.curCity })
      }).then(response => response.json()).then(res => {
        this.forecasts = res.data.forecast
      })
      // AQI预报5天
      fetch('http://aliv18.data.moji.com/whapi/json/alicityweather/aqiforecast5days', {
        method: 'POST',
        headers: this.headers,
        body: qs.stringify({ cityId: this.curCity })
      }).then(response => response.json()).then(res => {
        // this.forecasts = res.data.forecast
        console.log(res, 3333)
      })
    }
  },
  mounted() {
    this.headers = new Headers()
    this.headers.append('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8')
    this.headers.append('Authorization', 'APPCODE f70abac0ebcb459588c96c4ec7a8bcad') // 登录凭证
    // this.getlist() // todo 天气接口次数有限
    // 模拟接口
    const self = this
    window.setTimeout(() => {
      self.hourlys = data24hours.data.hourly// 24小时数据
      self.forecasts = day15Data.data.forecast// 15天数据
      self.aqis = aqis.data.data.aqi // 当日aqi数据
    }, 500)
  }
}
</script>

weather.vue

<template>
  <div>
    <div class="wrap">
      <span class="panelSecondTitle">天气预警</span>
      <div class="btn">
        <button
          v-for="item in weatherTypes"
          :key="item.id"
          :class="weatherTypeActiveId === item.id?'select':''"
          @click="weatherTypeActiveId = item.id"
        >
          {{ item.label }}
        </button>
      </div>
    </div>
    <div id="weatherLineChart" :style="{height:weatherTypeActiveId==1?'185px':'230px'}">
      <div v-show="weatherTypeActiveId==1">
        <div class="weather24IconBox">
          <div v-for="(item, index) in weather24Icons" :key="index" class="iconItem">
            <div class="iconImg">
              <img :src="require(`/public/img/weather/${item.icon}.png`)"/>
            </div>
            <div class="iconCon">{{ item.con }}</div>
            <div class="state"></div>
          </div>
        </div>
        <div id="dqhjjc24WeatherChart" style="width: 1100px;height: 120px"></div>
      </div>
      <div v-show="weatherTypeActiveId!=1">
        <div class="weather15DayBox">
          <div v-for="(item, index) in weather15DayIcons" :key="index" class="iconItem">
            <div class="iconWeek">{{ item.week }}</div>
            <div class="iconDate">{{ item.date }}</div>
            <div class="iconImg">
              <img :src="require(`/public/img/weather/${item.icon}.png`)"/>
            </div>
            <div class="iconCon">{{ item.con }}</div>
          </div>
        </div>
        <div id="dqhjjc15WeatherChart" style="width: 900px;height: 120px"></div>
        <div class="weather15NightBox">
          <div v-for="(item, index) in weather15NightIcons" :key="index" class="iconItem">
            <div class="iconImg">
              <img :src="require(`/public/img/weather/${item.icon}.png`)"/>
            </div>
            <div class="iconCon">{{ item.con }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  props: ['sunSetHour', 'sunRiseHour', 'hourlys', 'forecasts'],
  data() {
    return {
      weatherTypes: [
        { label: '24小时', id: 1 },
        { label: '15天', id: 2 }
      ],
      weatherTypeActiveId: 1,
      my24Chart: null,
      my15Chart: null,
      weather24Icons: [],
      weather15DayIcons: [],
      weather15NightIcons: []
    }
  },
  watch: {
    hourlys: {
      handler: {
        handler(data) {
          const option = this.my24Chart.getOption()
          option.xAxis[0].data = data.map((item) => item.hour + ':00')
          option.series[0].data = data.map((item) => item.temp)
          this.weather24Icons = data.map((item) => {
            let temp = {}
            temp.con = item.condition
            temp.id = item.hour
            if (
              item.hour < this.sunSetHour &&
              item.hour >= this.sunRiseHour
            ) {
              temp.icon = 'W' + item.iconDay
            } else {
              temp.icon = 'W' + item.iconNight
            }
            return temp
          })
          this.my24Chart.setOption(option)
        }
      }
    },
    forecasts: {
      handler(data) {
        const option = this.my15Chart.getOption()
        option.xAxis[0].data = data.map((item) => item.predictDate.split('-')[1] + '/' + item.predictDate.split('-')[2])
        option.series[0].data = data.map((item) => item.tempDay)
        option.series[1].data = data.map((item) => item.tempNight)
        this.weather15DayIcons = data.map(item => ({
          icon: 'W' + item.conditionIdDay,
          con: item.conditionDay,
          date:
            item.predictDate.split('-')[1] +
            '/' +
            item.predictDate.split('-')[2],
          week: new Date(item.predictDate).format('l')
        }))
        this.weather15NightIcons = data.map(item => ({
          icon: 'W' + item.conditionIdNight,
          con: item.conditionNight
        }))
        this.my15Chart.setOption(option)
      }
    }
  },
  methods: {
    draw24WeatherChart() { // 24小时天气
      let chartDom = document.getElementById('dqhjjc24WeatherChart')
      if (chartDom == null) {
        return
      }
      echarts.dispose(chartDom)
      this.my24Chart = echarts.init(chartDom)
      const option = {
        color: ['#0C65F6', '#00D68A'],
        tooltip: {
          confine: true
        },
        grid: {
          left: '-2%',
          right: '0%',
          top: '17%  ',
          bottom: '5%',
          containLabel: true
        },
        legend: {
          show: false
        },
        xAxis: {
          type: 'category',
          axisLine: {
            lineStyle: {
              color: 'rgba(255,255,255,0.2)'
            }
          },
          interval: 1,
          axisLabel: {
            align: 'center',
            fontSize: 12,
            color: '#fff'
          },
          axisTick: {
            show: false
          },
          splitLine: {
            show: false
          },
          data: ['20:00', '21:00', '22:00', '23:00', '0:00', '1:00', '2:00', '3:00', '4:00', '5:00', '6:00', '7:00', '8:00', '9:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00']
        },
        yAxis: {
          show: false,
          type: 'value'
        },
        series: [
          {
            type: 'line',
            // showSymbol: false,
            smooth: true,
            name: '气温', // 图例对应类别
            data: ['15', '13', '12', '11', '11', '10', '10', '9', '8', '7', '7', '7', '6', '10', '13', '17', '18', '19', '19', '19', '19', '19', '19', '18', '17'], // 纵坐标数据
            areaStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1,
                [
                  {
                    offset: 0,
                    color: '#09515a'
                  },
                  {
                    offset: 0.5,
                    color: '#09515a'
                  },
                  {
                    offset: 1,
                    color: 'transparent'
                  }
                ],
                false
              )
            },
            lineStyle: {
              color: '#20b3c8',
              width: 2
            },
            itemStyle: {
              color: '#c3e2fc'
            },
            tooltip: {
              show: true,
              trigger: 'item',
              formatter: '{a}:<br />{c}℃'
            },
            label: {
              show: true,
              position: 'top',
              color: '#fff'

            }
          }
        ]
      }
      option && this.my24Chart.setOption(option)
      this.dragScroll('weatherLineChart')
    },
    draw15WeatherChart() {
      let chartDom = document.getElementById('dqhjjc15WeatherChart')
      if (chartDom == null) {
        return
      }
      echarts.dispose(chartDom)
      this.my15Chart = echarts.init(chartDom)
      const option = {
        grid: {
          left: '-3%',
          right: '0%',
          top: '0%  ',
          bottom: '-29%',
          containLabel: true
        },
        tooltip: {
          trigger: 'axis'
        },
        xAxis: [
          {
            type: 'category',
            data: ['10/09', '10/10', '10/11', '10/12', '10/13', '10/14', '10/15', '10/16', '10/17', '10/18', '10/19', '10/20', '10/21', '10/22', '10/23', '10/24'],
            show: false
          }
        ],
        yAxis: {
          type: 'value',
          show: false
        },
        series: [
          {
            data: ['20', '19', '21', '20', '24', '25', '25', '26', '24', '23', '24', '29', '31', '28', '28', '31'],
            type: 'line'
          },
          {
            data: ['7', '7', '7', '10', '13', '13', '14', '14', '9', '7', '11', '13', '14', '13', '13', '13'],
            type: 'line'
          }
        ]
      }
      option && this.my15Chart.setOption(option)
    },
    dragScroll(moveTarget) {
      const title = document.getElementById(moveTarget)
      let startScrollLeft = 0
      let startX = 0
      let dragging = false
      title.addEventListener('mousedown', function(e) {
        e.stopPropagation()
        startScrollLeft = title.scrollLeft
        startX = e.clientX
        dragging = true
      })

      title.addEventListener('mousemove', function(e) {
        if (dragging) {
          const distance = e.clientX - startX
          title.scrollLeft = startScrollLeft - distance
        }
      })

      title.addEventListener('mouseup', function() {
        dragging = false
      })

      // -----鼠标滑轮滚动-----
      title.addEventListener('wheel', event => {
        event.preventDefault()
        const delta = event.deltaX || event.deltaY
        title.scrollLeft += delta
      })
    }
  },
  mounted() {
    this.draw24WeatherChart()
    this.draw15WeatherChart()
  }
}
</script>

<style lang="scss" scoped>
.wrap {
  display: flex;
  justify-content: space-between;
  /*定义滚动条高宽及背景高宽分别对应横竖滚动条的尺寸*/
  .btn {
    height: 30px;
    border-radius: 5px;
    border: 1px solid rgb(35, 145, 255);
    box-sizing: border-box;
    overflow: hidden;

    > button {
      width: 70px;
      text-align: center;
      line-height: 30px;
      margin: 0;
      padding: 0;
      background-color: transparent;
      border: none;
      color: rgb(35, 145, 255);;

      &.select {
        background: rgb(35, 145, 255);;
        color: #fff;
      }
    }
  }
}

#weatherLineChart {
  width: 100%;
  height: 185px;
  flex-grow: 1;
  overflow-x: auto;
  position: relative;

  &::-webkit-scrollbar {
    width: 0px;
    height: 0px;
  }

  .weather24IconBox, {
    width: 1100px;
    height: calc(100% - 121px);
    display: flex;
    justify-content: space-around;
    overflow: hidden;
    margin-top: 10px;
    user-select: none;

    .iconItem {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;

      .iconImg {
        width: 25px;
        height: 25px;

        img {
          display: block;
          width: 100%;
          height: 100%;
        }
      }

      .iconCon {
        color: #ffffffde;
        font-size: 14px;
      }

      .state {
        width: 35px;
        margin-top: 2px;
        color: #ffff00;
        text-align: center;
        font-size: 12px;
        border: 1px solid #ffff00;
        border-radius: 5px;
        background: rgba(255, 255, 0, 0.2);
      }
    }
  }

  .weather15DayBox {
    display: flex;
    justify-content: space-between;
    width: 900px;
    height: 64px;
    padding-left: 2px;
    padding-right: 7px;
    margin-top: 10px;
    cursor: move;
    box-sizing: border-box;
    user-select: none;

    .iconItem {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;

      .iconWeek {
        font-size: 14px;
        color: #ffffffe6;
      }

      .iconDate {
        font-size: 12px;
        color: #ffffff87;
      }

      .iconImg {
        width: 20px;
        height: 20px;

        img {
          width: 100%;
          height: 100%;
        }
      }

      .iconCon {
        color: #ffffffde;
        font-size: 12px;
      }
    }
  }

  .weather15NightBox {
    width: 900px;
    height: calc(100% - 65px - 64px);
    display: flex;
    justify-content: space-between;
    cursor: move;
    box-sizing: border-box;
    padding-left: 12px;
    padding-right: 18px;
    user-select: none;

    .iconItem {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;

      .iconImg {
        width: 20px;
        height: 20px;

        img {
          width: 100%;
          height: 100%;
        }
      }

      .iconCon {
        color: #ffffffde;
        font-size: 12px;
      }
    }
  }
}
</style>

图标文件

视频效果

天气

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/698645.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pytorch快速入门中文——03

神经网络 原文&#xff1a;https://pytorch.org/tutorials/beginner/blitz/neural_networks_tutorial.html#sphx-glr-beginner-blitz-neural-networks-tutorial-py 可以使用torch.nn包构建神经网络。 现在您已经了解了autograd&#xff0c;nn依赖于autograd来定义模型并对其进…

win10系统打开程序和功能的几种方式介绍

一&#xff0c;简介 在工作中常常会用到安装和卸载软件的功能&#xff0c;需要打开“程序和功能”&#xff0c;本文主要介绍如几种打开“程序和功能”的方法&#xff0c;供参考。 二&#xff0c;四种方法介绍 四种方法分别是&#xff1a; 从控制面板打开&#xff1b;通过运…

VsCode尝试在目标目录创建文件时发生一个错误

桌面右击vscode图标以管理员身份运行就可以了 结束语&#xff1a; 希望这篇文章能帮助到大家&#xff0c;如有不对之处&#xff0c;还请指正。愿我们一起成长。

按unicode值比较数组中的字符串元素numpy.compare_chararrays()方法

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 对比两个数组中对应位置 的元素的unicode值大小 numpy.compare_chararrays() [太阳]选择题 关于以下代码的输出结果是? import numpy as np a np.array(["a","B","…

联邦聚合(FedAvg、FedProx、SCAFFOLD)

目录 联邦聚合算法对比(FedAvg、FedProx、SCAFFOLD) 解决问题 FedAvg FedProx SCAFFOLD 实验结果 联邦聚合算法对比(FedAvg、FedProx、SCAFFOLD) 论文链接&#xff1a; FedAvg&#xff1a;Communication-Efficient Learning of Deep Networks from Decentralized Data …

在线预览文件

当我们前端小伙伴在码代码的时候&#xff0c;总会不约而同地遇到一个问题&#xff1a;上传文件。一旦文件成功上传&#xff0c;后端就会慷慨地给我们一个下载地址&#xff0c;这是怎么实现在线预览或者直接下载呢&#xff1f;fliencn 是后端给的地址这种是另外起一个标签页预览…

【Android Framework系列】第3章 Zygote进程相关

1 Zygote简介 Zygote是Android中最重要的一个进程&#xff0c;Zygote进程和Init进程、SystemServer进程是Android最重要的三大进程。Zygote是Android系统创建新进程的核心进程&#xff0c;负责启动Dalvik虚拟机&#xff0c;加载一些必要的系统资源和系统类&#xff0c;启动sys…

DevExpress WinForms日程/日历组件,可轻松创建信息管理解决方案!(一)

通过DevExpress WinForms完全可定制的Scheduler和Calendar组件&#xff0c;可以轻松地提供Outlook启发的调度/信息管理解决方案&#xff0c;Scheduler控件提供了多个日历视图选项(日、周、月、时间轴等)&#xff0c;并包括一个全面的内置和完全可定制的编辑表单集合。 PS&…

项目经理专用-项目周报模板-yyyymmdd-大型公司可用项目

作为一个项目经理或者子项目经理&#xff0c;肯定要面对各种文档&#xff0c;尤其是各种 *了狗的周报月报&#xff0c;有的甚至有日报&#xff0c;不厌其烦。 这个时候&#xff0c;一套规整的周报模板就可以省我们太多事&#xff0c;而且看起来也很专业。 今天分享一套自己用…

5.7.2 UDP协议格式(一)——UDP差错控制

5.7.2 UDP协议格式&#xff08;一&#xff09;——UDP差错控制 前面我们学习了UDP数据报格式&#xff08;5.7.1 UDP概述&#xff09;我们知道UDP只是在IP数据报服务基础上增加了端口的复用和分用功能&#xff0c;以及差错控制的功能&#xff0c;这里我们就一起来学习一下UDP的…

破局之作:首部开源 AIGC 软件工程应用电子书《构筑大语言模型应用:应用开发与架构设计》...

TL;DR 版&#xff1b; 在线&#xff1a;https://aigc.phodal.com 下载 1&#xff1a;https://github.com/phodal/aigc/releases 下载 2&#xff1a;https://pan.baidu.com/s/1wGc75vVHaZwvZyHeltyt8w?pwdphod 2023 年的上半年里&#xff0c;我&#xff08;phodal&#xff09;和…

数据结构KMP算法详解

目录 1. KMP算法是什么&#xff1f; 2. KMP算法的由来 2.1 需要要解决的问题 2.2 一开始想到的方法 2.3 KMP算法诞生了 3.KMP算法的详解 4.KMP算法的实现 5.KMP算法的改进 1. KMP算法是什么&#xff1f; KMP算法是一种改进的字符串匹配算法&#xff0c;即可以快速的从主…

通用分页【下】(将分页封装成标签)

目录 一、debug调试 1、什么是debug调试&#xff1f; 2、debug调试步骤 3、实践 二、分页的核心 三、优化 分页工具类 编写servlet jsp代码页面&#xff1a; 分页工具类PageBean完整代码 四、分页标签 jsp代码 编写标签 tld文件 助手类 改写servlet 解析&…

Let's Learn .NET - Web 开发实战

点击蓝字 关注我们 编辑&#xff1a;Alan Wang 排版&#xff1a;Rani Sun Lets Learn .NET 系列 “Lets Learn .NET” 是面向全球的 .NET 初学者学习系列&#xff0c;旨在通过不同语言&#xff0c;帮助不同地区的开发者掌握最新的 .NET 开发知识与技能。 7月2日&#xff0c;“…

【文件传输FTP】网络杂谈(4)之文件传输协议FTP详解

涉及知识点 什么是 FTP&#xff0c;FTP的概念&#xff0c;FTP客户端程序cuteFTP&#xff0c;FTP客户程序浏览器&#xff0c;FTP的客户程序。深入了解FTP技术。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更多内容可去其主页关注下哈&#xff0c;不胜感激 文章…

Tips--解决SquareLine Studio create页面中只有desktop选项

解决SquareLine Studio create页面中只有desktop选项 前言问题解决方法方法1方法2 前言 LVGL是一个强大的GUI框架&#xff0c;很多电子爱好者使用很多。SquareLine Studio是针对LVGL的一款非常强大的图形化设计平台&#xff0c;大大缩减了UI设计的时间。 问题 但是很多小伙…

(二十三)专题地图编制——布局设置

专题地图编制——布局设置 ArcMap地图模板是一种事先设计好的地图样式和布局&#xff0c;可以用于快速创建具有一致性和专业外观的地图。在ArcMap中&#xff0c;可以通过在地图窗口中创建新地图或导入现有地图的方式来使用地图模板。地图模板通常包括基础地图数据、图例、标签…

使用 Jetpack Compose 构建 Switch

欢迎来到这篇关于如何使用 Jetpack Compose 构建 Switch&#xff08;开关&#xff09;的博客。Jetpack Compose 是 Google 的现代 UI 工具包&#xff0c;主要用于构建 Android 界面。它以声明式的方式简化了 UI 的开发。 一、什么是 Switch&#xff1f; 在 Android 中&#xf…

HOT27-合并两个有序链表

leetcode原题链接&#xff1a;合并两个有序链表 题目描述 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1…

React修改Antd组件的样式

修改默认的antd组件&#xff0c;需要使用global import React, { useState, useEffect } from react; import { Tabs, Rate, Steps } from antd; import styles from ./index.less;const Index (props) >{return (<div className{styles.class_steps}><Stepsprog…