2024年《移动软件开发》实验二:小程序网络API:天气查询

一、小程序效果展示:

二、小程序功能

(一)基本功能

1.导航栏显示”今日天气“

2.点击地区文字可以修改地区

3.显示该地区的天气和温度

4.显示天气对应的图片

(二)额外功能

1.横向显示给该地区接下来24小时的天气情况。

2.添加背景面板

3.如果地区为雨天,增加雨点效果

三、基本步骤

  1. API密钥申请与服务器域名

(1)首先,进入和风天气开发服务 ~ 强大、丰富的天气数据服务网址,注册和风天气账号并申请API密钥。

(2)然后,进入微信小程序控制台微信公众平台。登录账号后,进入管理=>开发管理=>服务器域名,设置request的合法域名。

      2. 创建项目,并配置文件

(1)创建新的项目

(2)配置文件

https://gaopursuit.oss-cn-beijing.aliyuncs.com/2022/demo2_file.zip网址下载天气图片,创建文件夹images,将下载的天气图标放入images文件夹中。

删除不需要的文件和代码

     3.设计导航栏

修改app.json代码,对window属性进行调整,代码如下:

  "window": {
    "navigationBarTitleText": "今日天气",
    "navigationBarBackgroundColor": "#3883FA"
  },

4. **页面设计**

(1)背景设计:

​    选择合适的图片放入/images/icon中,然后编写如下代码:

<view class='container'>

  <image class="background-image" src="/images/icons/back.png" mode="aspectFill"></image>
  
</view>

​    对应container和background-image的css设置如下:

