搖出微笑是一款功能非常簡潔的小程序,非常適合用來作為新手入門的第一個(gè)實(shí)戰(zhàn)項(xiàng)目。主要涉及到的功能有:小程序動(dòng)畫接口 ...
搖出微笑是一款功能非常簡潔的小程序,非常適合用來作為新手入門的第一個(gè)實(shí)戰(zhàn)項(xiàng)目。
主要涉及到的功能有:
首頁涉及兩部分主要功能,一個(gè)是動(dòng)畫,一個(gè)是用搖一搖的功能。
在這里就說一說實(shí)現(xiàn)思路,有興趣的同學(xué)可以去看源代碼,這樣比較直觀。
動(dòng)畫是使用微信提供的 wx.createAnimation 接口來實(shí)現(xiàn)的,也是想了解一下這個(gè)動(dòng)畫接口的完善度。
通過觀察渲染出來的Wxml文件,可以發(fā)現(xiàn) wx.craeteAnimation 設(shè)置的一些動(dòng)畫方法會(huì)在 view 標(biāo)簽中多處來的 style 中體現(xiàn)出來。
大概說一下實(shí)現(xiàn)首頁動(dòng)畫的思路吧
由于三個(gè)框的旋轉(zhuǎn)角度不一樣,所以我創(chuàng)建了三個(gè)動(dòng)畫實(shí)例
var createAnimation = function() {
return wx.createAnimation({
duration: 400,
timingFunction: 'ease-out',
transformOrigin: "0% 0%",
})
}
var animationItem0 = createAnimation()
var animationItem1 = createAnimation()
var animationItem2 = createAnimation()
然后用 AnimationData0 ,AnimationData1,AnimationData2 來分別存儲(chǔ) 動(dòng)畫數(shù)據(jù),用 arrAnimation 來存儲(chǔ)這是三個(gè) 動(dòng)畫數(shù)據(jù)。
Page({
data: {
AnimationData0: {},
AnimationData1: {},
AnimationData2: {},
arrAnimation: [],
...
},
...
})
setAnimationData: function() {
this.setData({
AnimationData0: animationItem0.export(),
AnimationData1: animationItem1.export(),
AnimationData2: animationItem2.export()
})
var data1 = this.data.AnimationData0
var data2 = this.data.AnimationData1
var data3 = this.data.AnimationData2
var arr = [data1, data2, data3]
this.setData({arrAnimation: arr})
}
考慮到 Wxml 我是用 for循環(huán) 渲染出來的(其實(shí)也許直接用三個(gè) view 實(shí)現(xiàn)邏輯會(huì)更簡單),所以就需要?jiǎng)討B(tài)綁定每一個(gè)元素的ID,這樣才能知道哪個(gè)框是哪個(gè)動(dòng)畫,點(diǎn)擊的又是哪個(gè)框。
<view catchtouchend = "touchEnd">
<block wx:for="{{filterTips}}" wx:key="{{index}}">
<view id="item_{{index}}"
animation="{{arrAnimation[index]}}"
data-index="{{index}}"
class="item {{activeIndex == index ? 'touched' : 'untouched' }} " >
{{item.text}}
</view>
</block>
</view>
至于搖一搖功能,因?yàn)槲⑿艣]有提供具體的搖一搖接口,但是提供了重力感應(yīng)接口 wx.onAccelerometerChange,我們?nèi)绻胍褂脫u一搖功能,就得基于此來實(shí)現(xiàn)。
關(guān)于重力感應(yīng)有個(gè)問題就是,官方?jīng)]有提供停止監(jiān)聽重力感覺的接口,所以會(huì)導(dǎo)致一個(gè)情況就是:用戶在其他頁面時(shí),重力感應(yīng)依然在監(jiān)聽。一個(gè)不怎么好的解決方案時(shí)利用 頁面生命周期的 onHide ()函數(shù)。
通過這種方式,起碼用戶不會(huì)在其他頁面觸發(fā)搖一搖功能。
onHide: function() {
//當(dāng)前頁面處于onHide狀態(tài)
this.setData({onHide: true})
},
wx.onAccelerometerChange((res) => {
if(this.data.onHide === true) {
return
}
}
關(guān)于搖一搖的實(shí)現(xiàn),其本質(zhì)無非就是記錄一段時(shí)間內(nèi),重力感應(yīng)返回的三個(gè)方向的值變化有多大,如果超過某個(gè)閥值,則認(rèn)為用戶觸發(fā)了搖一搖事件。
wx.onAccelerometerChange((res) => {
if(this.data.onHide === true) {
return
}
var currentTime = new Date().getTime()
var SHAKE_THRESHOLD = app.globalData.sensitivity;
var lastUpdate = this.data.lastUpdate
if ((currentTime - lastUpdate) > 100) {
var diffTime = currentTime - lastUpdate;
var speed = Math.abs(res.x + res.y + res.z - this.data.lastX - this.data.lastY - this.data.lastZ) / diffTime * 10000;
if(speed > SHAKE_THRESHOLD && tag) {
tag = false
//用戶搖一搖后的代碼邏輯
//...
setTimeout(() => {
tag = true;
}, 800)
}
}
this.setData({
lastX: res.x,
lastY: res.y,
lastZ: res.z,
lastUpdate: currentTime
})
})
作為列表頁,主要涉及的就是 列表渲染,可滾動(dòng)視圖區(qū)域(scroll-view),上拉加載更多。
在 scroll-view 中 無法觸發(fā) onPullDownRefresh,也就是不支持下拉刷新。
若要使用下拉刷新,請使用頁面的滾動(dòng),而不是 scroll-view ,這樣也能通過點(diǎn)擊頂部狀態(tài)欄回到頁面頂部
這里涉及到一個(gè)思想,就是一個(gè)函數(shù)盡量做一件事。
具體來說,比如獲取列表的網(wǎng)絡(luò)請求我們就封裝成一個(gè)函數(shù),然后因?yàn)檎埱筚Y源列表時(shí)涉及到 per(一頁多少個(gè)) 和 page(第幾頁) 參數(shù),所以我們可以把 per 和 page 的值放在 data 中。
這樣就有一個(gè)好處。比如實(shí)現(xiàn)加載更多這個(gè)功能的時(shí)候,只需要把 page + 1,然后再去獲取資源列表就可以了。
看代碼
loadMore: function() {
this.setData({page: this.data.page + 1})
this.getList()
},
getList: function() {
var page = this.data.page;
var per = this.data.per;
wx.request({
url: 'https://xxxxx.com/',
data: {
page: page,
per: per
},
method: 'GET',
success: (res) => {
this.setData({listLi: this.data.listLi.concat(res.data)})
}
})
},
wxml的內(nèi)容就很簡單了,主要用到了微信提供的 列表渲染 功能
<view>
<view>
<scroll-view class="scroll" scroll-top="{{scrollTop}}" style="height:{{windowHeight}}px;" scroll-y="true" bindscroll="bindScrollHandel" bindscrolltolower="loadMore">
<view class="block" wx:for="{{listLi}}" wx:key="{{index}}" >
<text>{{item.text}}</text>
</view>
</scroll-view>
</view>
<view class="top" hidden="{{hiddenIcon}}" catchtap="goTop">?</view>
</view>
個(gè)人頁面在獲取用戶信息的時(shí)候用到了回調(diào)函數(shù),就重點(diǎn)說一下這個(gè)吧。
先看 app.js 這段代碼。
定義 getUserInfo 函數(shù),該函數(shù)接受一個(gè) 回調(diào)函數(shù) 作為參數(shù),邏輯是:如果 globalData 中有 userInfo 的值,就把該 userInfo 的值作為參數(shù)給這個(gè)回調(diào)函數(shù),反之,則調(diào)用 wx.login 和 wx.getUserInfo 獲取 userInfo,然后 賦值給 globalData.userInfo,并同樣的作為參數(shù)給這個(gè)回調(diào)函數(shù)。
getUserInfo: function(cb){
var that = this
if(this.globalData.userInfo){
typeof cb == "function" && cb(this.globalData.userInfo)
}else{
//調(diào)用登錄接口
wx.login({
success: function (res) {
wx.getUserInfo({
success: function (res) {
that.globalData.userInfo = res.userInfo
typeof cb == "function" && cb(that.globalData.userInfo)
}
})
}
})
}
},
個(gè)人頁面,調(diào)用 getUserInfo()以一個(gè)函數(shù)作為參數(shù),然后該函數(shù)的參數(shù)就有 userInfo 的值
onLoad: function () {
var that = this
//調(diào)用應(yīng)用實(shí)例的方法獲取全局?jǐn)?shù)據(jù)
app.getUserInfo(function(userInfo){
//更新數(shù)據(jù)
that.setData({
userInfo:userInfo
})
})
}
想一想,如果用戶是第一次使用,那么 globalData 中肯定沒有 userInfo 的值,這時(shí)候會(huì)從微信服務(wù)器中獲取,而如果 globalData 中 userInfo的值,那么就不從服務(wù)器中獲取,直接從globalData中取值即可。
這是我第一次寫教程,個(gè)人感覺寫的并不是很好,一方面是因?yàn)闆]有寫教程的經(jīng)驗(yàn),另一方面則是因?yàn)檎娴暮苊Γ栽谶@里跟大家說一說抱歉!然后附上這個(gè)小程序的源碼地址
如果你看了代碼后覺得有什么地方想找我探討的,可以來問我,我非常樂意跟你交流。
如果你看了代碼后愿意給我一些好的批評或者建議,我會(huì)非常開心。
源碼地址:https://github.com/wardenger/shakeTips(歡迎點(diǎn)star)
源碼下載:shakeTips-master.zip