酷站(www.ku0.com)-致力于为互联网从业者提供动力!

热门关键词:  企业  as  baidu  c4rp3nt3r  美女
【ECS精选特惠】新用户上云低至1折起
百度资源

微信小程序canvas开发水果老虎机的思路

来源:互联网搜集 作者:秩名 人气: 发布时间:2020-02-09
本篇文章主要介绍了微信小程序canvas开发水果老虎机的思路,对大家的学习或者工作具有一定的参考学习价值,感兴趣的小伙伴们可以参考一下,也感谢大家对酷站(ku0.com)的支持。

效果图:


使用结构还是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

<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(); // 启动
 

版权声明:本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 959677720#qq.cn(#换@) 举报,一经查实,本站将立刻删除。
原文链接:https://juejin.im/post/5e3c2d44f265da575e37a202

相关文章

  • 微信小程序实现多图上传的方法

    微信小程序实现多图上传的方法

    看一下效果图 index.html view class=imgs block wx:for={{ imgs }} wx:key={{ index }} view class=img-box image src={{ item }} / icon class=iconfont size=18px color=gray data-index={{ index }} bind:tap=close type=cancel/icon......
    06-20
  • Javascript执行流程细节的介绍

    Javascript执行流程细节的介绍

    Javascript从定义到执行,JS引擎在实现层做了很多初始化工作,因此在学习JS引擎工作机制之前,我们需要引入几个相关的概念:执行环境栈、全局对象、执行环境、变量对象、活动对象、作用域和作用域链等,这些概念正是JS引擎工作的核心组件......
    05-15
  • javascript代码是如何被压缩

    javascript代码是如何被压缩

    随着前端的发展,特别是 React , Vue 等构造单页应用的兴起,前端的能力得以很大提升,随之而来的是项目的复杂度越来越大。 此时的前端的静态资源也越来越庞大,而毫无疑问 javascript 资源已是前端的主体资源,对于压缩它的体积至为重......
    05-06
  • 解决React在安装antd之后出现的Can't resolve './locale'问题

    解决React在安装antd之后出现的Can't resolve './locale'问题

    React在安装antd之后出现的Cant resolve ./locale问题,是因为moment在2.2之后的版本都有问题,而react默认使用了最新的moment,但是在moment@2.18.1中是没有问题的。 解决方案就是配置webpack的alias,将所有的 moment 路径引用导入到 mo......
    05-03
  • jQuery实现移动端图片上传预览组件的方法

    jQuery实现移动端图片上传预览组件的方法

    我们先来捋一捋想要实现的功能: 预览 删除 压缩 上传到服务器 基本机构 这样,我们的组件结构就有了: ;!function(window, $, undefined){ function Upload() { }; Upload.prototype.change = function() { }; Upload.prototype.del = f......
    05-01
  • js解析JSON数据的详解

    js解析JSON数据的详解

    JSON 数据如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 { name : mkyong , age : 30, address : { streetAddress : 88 8nd Street , city : New York }, phoneNumber : [ { type : home , number : 111 111-1111 }, { type : ......
    04-21
  • js中间件设计模式的深入探讨与实例分析

    js中间件设计模式的深入探讨与实例分析

    中间件作为一些辅助处理功能,应用非常广泛,例如express中间件,redux中间件,koa中间件,那么中间件的设计模式到底是怎样的呢。结合中间件的使用实例探讨和总结一下中间件的设计思想和一般实现模式。 仿照redux中间件实现模式,看如下......
    04-11
  • Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式

    Quasar Input:type="number" 去掉上下小箭头 实现加减按钮样式

    实现效果 UI组件依然是使用 Quasar Framework。 先来看一下效果: 加减.gif input type=number 去掉上下小箭头 去掉上下小箭头,主要是css: input::-webkit-outer-spin-button,input::-webkit-inner-spin-button {-webkit-appearance: no......
    04-09
  • js实现登录时记住密码

    js实现登录时记住密码

    常见的很多网站登录,都有记住密码功能,下面是用js实现的记住密码功能(代码用的源生js,不用引入任何插件,大家如果引入了jQuery,可以进行修改,优化) js部分 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ......
    04-05
  • jQuery实现鼠标放置名字上显示详细内容气泡提示框效果

    jQuery实现鼠标放置名字上显示详细内容气泡提示框效果

    本文实例讲述了jQuery实现鼠标放置名字上显示详细内容气泡提示框效果的方法。分享给大家供大家参考,具体如下: 实现效果如上图,当鼠标放置到名字上时,则显示出内容详情。 实现具体过程如下: 1、需要加这句js ? 1 2 3 4 5 6 !--实现鼠......
    04-04

最新更新