午夜91福利视频,午夜成人在线观看,午夜在线视频免费观看,午夜福利短视频,精品午夜成人免费视频APP

小程序模板網

小程序canvas開發水果老虎機

發布(bu)時間:2020-05-22 09:56 所屬欄目:小程序開發教程

在這(zhe)個超長假期(qi)中,無(wu)聊。。。,所以(yi)動手(shou)做一個早就計劃要做的小玩意(yi), 水果*** ,嗯,這(zhe)是一個小程(cheng)序而(er)不是小游戲...

使用結構還是canvas?

使用(yong)(yong)(yong)模板結構(gou)(gou)(gou)(view)生(sheng)成水(shui)果盤的(de)(de)(de)好處一(yi)是(shi)(shi)用(yong)(yong)(yong)戶可(ke)自(zi)定義產出 n x n 的(de)(de)(de)定制化(hua)***,二(er)是(shi)(shi)容易通過(guo)算法(fa)樣式生(sheng)成布局,三是(shi)(shi)通過(guo) wx.selectQueryAll 的(de)(de)(de)方法(fa)能(neng)夠很方便的(de)(de)(de)抓到(dao)定位數據。但,問題是(shi)(shi)動(dong)(dong)畫性能(neng)過(guo)于孱弱(ruo),如圖構(gou)(gou)(gou)建一(yi)個 7x7 的(de)(de)(de)水(shui)果盤,動(dong)(dong)畫性能(neng)估計會慘不忍睹(du),而(er)且(qie)純粹(cui)模板結構(gou)(gou)(gou)無(wu)論使用(yong)(yong)(yong) animation 動(dong)(dong)畫方法(fa)還是(shi)(shi) css 的(de)(de)(de)keyframe的(de)(de)(de)動(dong)(dong)畫方法(fa)得到(dao)的(de)(de)(de)動(dong)(dong)畫效果都非常差(cha)(測(ce)試過(guo)的(de)(de)(de)結論),還有(you)是(shi)(shi)已知的(de)(de)(de)動(dong)(dong)畫方法(fa)可(ke)控性很差(cha)

使(shi)用canvas來生成(cheng)水果(guo)盤好(hao)處是(shi)(shi)動畫性(xing)(xing)能很好(hao)(canvas2d),但是(shi)(shi)定制(zhi)性(xing)(xing)和(he)擴展性(xing)(xing)比(bi)較差

so綜上考慮,使用(yong)模板(ban)(view)布局,使用(yong)canvas來實現動畫。既保(bao)證(zheng)了組(zu)件的性能,同時定制(zhi)型,擴展性也很(hen)好

準備計時器方法

動畫的生成離不(bu)開計(ji)時器(qi)方(fang)法(fa),settimeout/setinterval這兩兄弟真(zhen)的不(bu)夠看啊,問(wen)題還多(duo),做過web開發的一定都知道(dao) window.requestAnimationFrame ,這貨在(zai)小程序的計(ji)時器(qi)方(fang)法(fa)中不(bu)存在(zai),好在(zai) canvas2d 中可(ke)以使用 Canvas.requestAnimationFrame(function callback) 方(fang)法(fa)來實現

準備運動算法

在水果(guo)***中(zhong)(zhong),激活(huo)狀態會沿(yan)著(zhu)四方(fang)的水果(guo)盤做非線性(xing)運動(dong)(dong)(dong)(dong)(easeInOut比較好用),需(xu)要基礎(chu)的運動(dong)(dong)(dong)(dong)算(suan)法來計(ji)算(suan)實(shi)際(ji)的運動(dong)(dong)(dong)(dong)距離(li)。在 animation 動(dong)(dong)(dong)(dong)畫方(fang)法中(zhong)(zhong),我們可以使用 ease-in/ease-out 等(deng)緩(huan)動(dong)(dong)(dong)(dong)算(suan)法來實(shi)現動(dong)(dong)(dong)(dong)畫效(xiao)果(guo),但在這里(li)必(bi)須要借助(zhu) tween.js 中(zhong)(zhong)的緩(huan)動(dong)(dong)(dong)(dong)算(suan)法來實(shi)現運動(dong)(dong)(dong)(dong)效(xiao)果(guo)(因為需(xu)要控制運動(dong)(dong)(dong)(dong)節(jie)點)。

