微信小程序基于高德地圖API實(shí)現(xiàn)天氣組件(動(dòng)態(tài)效果)
在社區(qū)翻騰了許久,沒有找到合適的天氣插件。迫不得已,只好借鑒互聯(lián)網(wǎng)上的web項(xiàng)目,手動(dòng)遷移到小程序中使用。現(xiàn)在分享到互聯(lián)網(wǎng)社區(qū)中,幫助后續(xù)有需要的開發(fā)者。
1.組件介紹
1.1 組件效果預(yù)覽圖
小程序組件繼承了外部樣式colorui的色彩,但實(shí)際動(dòng)畫會(huì)根據(jù)父節(jié)點(diǎn)的color屬性自動(dòng)填充顏色,即使不引入colorui這個(gè)樣式庫(kù),也可以在該組件引用外定義一個(gè)有color屬性的塊包裹該組件,同樣可以達(dá)到如圖的效果。

1.2 構(gòu)造形式

1.3 支持的動(dòng)畫效果
簡(jiǎn)單介紹下,動(dòng)畫由3個(gè)部分組成
一個(gè)是主體塊,這幾個(gè)動(dòng)畫中的大云朵就是;第二個(gè)是背景塊,如第一個(gè)中的太陽(yáng)和第三個(gè)中的多層云;第三個(gè)就是狀態(tài)塊,如第一個(gè)中的雨水和第二個(gè)中的雷。每個(gè)塊有且僅能展示一個(gè)??梢愿鶕?jù)自己的需要,自行組合這幾個(gè)塊,來滿足對(duì)應(yīng)的天氣需求。
注:如想要實(shí)現(xiàn)雷雨交加的效果,需要定義兩個(gè)動(dòng)畫,一個(gè)是雷一個(gè)是雨,然后通過定時(shí)器進(jìn)行動(dòng)畫的來回切換,如果有完成的可以在評(píng)論里留下代碼,我懶得實(shí)現(xiàn)了,哈哈。

2.組件的使用
組件的使用,需要授權(quán)獲取位置信息,在app.json中配置授權(quán)。
"permission": {
"scope.userLocation": {
"desc": "你的位置信息將用于定位效果和天氣信息展示"
}
}
組件配置完成后,在全局app.json中進(jìn)行引入。
"usingComponents": {
"uweather":"animation/uweather/weather"
}
組件有兩種模式:
用戶自定義模式默認(rèn)模式(引入amap-wx.js,申請(qǐng)高德地圖key,具體步驟參見參考文檔第一個(gè))
- 用戶自定義模式下,所有的信息包括動(dòng)畫和信息展示,都由用戶傳入的信息來控制。
- 默認(rèn)模式下,即用戶未傳入任何信息,這時(shí)候組件就會(huì)基于位置信息,請(qǐng)求高德地圖對(duì)應(yīng)接口來獲取地理位置及其天氣信息。
組件在被創(chuàng)建的時(shí)候會(huì)檢測(cè)是否有對(duì)應(yīng)值的傳入,如果有值傳入,那么就是用戶自定義模式,如果沒有值傳入,那么就是默認(rèn)模式。
lifetimes:{
attached(){
if(this.properties.winfo == null){
this.setData({
amapPlugin: new amap.AMapWX({
key: this.data.key
})
},()=>{
//獲取天氣信息
this.getWeather()
})
}
}
},
2.1 自定義模式

自定義模式下,傳入的數(shù)據(jù)要按照規(guī)定的的格式(也可以自己修改組件的屬性值)
例如在page中配置的屬性如下
weather:'雷',
winfo:{
province:'自定義省份',
city:'自定義城市',
temperature:'自定義溫度',
weather:'自定義天氣',
winddirection:'自定義風(fēng)向',
windpower:'自定義風(fēng)力'
}
wxml頁(yè)面中的組件使用如下
<uweather
weather="{{weather}}"
winfo="{{winfo}}"
>
</uweather>
那么對(duì)應(yīng)的組件展示效果就是這樣子的

2.2 默認(rèn)模式
默認(rèn)模式需要獲得用戶的地理位置信息授權(quán),確認(rèn)在app.json中進(jìn)行了授權(quán)配置和使用組件前完成了授權(quán)信息的校驗(yàn)。
組件生命周期會(huì)在每一次組件被裝如頁(yè)面樹時(shí),監(jiān)聽是否有對(duì)應(yīng)數(shù)據(jù)的傳入,如果沒有,就會(huì)請(qǐng)求對(duì)應(yīng)的接口,獲取地圖信息。使用默認(rèn)方法,還需要配置 https://restapi.amap.com 為合法的request域名和申請(qǐng)對(duì)應(yīng)的key用于開發(fā),申請(qǐng)步驟參見參考文檔。
默認(rèn)模式下不需要傳入任何參數(shù),直接引入組件即可。
<uweather> </uweather>
3.組件使用注意事項(xiàng)
默認(rèn)方法的天氣返回值具有很多種,具體使用還需要自己修改組件,完成不同天氣到對(duì)應(yīng)動(dòng)畫的映射,例如小雨、中雨、大雨都可以映射到雨這個(gè)動(dòng)畫狀態(tài)。下圖是高德地圖天氣API的部分信息,全部請(qǐng)參見參考文檔。