.container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-around;
}
.background-image {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1; /* 将背景图放在最底层 */
}
```

​    设计后效果如下:

(2)区域一:地区选择

​    使用picker控件,进行地域的选择。:

  <!-- 区域1:地区选择器 -->
  <picker mode='region' bindchange='regionChange'>
    <view>{{region}}</view>
  </picker>

​    效果图如下所示:

(3)区域二: 天气信息显示

​    使用text控件

  <view class="horizon-container">
    <text> {{now.temp}}° </text>
    <text class="weather-text">{{now.text}}</text>
  </view>

(4)区域三: 天气图标

​    使用image控件显示天气图标

  <!-- 区域3:天气图标 -->
  <image src='/images/{{now.icon}}.png' mode='widthFix'></image>

(5)区域四:显示接下来24小时天气

​    使用scroll-view控件,然后使用for循环从js代码中获取24个小控件:

  <scroll-view scroll-x="true" class="hourly-weather">
    <block wx:for="{{hours}}" wx:key="index">
      <view class="hour-item">
        <text class="hour-time">{{item.time}}:00</text>
        <image class="hour-icon" src="/images/{{item.icon}}.png"></image>
        <text class="hour-temp">{{item.temp}}°</text>
      </view>
    </block>
  </scroll-view>

​    为了美观,对应css如下:

.hourly-weather {
  width: 100%;
  display: flex;
  overflow-x: auto; /* 允许横向滚动 */
  white-space: nowrap; /* 防止内容换行 */
  padding: 10px 0;
  align-items: center;
}

.hour-item {
  width: 12%;
  flex-shrink: 0;
  display: inline-block;
  align-items: center; /* 水平居中 */
  margin-right: 10px;
  color: white;
}

.hour-time {
  display: block;
  font-size: 14px;
}

.hour-icon {
  display: block;
  width: 30px;
  height: 30px;
  margin: 5px 0;
}

.hour-temp {
  display: block;
  font-size: 16px;
  font-weight: bold;
}

​    实现效果如下:

(6)区域五: 多行天气信息

​    显示2行3列的天气信息

  <view class='detail'>
    <view class="bar">
      <view class='box'>湿度</view>
      <view class='box'>气压</view>
      <view class='box'>能见度</view>
    </view>
    <view class="bar">
      <view class='box'>{{now.humidity}}%</view>
      <view class='box'>{{now.pressure}}hPa</view>
      <view class='box'>{{now.vis}}km</view>
    </view>
    <view class="bar">
      <view class='box'>风向</view>
      <view class='box'>风速</view>
      <view class='box'>风力</view>
    </view>
    <view class="bar">
      <view class='box'>{{now.windDir}}</view>
      <view class='box'>{{now.windScale}}km/h</view>
      <view class='box'>{{now.windSpeed}}级</view>
    </view>
  </view>
.detail {
  width: 100%;
  display: flex;
  flex-direction: column;
}

.bar {
  display: flex;
  flex-direction: row;
  margin: 20rpx 0;
}

.box {
  width: 33.3%;
  text-align: center;
}

​    对应效果如下:

5. **功能实现**

(1)创建页面初始数据信息

​    data用于连接wxml的数据,包括地区、地区对应id、当前的天气状况(8项指标)以及接下来24小时的天气情况

```js
  data: {
    region:['山东省','青岛市','黄岛区'],
    id: 101220301,//对应的编号
    now: {
      temp: 0,//温度
      text:'未知',//内容
      icon:'999',//天气代码
      humidity: 0,//湿度
      pressure: 0,//大气压
      vis: 0,    //能见度
      windDir: 0,//风向
      windScale: 0,//风级
      windSpeed: 0//风速
    },
    hours: [                //用于获取24小时的天气情况
        { time: 0, icon: '100', temp: 20 },
        { time: 1, icon: '100', temp: 19 },
        { time: 2, icon: '100', temp: 19 },
        { time: 3, icon: '100', temp: 19 },
        { time: 4, icon: '100', temp: 19 },
        { time: 5, icon: '100', temp: 19 },
        { time: 6, icon: '100', temp: 19 },
        { time: 7, icon: '100', temp: 19 },
        { time: 8, icon: '100', temp: 19 },
        { time: 9, icon: '100', temp: 19 },
        { time: 10, icon: '100', temp: 19 },
        { time: 11, icon: '100', temp: 19 },
        { time: 12, icon: '100', temp: 19 },
        { time: 13, icon: '100', temp: 19 },
        { time: 14, icon: '100', temp: 19 },
        { time: 15, icon: '100', temp: 19 },
        { time: 16, icon: '100', temp: 19 },
        { time: 17, icon: '100', temp: 19 },
        { time: 18, icon: '100', temp: 19 },
        { time: 19, icon: '100', temp: 19 },
        { time: 20, icon: '100', temp: 19 },
        { time: 21, icon: '100', temp: 19 },
        { time: 22, icon: '100', temp: 19 },
        { time: 23, icon: '100', temp: 18 }
      ]
  },
```

(2)getWeather函数,用于**获取某地区的天气信息**(调用该函数前,应该知道对应地区的ID)。

​    首先向API发送id和key,获取当地的当前天气情况,然后判断是否是雨天。如果是雨天调用drawRain函数,产生雨滴效果,否则不产生雨滴效果。

  getWeather: function() {
    console.log(this.data.id)
    let that = this
    wx.request({
      url: 'https://devapi.qweather.com/v7/weather/now',
      data: {
        location: that.data.id,
        key: "32481277610c405b9f6cbfa910c2d165"
      },
      success: function(res) {
        console.log(res.data)
        that.setData({now: res.data.now})
        if(res.data.now.icon>=300&&res.data.now.icon<=470)    //用于产生雨点效果
        {
          that.drawRain();
        }
        else{
          that.clearRain()
        }
      }
    })
  },

(3)getHourly函数,用于获取某地区接下来24小时天气情况

​    向apihttps://devapi.qweather.com/v7/weather/24h发送id和key,获取数据信息;其中时间信息需要截取第11到13位,从而获得对应的小时数。```