你會(hui)(hui)不會(hui)(hui)想(xiang)到用css的(de)(de)keyframe動(dong)(dong)畫(hua)來做這(zhe)個運動(dong)(dong)效(xiao)果(guo),經過我的(de)(de)測試,css的(de)(de)動(dong)(dong)畫(hua)和(he)animation的(de)(de)動(dong)(dong)畫(hua)會(hui)(hui)在每一(yi)條邊上實現一(yi)次(ease)緩動(dong)(dong)運動(dong)(dong)(很奇怪(guai)的(de)(de)效(xiao)果(guo)

使用其中一(yi)個,節省代碼量(liang)

/*
 * Tween.js
 * t: current time(當前時間);
 * b: beginning value(初始值);
 * c: change in value(變化量);
 * d: duration(持續時間)。
 */
// Quart 四次方的緩動
const easeInOutQuart = function (t, b, c, d) {
  if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
  return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}
復制代碼

tween算法是(shi)以時(shi)間(jian)為基準(時(shi)間(jian)比(bi)率 = 距離比(bi)率)來(lai)計算單位時(shi)間(jian)的實際運動距離

布局

以上(shang)面的圖為(wei)例,我們需要做一個 7 x 7 的水果(guo)盤,實際有效的獎品格子數為(wei) 7*4-4 共24個有效格子

有效格子算法

js

// 0-6 第一行所有格子全部有效  
// 21-27 最后一行所有格子全部有效  
// 中間部分 i%7===0 和 i%7 === (7-1) 有效
// 算法源碼有點無聊,依據上述思路,即可遍歷28個格子并標識獎品格子valide=true
// 可以擴展想一想 6x6 5x5,思路是一樣的
復制代碼

wxml

<view class="fruits-container" >
    <view class="fruits-table" >
        <block wx:for="{{ary}}" wx:key="index" >
            <view wx:if="{{item.valide}}" class="valide">{{item.title}}</view>
            <view wx:else class="in-valide"></view>
        </block>
    </view>
    <canvas type="2d" .... />
</view>
復制代碼

樣式

只(zhi)節(jie)選關鍵樣(yang)式(shi),目的是讓canvas覆蓋(gai)在水果(guo)盤上,長寬(kuan)一致

.fruits-container {
    position: relative;
    width: 400px;
    height: 400px;
    ...
}

.fruits-table {
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    ...
}
復制代碼

抓取位置信息

canvas的(de)繪制需要X軸(zhou), Y軸(zhou)的(de)精確信息,可以使(shi)用 wx.createSelectorQuery 方式抓取類名為‘valide’的(de) view (獎品格子)的(de)位置信息

let query = wx.createSelectorQuery().in(this)
query.selectAll(`.fruits-table .valide`).boundingClientRect(ret => {
    ....
    console.log(ret[0]) // top, left, right, bottom, width, height
    console.log(ret[1]) // top, left, right, bottom, width, height
    ...
    ...
    console.log(ret[23]) // top, left, right, bottom, width, height
})
復制代碼

得到每一個(ge)獎品格子的位置信息后,就可以使(shi)用canvas的 fillRect 方(fang)法來繪制(zhi)激活狀態了。

繪制一個激活狀態

let query = wx.createSelectorQuery().in(this)
query.selectAll(`.fruits-table .valide`).boundingClientRect(ret => {
    ....
    let {top, left, right, bottom, width, height} = ret[0]
    const canvasQuery = wx.createSelectorQuery()
    canvasQuery.select('#fruit-canvas')
    .fields({ node: true, size: true })
    .exec((res) => {
        const canvas = res[0].node
        const ctx = canvas.getContext('2d') 
        let x = top
        let y = left
        let dx = width
        let dy = height
        ctx.shadowOffsetX = 2
        ctx.shadowOffsetY = -2
        ctx.shadowColor = 'red'
        ctx.shadowBlur = 50
        ctx.lineWidth = 5
        ctx.strokeStyle = 'red'
        ctx.clearRect(0, 0, canvas.width, canvas.height)
        ctx.strokeRect(x, y, dx, dy)
    })
})
復制代碼

跑起來

已經繪制了一個激(ji)活狀(zhuang)態,接下(xia)來使它能夠簡單動起來

// 抽象激活方法  
functon rect(point, canvas){
    let {x, y, dx, dy} = getPosition(point)
    ctx.shadowOffsetX = 2
    ctx.shadowOffsetY = -2
    ...
    ...
    ctx.clearRect(0, 0, canvas.width, canvas.height) // 擦除整個水果盤
    ctx.strokeRect(x, y, dx, dy) // 繪制激活區域
}

function run(){
    setTimeout(()=>{
        if (ret.length) {
            let point = ret.shift()
            rect(point, canvas)
            run()
        }
    }, 100)
}
復制代碼

執行run方(fang)法(fa)后可以看(kan)到水果盤的激活(huo)狀態一步一步的往前走(zou)(100毫秒),拖(tuo)拉機(ji)終于可以啟動(dong)了(le)

配上運動算法

經過上面的試驗我們(men)終于可以看到基本的運(yun)(yun)動效果了,接下來配上運(yun)(yun)動算法(fa)和計時器方法(fa)

// Quart 四次方的緩動
const easeInOutQuart = function (t, b, c, d) {
  if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
  return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
}

let start = 0  // 開始時間
let begin = 0  // 開始獎品位置
let end = 23  // 終點位置,這里跑一圈
let during = 5000 // 運動總時間

// 1000/60 ≈ 17,
// 17毫秒即表示屏幕60幀刷新率每秒 ≈ requestAnimationFrame計數頻率(一般情況)  
const steper = () => {
  // left為位移距離
  // ***的運動位移是節點位移,不是精確位移
  // 所以這里用parseInt處理,只取整數部分
  // 數據變化為 0,1,2,3,4,5...23
  // 間隔時間/距離由easeInOutQuart算法計算
  var left = easeInOutQuart(start, begin, end, during);
  let idx = parseInt(left)
  start = start + 17; 
  if (idx <= end) {
    let point = this.ret[idx] // 取節點位置信息
    this.rect(point) // 繪制
  }
  
  // 時間遞增
  if (start <= during) {
    this.ctx.requestAnimationFrame(steper); // 計時器
  } else {
    // 動畫結束,這里可以插入回調...
    // callback()...
  }
};

steper(); // 啟動
復制代碼

以上為我的小程(cheng)序水果***的基本開發思(si)路(lu)


易(yi)優小程(cheng)序(企業版)+靈活(huo)api+前后代碼開源(yuan) 碼云(yun)倉庫:
本文地址://www.jinyoudianli.com/wxmini/doc/course/25254.html 復制鏈接 如需定制請聯(lian)系(xi)易優客服咨詢:

工作日 8:30-12:00 14:30-18:00
周六及部分節假日提供值班服務

易小優
轉人工 ×