4.組件代碼
詳細(xì)的組件在項(xiàng)目中的使用結(jié)構(gòu) 請(qǐng)看[開源項(xiàng)目](miniprogram/animation/uweather · Kindear/校園小程序 - 碼云 - 開源中國(guó) (gitee.com)),記得給個(gè)⭐,感謝。
uweather.js
// animation/uweather/rain.js
const amap = require('../../lib/amap-wx.js');
Component({
options: {
addGlobalClass: true,
multipleSlots: true
},
/**
* 組件的屬性列表
*/
properties: {
weather:{
type:String,
value:'',
observer:function(n,o){
//天氣變化
}
},
winfo:{
type:Object,
value:null,
observer:function(n,o){
//如果有自定義的值就使用自定義的值
this.setData({
obj:n
})
}
}
},
/**
* 組件的初始數(shù)據(jù)
*/
data: {
amapPlugin: null,
key: "6799b5f6f88d3d9fb52ac244855a8759",
obj:{},
},
lifetimes:{
attached(){
if(this.properties.winfo == null){
this.setData({
amapPlugin: new amap.AMapWX({
key: this.data.key
})
},()=>{
this.getWeather()
})
}
}
},
/**
* 組件的方法列表
*/
methods: {
//獲取天氣數(shù)據(jù)
getWeather:function(){
wx.showLoading({
title: '請(qǐng)稍候...'
})
// type:天氣的類型。默認(rèn)是live(實(shí)時(shí)天氣),可設(shè)置成forecast(預(yù)報(bào)天氣)。
// city:城市對(duì)應(yīng)的adcode,非必填。為空時(shí),基于當(dāng)前位置所在區(qū)域。 如:440300,返回深圳市天氣
// success(data) :調(diào)用成功的回調(diào)函數(shù)。
// fail(info) :調(diào)用失敗的回調(diào)函數(shù)。
this.data.amapPlugin.getWeather({
success: (data) =>{
//成功回調(diào)
console.log(data)
wx.hideLoading()
this.setData({
obj:data.liveData,
})
if(this.properties.weather == ''){
this.setData({
weather:data.liveData.weather
})
}
},
fail: function (info) {
//失敗回調(diào)
console.log(info)
}
})
},
}
})
uweather.wxml
<view class="padding-sm">
<view class="bg-gradual-blue padding radius shadow-blur" style="display: flex;flex-direction: row;">
<view style="width:50%;height:100%;color:#1A94E6;">
<view class="icon sun-shower " wx:if="{{weather == '太陽(yáng)雨'}}">
<view class="cloud"></view>
<view class="sun"><view class="rays"></view></view>
<view class="rain"></view>
</view>
<view class="icon sun-shower " wx:if="{{weather == '多云'}}">
<view class="cloud"></view>
<view class="sun"><view class="rays"></view></view>
</view>
<view class="icon thunder-storm" wx:if="{{weather == '雷'}}">
<view class="cloud"></view>
<view class="lightning">
<view class="bolt"></view>
<view class="bolt"></view>
</view>
</view>
<view class="icon cloudy" wx:if="{{weather == '陰'}}">
<view class="cloud"></view>
<view class="cloud"></view>
</view>
<view class="icon flurries" wx:if="{{weather == '雪'}}">
<view class="cloud"></view>
<view class="snow">
<view class="flake"></view>
<view class="flake"></view>
</view>
</view>
<view class="icon sunny" wx:if="{{weather == '晴'}}">
<view class="sun"><view class="rays"></view></view>
</view>
<view class="icon rainy" wx:if="{{weather == '雨'}}"><view class="cloud"></view></view>
</view>
<!--文字部分-->
<view style="width:50%;height:100%;">
<view class="title">
<view class="text-cut" style="margin-top:20rpx;">{{obj.province}}-{{obj.city}}</view>
<!--view class="text-cut">濕度:{{obj.humidity.data}}</view-->
<view class="text-cut" style="margin-top:20rpx;">溫度:{{obj.temperature}}℃</view>
<view class="text-cut" style="margin-top:20rpx;">天氣:{{obj.weather}}</view>
<view class="text-cut" style="margin-top:20rpx;">{{obj.winddirection}}風(fēng){{obj.windpower}}級(jí)</view>
</view>
</view>
</view>
</view>
uweather.wxss
body {
max-width: 42em;
padding: 2em;
margin: 0 auto;
color: #161616;
font-family: 'Roboto', sans-serif;
text-align: center;
background-color: currentColor;
}
h1 {
margin-bottom: 1.375em;
color: #fff;
font-weight: 100;
font-size: 2em;
text-transform: uppercase;
}
p,
a {
color: rgba(255,255,255,0.3);
font-size: small;
}
p { margin: 1.375rem 0; }
.icon {
position: relative;
display: inline-block;
width: 12em;
height: 10em;
font-size: 1em; /* control icon size here */
}
.cloud {
position: absolute;
z-index: 1;
top: 50%;
left: 50%;
width: 3.6875em;
height: 3.6875em;
margin: -1.84375em;
background: currentColor;
border-radius: 50%;
box-shadow:
-2.1875em 0.6875em 0 -0.6875em,
2.0625em 0.9375em 0 -0.9375em,
0 0 0 0.375em #fff,
-2.1875em 0.6875em 0 -0.3125em #fff,
2.0625em 0.9375em 0 -0.5625em #fff;
}
.cloud:after {
content: '';
position: absolute;
bottom: 0;
left: -0.5em;
display: block;
width: 4.5625em;
height: 1em;
background: currentColor;
box-shadow: 0 0.4375em 0 -0.0625em #fff;
}
.cloud:nth-child(2) {
z-index: 0;
background: #fff;
box-shadow:
-2.1875em 0.6875em 0 -0.6875em #fff,
2.0625em 0.9375em 0 -0.9375em #fff,
0 0 0 0.375em #fff,
-2.1875em 0.6875em 0 -0.3125em #fff,
2.0625em 0.9375em 0 -0.5625em #fff;
opacity: 0.3;
transform: scale(0.5) translate(6em, -3em);
animation: cloud 4s linear infinite;
}
.cloud:nth-child(2):after { background: #fff; }
.sun {
position: absolute;
top: 50%;
left: 50%;
width: 2.5em;
height: 2.5em;
margin: -1.25em;
background: currentColor;
border-radius: 50%;
box-shadow: 0 0 0 0.375em #fff;
animation: spin 12s infinite linear;
}
.rays {
position: absolute;
top: -2em;
left: 50%;
display: block;
width: 0.375em;
height: 1.125em;
margin-left: -0.1875em;
background: #fff;
border-radius: 0.25em;
box-shadow: 0 5.375em #fff;
}
.rays:before,
.rays:after {
content: '';
position: absolute;
top: 0em;
left: 0em;
display: block;
width: 0.375em;
height: 1.125em;
transform: rotate(60deg);
transform-origin: 50% 3.25em;
background: #fff;
border-radius: 0.25em;
box-shadow: 0 5.375em #fff;
}
.rays:before {
transform: rotate(120deg);
}
.cloud + .sun {
margin: -2em 1em;
}
.rain,
.lightning,
.snow {
position: absolute;
z-index: 2;
top: 50%;
left: 50%;
width: 3.75em;
height: 3.75em;
margin: 0.375em 0 0 -2em;
background: currentColor;
}
.rain:after {
content: '';
position: absolute;
z-index: 2;
top: 50%;
left: 50%;
width: 1.125em;
height: 1.125em;
margin: -1em 0 0 -0.25em;
background: #0cf;
border-radius: 100% 0 60% 50% / 60% 0 100% 50%;
box-shadow:
0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2),
-0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2),
-1.375em -0.125em 0 rgba(255,255,255,0.2);
transform: rotate(-28deg);
animation: rain 3s linear infinite;
}
.bolt {
position: absolute;
top: 50%;
left: 50%;
margin: -0.25em 0 0 -0.125em;
color: #fff;
opacity: 0.3;
animation: lightning 2s linear infinite;
}
.bolt:nth-child(2) {
width: 0.5em;
height: 0.25em;
margin: -1.75em 0 0 -1.875em;
transform: translate(2.5em, 2.25em);
opacity: 0.2;
animation: lightning 1.5s linear infinite;
}
.bolt:before,
.bolt:after {
content: '';
position: absolute;
z-index: 2;
top: 50%;
left: 50%;
margin: -1.625em 0 0 -1.0125em;
border-top: 1.25em solid transparent;
border-right: 0.75em solid;
border-bottom: 0.75em solid;
border-left: 0.5em solid transparent;
transform: skewX(-10deg);
}
.bolt:after {
margin: -0.25em 0 0 -0.25em;
border-top: 0.75em solid;
border-right: 0.5em solid transparent;
border-bottom: 1.25em solid transparent;
border-left: 0.75em solid;
transform: skewX(-10deg);
}
.bolt:nth-child(2):before {
margin: -0.75em 0 0 -0.5em;
border-top: 0.625em solid transparent;
border-right: 0.375em solid;
border-bottom: 0.375em solid;
border-left: 0.25em solid transparent;
}
.bolt:nth-child(2):after {
margin: -0.125em 0 0 -0.125em;
border-top: 0.375em solid;
border-right: 0.25em solid transparent;
border-bottom: 0.625em solid transparent;
border-left: 0.375em solid;
}
.flake:before,
.flake:after {
content: '\2744';
position: absolute;
top: 50%;
left: 50%;
margin: -1.025em 0 0 -1.0125em;
color: #fff;
opacity: 0.2;
animation: spin 8s linear infinite reverse;
}
.flake:after {
margin: 0.125em 0 0 -1em;
font-size: 1.5em;
opacity: 0.4;
animation: spin 14s linear infinite;
}
.flake:nth-child(2):before {
margin: -0.5em 0 0 0.25em;
font-size: 1.25em;
opacity: 0.2;
animation: spin 10s linear infinite;
}
.flake:nth-child(2):after {
margin: 0.375em 0 0 0.125em;
font-size: 2em;
opacity: 0.4;
animation: spin 16s linear infinite reverse;
}
/* Animations */
@keyframes spin {
100% { transform: rotate(360deg); }
}
@keyframes cloud {
0% { opacity: 0; }
50% { opacity: 0.3; }
100% {
opacity: 0;
transform: scale(0.5) translate(-200%, -3em);
}
}
@keyframes rain {
0% {
background: #0cf;
box-shadow:
0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2),
-0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2),
-1.375em -0.125em 0 #0cf;
}
25% {
box-shadow:
0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2),
-0.875em 1.125em 0 -0.125em #0cf,
-1.375em -0.125em 0 rgba(255,255,255,0.2);
}
50% {
background: rgba(255,255,255,0.3);
box-shadow:
0.625em 0.875em 0 -0.125em #0cf,
-0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2),
-1.375em -0.125em 0 rgba(255,255,255,0.2);
}
100% {
box-shadow:
0.625em 0.875em 0 -0.125em rgba(255,255,255,0.2),
-0.875em 1.125em 0 -0.125em rgba(255,255,255,0.2),
-1.375em -0.125em 0 #0cf;
}
}
@keyframes lightning {
45% {
color: #fff;
background: #fff;
opacity: 0.2;
}
50% {
color: #0cf;
background: #0cf;
opacity: 1;
}
55% {
color: #fff;
background: #fff;
opacity: 0.2;
}
}
參考文檔
入門指南-微信小程序SDK | 高德地圖API (amap.com)
天氣查詢-API文檔-開發(fā)指南-Web服務(wù) API | 高德地圖API (amap.com)
校園小程序: 基于強(qiáng)智教務(wù)系統(tǒng)的校園服務(wù)類小程序--多校版本(默認(rèn) 山科)使用云開發(fā) (gitee.com)
到此這篇關(guān)于微信小程序基于高德地圖API實(shí)現(xiàn)天氣組件(動(dòng)態(tài)效果)的文章就介紹到這了,更多相關(guān)微信小程序?qū)崿F(xiàn)天氣組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SVG動(dòng)畫vivus.js庫(kù)使用小結(jié)(實(shí)例代碼)
本文通過代碼給大家介紹SVG動(dòng)畫vivus.js庫(kù)使用小結(jié),代碼簡(jiǎn)單易懂,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧2017-09-09
css值轉(zhuǎn)換成數(shù)值請(qǐng)拋棄parseInt
絕大多數(shù)人喜歡用parseInt()把css中的字符串值轉(zhuǎn)換成數(shù)值2011-10-10
javascript實(shí)現(xiàn)鼠標(biāo)拖動(dòng)改變層大小的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)鼠標(biāo)拖動(dòng)改變層大小的方法,涉及javascript操作鼠標(biāo)事件及樣式的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04
詳解關(guān)于微信setData回調(diào)函數(shù)中的坑
這篇文章主要介紹了詳解關(guān)于微信setData回調(diào)函數(shù)中的坑,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02
不到200行 JavaScript 代碼實(shí)現(xiàn)富文本編輯器的方法
這篇文章主要介紹了不到200行 JavaScript 代碼實(shí)現(xiàn)富文本編輯器的方法,需要的朋友可以參考下2018-01-01
Javascript remove 自定義數(shù)組刪除方法
Javascript自定義數(shù)組刪除方法remove(),需要的朋友可以參考下。2009-10-10
Layui給數(shù)據(jù)表格動(dòng)態(tài)添加一行并跳轉(zhuǎn)到添加行所在頁(yè)的方法
今天小編就為大家分享一篇Layui給數(shù)據(jù)表格動(dòng)態(tài)添加一行并跳轉(zhuǎn)到添加行所在頁(yè)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-08-08