getHourly:function(){
  let that = this
  wx.request({
    url: 'https://devapi.qweather.com/v7/weather/24h',
    data:{
      location:that.data.id,
      key: "32481277610c405b9f6cbfa910c2d165"
    },
    success:function(res){
      console.log(res.data)
      let hourlyData = res.data.hourly.map(item => {
        let st = item.fxTime.slice(11, 13); // 从 fxTime 中提取时间(小时)
        return {
          temp: item.temp,
          time: st,
          icon: item.icon
        };
      });

      // 更新页面数据
      that.setData({
        hours: hourlyData
      });
    }
  })

(4)getID函数,用于获取某个地区的ID,然后调用getWeather和getHourly。```js

 getId: function(city) {
    city = city.slice(0, -1)
    let that = this

    wx.request({
      url: 'https://geoapi.qweather.com/v2/city/lookup',
      data: {
        location: city,
        key: "32481277610c405b9f6cbfa910c2d165"
      },
      success: function(res) {
        that.setData({id: res.data.location[0].id})
        that.getWeather()
        that.getHourly()
      }
    })
  },

(5)当选择器发生变化时,可以自动加载新的地区的天气情况

  regionChange: function(e) {
    this.setData({region: e.detail.value})
    this.getId(this.data.region[1])
  },

(6)页面加载函数,进入页面首先调用getId,更新天气信息

  onLoad: function (options) {
    this.getId(this.data.region[1])
  },

(7)雨滴效果实现

​    首先,它通过获取屏幕宽高来确定绘制区域,然后生成一定数量的雨滴,每个雨滴都有随机的初始位置、长度、透明度和下落速度。通过在画布上绘制每个雨滴并不断更新其位置,实现了雨滴从上到下的下落效果。当雨滴超出屏幕底部时,它们会重新出现在顶部,循环往复,形成持续的降雨动画效果。

  drawRain: function () {
    const ctx = wx.createCanvasContext('rainCanvas', this);
    const w = wx.getSystemInfoSync().windowWidth;
    const h = wx.getSystemInfoSync().windowHeight;
    const raindrops = [];
    const numDrops = 100;

    for (let i = 0; i < numDrops; i++) {
      raindrops.push({
        x: Math.random() * w,
        y: Math.random() * h,
        length: Math.random() * 20 + 10,
        opacity: Math.random() * 0.5 + 0.5,
        speed: Math.random() * 3 + 2
      });
    }

    const draw = () => {
      ctx.clearRect(0, 0, w, h);
      ctx.setFillStyle('rgba(174,194,224,0.5)');
      ctx.setStrokeStyle('rgba(174,194,224,0.5)');
      ctx.setLineWidth(2);
      raindrops.forEach(drop => {
        ctx.beginPath();
        ctx.moveTo(drop.x, drop.y);
        ctx.lineTo(drop.x, drop.y + drop.length);
        ctx.stroke();

        drop.y += drop.speed;
        if (drop.y > h) {
          drop.y = -drop.length;
          drop.x = Math.random() * w;
        }
      });

      ctx.draw();
      requestAnimationFrame(draw);
    };

    draw();
  },

​    获取指定 `canvas-id` 的画布上下文,调用 `clearRect` 方法清空整个画布区域,然后通过 `ctx.draw()` 执行清空操作。最后,使用 `this.setData({ isRaining: false })` 更新状态,表示降雨已停止。

  clearRain: function() {
    const ctx = wx.createCanvasContext('rainCanvas'); // 假设你的 canvas-id 为 'rainCanvas'
    ctx.clearRect(0, 0, this.data.canvasWidth, this.data.canvasHeight); // 清空整个画布
    ctx.draw(); // 执行清空操作
    this.setData({ isRaining: false });
  },

​    对应的画布如下:

.rain-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: -1; /* 让雨滴效果在底层 */
}

​    实现效果如下:

四、遇到问题:

描述实验过程中所遇到的问题,以及是如何解决的。有哪些收获和体会,对于课程的安排有哪些建议。

问题:在设计查看24小时的天气情况时,不能正常横向显示,如图:

解决方案:修改hour-item,将display改为inline-block;然后为了保证其他组件垂直排列,将包含的组件的display设置位block

  • 26
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值