亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

微信小程序canvas開發水果老虎機的思路詳解

發布時間:2020-09-12 18:19:13 來源:腳本之家 閱讀:181 作者:天天修改 欄目:web開發

在這個超長假期中,無聊。。。,所以動手做一個早就計劃要做的小玩意, 水果老虎機 ,嗯,這是一個小程序而不是小游戲...

微信小程序canvas開發水果老虎機的思路詳解 

使用結構還是canvas?

使用模板結構(view)生成水果盤的好處一是用戶可自定義產出 n x n 的定制化老虎機,二是容易通過算法樣式生成布局,三是通過 wx.selectQueryAll 的方法能夠很方便的抓到定位數據。但,問題是動畫性能過于孱弱,如圖構建一個 7x7 的水果盤,動畫性能估計會慘不忍睹,而且純粹模板結構無論使用 animation 動畫方法還是 css 的keyframe的動畫方法得到的動畫效果都非常差(測試過的結論),還有是已知的動畫方法可控性很差

使用canvas來生成水果盤好處是動畫性能很好(canvas2d),但是定制性和擴展性比較差

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

準備計時器方法

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

準備運動算法

在水果老虎機中,激活狀態會沿著四方的水果盤做非線性運動(easeInOut比較好用),需要基礎的運動算法來計算實際的運動距離。在 animation 動畫方法中,我們可以使用 ease-in/ease-out 等緩動算法來實現動畫效果,但在這里必須要借助 tween.js 中的緩動算法來實現運動效果(因為需要控制運動節點)。

你會不會想到用css的keyframe動畫來做這個運動效果,經過我的測試,css的動畫和animation的動畫會在每一條邊上實現一次(ease)緩動運動(很奇怪的效果)

推薦這篇文章

使用其中一個,節省代碼量

/*
 * 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算法是以時間為基準(時間比率 = 距離比率)來計算單位時間的實際運動距離

布局

以上面的圖為例,我們需要做一個 7 x 7 的水果盤,實際有效的獎品格子數為 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>

樣式

只節選關鍵樣式,目的是讓canvas覆蓋在水果盤上,長寬一致

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

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

抓取位置信息

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

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
})

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

繪制一個激活狀態

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)
  })
})

跑起來

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

// 抽象激活方法 
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方法后可以看到水果盤的激活狀態一步一步的往前走(100毫秒),拖拉機終于可以啟動了

配上運動算法

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

// 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(); // 啟動

總結

以上所述是小編給大家介紹的微信小程序canvas開發水果老虎機的思路詳解,希望對大家有所幫助!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

临高县| 五河县| 瑞安市| 汤阴县| 济南市| 抚顺县| 长阳| 威海市| 融水| 浦县| 吴堡县| 萝北县| 贵州省| 津南区| 郓城县| 若羌县| 友谊县| 绥滨县| 龙江县| 通化县| 光泽县| 修水县| 阳城县| 土默特右旗| 平和县| 莆田市| 龙岩市| 高密市| 黑河市| 沙湾县| 吴堡县| 宣城市| 巴林左旗| 榆林市| 阳朔县| 繁昌县| 晋城| 邵阳县| 翁牛特旗| 长寿区| 天峻县|