wxml
<canvas style='width:{{windowWidth}}px;height:{{height}}px; position: fixed;' canvas-id="secondCanvas0">
</canvas>
<canvas style='width:{{windowWidth}}px;height:{{height}}px; position: fixed;' canvas-id="secondCanvas1"></canvas>
<view class='receivenow_view'>
<view class="receivenow_button_view" bindtap='{{!start_state?"shuffle_func":"card_selection_func"}}' style='margin-top:{{height+10}}px' animation="{{animation3}}">
<text>{{!start_state?"开始洗牌":"开始选牌"}}</text>
</view>
</view>
wxss
.receivenow_view {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-bottom: 80rpx;
}
.receivenow_button_view {
font-size: 30rpx;
color: #fff;
padding: 35rpx 190rpx;
border-radius: 60rpx;
background: linear-gradient(to right, #ff5846, #ff067a);
line-height: normal;
}
js
const animationFrame = require('../../utils/requestAnimationFrame.js')
const ctx0 = wx.createCanvasContext('secondCanvas0')
const ctx = wx.createCanvasContext('secondCanvas1')
Page({
/**
*
*/
data: {
//默认canvas高度
height: 375,
//默认canvas宽度
windowWidth: 375,
//背景资源
bg: "",
//卡片资源
card: "",
//是否开始洗牌
start_state: false,
//开场动画是否结束
kaichang: false,
// 是否开始选牌
card_selection: false,
//20张卡开场动画过后的所在位置x坐标
xarrs: [],
//20张卡开场动画过后的所在位置y坐标
yarrs: [],
//开场动画执行时间
start_time: 1500,
card_width: 46,
card_height: 76.3
},
onLoad: function(options) {
var that = this
//获取手机屏幕宽度
wx.getSystemInfo({
success(res) {
let windowWidth = res.windowWidth
let height = windowWidth
that.setData({
height: height,
windowWidth: windowWidth
})
}
})
// const ctx = wx.createCanvasContext('secondCanvas')
// ctx.clearRect(0, 0, that.data.windowWidth, that.data.height)
// ctx.draw()
this.init();
},
//初始化数据,获取绘图所需图片
init() {
var doAnimationFrame = animationFrame.doAnimationFrame
this.setData({
bg: "/img/bg.jpg",
card: "/img/card.png"
})
this.draw();
},
//开始画图
draw() {
var that = this
let width = that.data.windowWidth
let height = that.data.height
let nowtime = new Date().getTime()
let time = that.data.start_time
let card_width = that.data.card_width
let card_height = that.data.card_height
//用来存储所有卡片的x坐标和移动距离
let xarrs = []
//设置所有卡片的x坐标和移动距离
for (let i = 0; i < 20; i++) {
xarrs.push([width / 18, card_width * (i * 0.5)])
}
console.log(xarrs)
//用来存储所有卡片的y坐标和移动距离
let yarrs = [
[height / 2 - card_height / 2, 0]
]
//画一个背景
ctx0.drawImage(that.data.bg, 0, 0, width, height);
ctx0.draw()
// animationFrame.doAnimationFrame,e为回调执行时间
var rander = function(e) {
e = e ? e : nowtime
ctx.clearRect(0, 0, width, height) //清空所有的内容
//绘制卡片
for (let i = 0; i < xarrs.length; i++) {
ctx.drawImage(that.data.card, xarrs[i][0], yarrs[0][0], card_width, card_height);
//从新设置卡片的x坐标和剩余移动距离
xarrs[i] = that.move_x_func(xarrs[i][0], xarrs[i][1], time)
}
// console.log(arrs[0])
ctx.draw()
//如果开始执行动画时间到最后一次的时间大于动画执行时间则停止动画
if (e - nowtime < time) {
var id = animationFrame.doAnimationFrame(rander);
} else {
//开场动画结束保存其位置
that.setData({
xarrs: xarrs,
yarrs: yarrs,
kaichang: true
})
}
}
rander()
},
//x坐标位置,以及移动距离(px),两秒移动s,16ms移动多少;time动画持续时间返回一个arr
move_x_func(position, s, time) {
// console.log(position)
//动画持续时长两秒
position = parseFloat(position.toFixed(2))
//16ms移动的距离
let time_distance = parseFloat((s * 16 / time).toFixed(2))
s = parseFloat(s.toFixed(2))
if (s === 0) {
return [position, s];
} else {
return [position + time_distance, s - time_distance]
}
},
//y坐标位置,以及移动距离
move_y_func(position, s) {
},
//洗牌开始
shuffle_func() {
let that = this
let width = that.data.windowWidth
let height = that.data.height
let nowtime = new Date().getTime()
let time = that.data.start_time
let card_width = that.data.card_width
let card_height = that.data.card_height
let xarrs = that.data.xarrs
let yarrs = that.data.yarrs
let time1 = 0
//如果还未开场,不进行洗牌
if (!that.data.kaichang | that.data.start_state) {
return false;
}
var animation3 = wx.createAnimation({
duration: 300,
timingFunction: 'ease',
})
animation3.scale3d(0.1, 0.1, 0.1).step().scale3d(1, 1, 1).step();
that.setData({
animation3: animation3,
//洗牌开始了,改变是否洗牌的状态
start_state: true
})
let x = that.rnd(1, height / 2)
let ys = []
let xs = []
let centers = []
for (let i = 0; i < xarrs.length; i++) {
ys.push(that.rnd(height / 10, height / 8))
// xs.push(that.rnd(width / 8, width / 4))
xs.push(width / 10)
centers.push([that.rnd(width / 4, width / 2), that.rnd(height / 4, height / 2)])
}
//用户点击洗牌,执行另一个动画
var rander = function(e) {
ctx.clearRect(0, 0, width, height) //清空所有的内容
//设置中心点
ctx.translate(width / 2, height / 2);
for (let i = 0; i < xarrs.length; i++) {
//设定每次旋转的度数
// ctx.save()
ctx.rotate(time1 * Math.PI / 540);
ctx.drawImage(that.data.card, xs[i], ys[i], card_width, card_height);
// ctx.restore()
}
ctx.draw()
time1++
if (!that.data.card_selection) {
var id = animationFrame.doAnimationFrame(rander);
}
}
rander()
},
/**
* 选牌开始
* 所有当前卡牌归位
*/
card_selection_func() {
let that = this
//设置开始选牌为true
that.setData({
card_selection: true
})
},
//在min和max之间取随机
rnd(min, max) {
return min + Math.floor(Math.random() * (max - min + 1));
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function(options) {
var that = this;
return {
title: "塔罗牌测试",
path: '/pages/start/start',
imageUrl: "/img/share.png",
success: function(res) {
var shareTickets = res.shareTickets;
//如果分享不成功,或者不是到群
if (shareTickets.length == 0) {
return false;
}
}
}
},
})
requestAnimationFrame.js
// 模拟 web端的requestAnimationFrame
// lastFrameTime为上次更新时间
var lastFrameTime = 0;
var doAnimationFrame = function(callback) {
//当前毫秒数
var currTime = new Date().getTime();
//设置执行该函数的等待时间,如果上次执行时间和当前时间间隔大于16ms,则设置timeToCall=0立即执行,否则则取16-(currTime - lastFrameTime),确保16ms后执行动画更新的函数
var timeToCall = Math.max(0, 16 - (currTime - lastFrameTime));
// console.log(timeToCall)
var id = setTimeout(function() {
callback(currTime + timeToCall);
//确保每次动画执行时间间隔为16ms
}, timeToCall);
//timeToCall小于等于16ms,lastFrameTime为上次更新时间
lastFrameTime = currTime + timeToCall;
return id;
};
// 模拟 cancelAnimationFrame
var abortAnimationFrame = function(id) {
clearTimeout(id)
}
module.exports = {
doAnimationFrame: doAnimationFrame,
abortAnimationFrame: abortAnimationFrame
}
|
请发表评论