小程序 大轉(zhuǎn)盤 抽獎(jiǎng) canvas animation

項(xiàng)目需求運(yùn)用到大轉(zhuǎn)盤 可設(shè)置概率 可直接自定義結(jié)果 效果如下?

?

兩種方法及結(jié)合法

一 通過(guò)canvas 實(shí)現(xiàn) 但是因?yàn)槎〞r(shí)器原因 手機(jī)端卡頓嚴(yán)重 故而最終使用了方法二 但也是該記錄下 學(xué)習(xí)canvas

二 通過(guò)小程序Api?animation完成完美解決卡頓問(wèn)題 更精確定位 有樣式缺陷 css無(wú)法解決樣式 自動(dòng)分配問(wèn)題 故結(jié)合一二兩種方法 出現(xiàn)第三種

三?通過(guò)小程序Api?animation 做動(dòng)畫旋轉(zhuǎn) 樣式用canvas來(lái)實(shí)現(xiàn) 完美解決各類問(wèn)題?

話不多說(shuō)踩坑部分 就不展示 直接上第三種方法

創(chuàng)建動(dòng)畫區(qū)域 (animation) 動(dòng)畫可參考小程序官方API?animationData動(dòng)畫參數(shù) 在點(diǎn)擊開始的時(shí)候填充數(shù)據(jù)

<view class="wrapper-content" style='margin:0 auto;'>

? <view class="canvas-container">

? ? <view animation="{{animationData}}" class="canvas-content" style='margin:0 auto;'>? ?

? ? </view>

? </view>

</view>

.wrapper-content{

? background: #E0CFBC;

? border-radius: 50%;

? width: 720rpx;

? height: 720rpx;

? padding: 40rpx;

? position: relative;

? box-sizing: border-box;

? z-index: 101;

}

.canvas-container {

? margin: 0 auto;

? position: absolute;

? left: 40rpx;

? top: 40rpx;

? width: 640rpx;

? height: 640rpx;

? border-radius: 50%;

}

.canvas-content {

? overflow: hidden;

? box-sizing: content-box;

? border: 20rpx solid #CDB193;

? position: absolute;

? left: 0;

? top: 0;

? z-index: 1;

? display: block;

? width: 600rpx;

? height: 600rpx;

? border-radius: inherit;

? background-clip: padding-box;

}

定義canvas 畫板區(qū)域? 設(shè)置ID?

<canvas class="canvas-line" disable-scroll="true" canvas-id="canvas"></canvas>

onReady: function(e) {

? ? let that = this,

? ? ? ? fps = 60,

? ? ? ? awardsConfig = that.data.awardsConfig,

? ? ? ? w = this.data.windowWidth / 750 * 600,

? ? ? ? h = this.data.windowWidth / 750 * 600,

? ? ? ? context = wx.createCanvasContext('canvas'),

? ? ? ? //定義canvas位置

? ? ? ? wheel = new Wheel(w / 2, w / 2, (w / 2) - 0, awardsConfig.slicePrizes),

? ? ? ? animation = new Animation(wheel, { w: w, h: h });

? ? ? ? wheel.prizeWidth = 30;

? ? ? ? wheel.prizeHeight = 30;

? ? // 更新動(dòng)畫

? ? let update = function () {

? ? ? // 清空

? ? ? context.clearRect(0, 0, w, h);

? ? ? // 畫轉(zhuǎn)盤

? ? ? wheel.draw(context);

? ? ? // 更新數(shù)據(jù)

? ? ? animation.draw(context);

? ? ? // 更新數(shù)據(jù)

? ? ? animation.update();

? ? ? // 繪圖?

? ? ? context.draw()

? ? };

? ? setTimeout(update, 1000 / fps, 1000 / fps)

}

1.awardsConfig.slicePrizes為獎(jiǎng)品列表? 因?yàn)榇筠D(zhuǎn)盤是圓的 所以W H 是一樣的?

2.this.data.windowWidth 是屏幕的寬度 小程序有API 可以獲取? 600是設(shè)置的轉(zhuǎn)盤內(nèi)容(canvas)的rpx寬度? 用屏幕寬度/750*設(shè)置內(nèi)容寬度rpx = 實(shí)際內(nèi)容寬度的px 值

3.wheel是canvas繪制轉(zhuǎn)盤的代碼 可自行修改參數(shù)

設(shè)置點(diǎn)擊抽獎(jiǎng)按鈕 兩種方法 一直接在canvas內(nèi)繪制? 二在HTML里面通過(guò)定位實(shí)現(xiàn)

提供二 HTML 定位實(shí)現(xiàn)按鈕

<view class="canvas-btn" bindtap="getLottery">

? ? ? ? <view>

? ? ? ? ? ? <view style="font-size:56rpx;color:#fff;padding-bottom:4rpx;">開始</view>

? ? ? ? ? ? <view style="font-size:20rpx;color:#6F5942;font-weight:600;">點(diǎn)擊抽獎(jiǎng)</view>

? ? ? ? ? </view>

</view>

.canvas-btn {

? display: flex;

? flex-direction: column;

? justify-content: space-around;

? position: absolute;

? left: 50%;

? top: 50%;

? margin-left: -110rpx;

? margin-top: -110rpx;

? z-index: 400;

? width: 220rpx;

? height: 220rpx;

? border-radius: 50%;

? color: #f4e9cc;

? border: 10px solid #cdb193;

? text-align: center;

? font-size: 40rpx;

? text-decoration: none;

? box-sizing: border-box;

}

.canvas-btn>view {

? position: absolute;

? top: 7%;

? left: 7%;

? width: 86%;

? height: 86%;

? border-radius: 50%;

? box-sizing: border-box;

? padding: 22rpx 20rpx 0;

? background: linear-gradient(134deg, rgba(232, 219, 197, 1) 0%, rgba(205, 177, 147, 1) 100%);

? /* box-shadow:0px 5px 7px 0px rgba(255,255,255,1); */

? margin: auto;

? z-index: 102;

}

.canvas-btn::after {

? position: absolute;

? display: block;

? content: ' ';

? left: 39%;

? top: -78%;

? width: 0;

? height: 0;

? overflow: hidden;

? border-width: 80rpx 20rpx 80rpx 20rpx;

? border-style: solid;

? border-color: transparent;

? border-bottom-color: #ffab52;

}

getLottery() {

? ? let that = this;

? ? // 獲取獎(jiǎng)品配置

? ? let awardsConfig = that.data.awardsConfig,

? ? ? ? runNum = 12, len = awardsConfig.slicePrizes.length,

? ? ? ? awardIndex = 0;

? ? awardIndex = parseInt(Math.random() * 6)

? ? console.log("獎(jiǎng)品序號(hào):" + awardIndex);

? ? // 旋轉(zhuǎn)抽獎(jiǎng)

? ? app.runDegs = app.runDegs || 0

? ? app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / len))

? ? //創(chuàng)建動(dòng)畫

? ? let animationRun = wx.createAnimation({

? ? ? duration: 4000,

? ? ? timingFunction: 'ease'

? ? })

? ? console.log(awardsConfig.slicePrizes[awardIndex]);

? ? that.animationRun = animationRun

? ? animationRun.rotate(app.runDegs - (360 / len * 2 + (360 / len)) ).step()

? ? that.setData({

? ? ? animationData: animationRun.export()

? ? })

? },

點(diǎn)擊按鈕觸發(fā)getLottery 進(jìn)行動(dòng)畫數(shù)據(jù)填充 實(shí)現(xiàn)旋轉(zhuǎn)效果??runNum為旋轉(zhuǎn)的圈數(shù)?awardIndex為中獎(jiǎng)的序號(hào)

整體如此完美實(shí)現(xiàn)獻(xiàn)上整體代碼

html

<view class="wrapper-content" style='margin:0 auto;'>

? ? ? ? ? <view class="canvas-container-quiu" wx:for="{{list}}" style="-webkit-transform: rotate({{index * (360/list.length)}}deg);transform: rotate({{index * (360/list.length)}}deg);{{index%2==0?'background:#F2E86D':'background:#ffffff'}}"></view>

? ? ? ? ? <view class="canvas-container">

? ? ? ? ? ? <view animation="{{animationData}}" class="canvas-content" style='margin:0 auto;'>

? ? ? ? ? ? <canvas class="canvas-line" disable-scroll="true" bindtouchstart="canvasTouchStart" bindtouchmove="touchMove" bindtouchend="canvasTouchEnd" canvas-id="canvas"></canvas>

? ? ? ? ? ? </view>

? ? ? ? ? ? <view class="canvas-btn" bindtap="getLottery">

? ? ? ? ? ? ? <view>

? ? ? ? ? ? ? ? <view style="font-size:56rpx;color:#fff;padding-bottom:4rpx;">開始</view>

? ? ? ? ? ? ? ? <view style="font-size:20rpx;color:#6F5942;font-weight:600;">點(diǎn)擊抽獎(jiǎng)</view>

? ? ? ? ? ? ? </view>

? ? ? ? ? ? </view>

? ? ? ? ? </view>

? ? ? ? </view>

CSS

.wrapper-content{

? background: #E0CFBC;

? border-radius: 50%;

? width: 720rpx;

? height: 720rpx;

? padding: 40rpx;

? position: relative;

? box-sizing: border-box;

? z-index: 101;

}

.canvas-container ul, .canvas-container li {

? margin: 0;

? padding: 0;

? list-style: none;

}

.canvas-container {

? margin: 0 auto;

? position: absolute;

? left: 40rpx;

? top: 40rpx;

? width: 640rpx;

? height: 640rpx;

? border-radius: 50%;

}

.canvas-container-quiu{

? width: 20rpx;

? height: 20rpx;

? border-radius: 50%;

? position: absolute;

? left:10rpx;

? top: 50%;

? margin-top: -8rpx;

? -webkit-transform-origin: 330rpx 50%;

? transform-origin: 350rpx 50%;

? z-index: 1001;

}

.canvas-content {

? overflow: hidden;

? box-sizing: content-box;

? border: 20rpx solid #CDB193;

? position: absolute;

? left: 0;

? top: 0;

? z-index: 1;

? display: block;

? width: 600rpx;

? height: 600rpx;

? border-radius: inherit;

? background-clip: padding-box;

}

.canvas-btn {

? display: flex;

? flex-direction: column;

? justify-content: space-around;

? position: absolute;

? left: 50%;

? top: 50%;

? margin-left: -110rpx;

? margin-top: -110rpx;

? z-index: 400;

? width: 220rpx;

? height: 220rpx;

? border-radius: 50%;

? color: #f4e9cc;

? border: 10px solid #cdb193;

? text-align: center;

? font-size: 40rpx;

? text-decoration: none;

? box-sizing: border-box;

}

.canvas-btn>view {

? position: absolute;

? top: 7%;

? left: 7%;

? width: 86%;

? height: 86%;

? border-radius: 50%;

? box-sizing: border-box;

? padding: 22rpx 20rpx 0;

? background: linear-gradient(134deg, rgba(232, 219, 197, 1) 0%, rgba(205, 177, 147, 1) 100%);

? /* box-shadow:0px 5px 7px 0px rgba(255,255,255,1); */

? margin: auto;

? z-index: 102;

}

.canvas-btn::after {

? position: absolute;

? display: block;

? content: ' ';

? left: 39%;

? top: -78%;

? width: 0;

? height: 0;

? overflow: hidden;

? border-width: 80rpx 20rpx 80rpx 20rpx;

? border-style: solid;

? border-color: transparent;

? border-bottom-color: #ffab52;

}

js

var app = getApp()

var utils = require('../../utils/utils.js');

var Animation = require('../../utils/Animation.js');

var Wheel = require('../../utils/Wheel.js');

Page({

? /**

? * 頁(yè)面的初始數(shù)據(jù)

? */

? data: {

? ? awardsList: {},

? ? list: [],

? ? statusBarHeight: getApp().globalData.statusBarHeight,

? ? scrollHeight: 200,

? ? windowWidth:0,

? ? windowHeight:0,

? ? awardsConfig: {

? ? ? count: 50,

? ? ? slicePrizes: [

? ? ? ? { text: "恭喜中大獎(jiǎng)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "1200", x: "1" },

? ? ? ? { text: "醫(yī)療服務(wù)費(fèi)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "50", x: "2" },

? ? ? ? { text: "健康保養(yǎng)費(fèi)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "500", x: "1" },

? ? ? ? { text: "謝謝參與", img: "/assets/coupon_gold.png", title: "積分券x3", num: "0", x: "2" },

? ? ? ? { text: "青春補(bǔ)償費(fèi)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "200", x: "1" },

? ? ? ? { text: "感恩奉獻(xiàn)費(fèi)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "100", x: "2" },

? ? ? ? { text: "咨詢售后費(fèi)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "150", x: "1" },

? ? ? ? { text: "謝謝參與", img: "/assets/coupon_gold.png", title: "積分券x1", num: "0", x: "1" }, { text: "咨詢售后費(fèi)", img: "/assets/coupon_gold.png", title: "積分券x1", num: "150", x: "1" },

? ? ? ? { text: "謝謝參與", img: "/assets/coupon_gold.png", title: "積分券x1", num: "0", x: "1" }

? ? ? ],

? ? },

? },

? /**

? * 生命周期函數(shù)--監(jiān)聽頁(yè)面加載

? */

? onLoad: function(options) {

? ? var that = this;

? ? var that = this;

? ? wx.getSystemInfo({

? ? ? success: function (res) {

? ? ? ? that.setData({

? ? ? ? ? windowWidth: res.windowWidth,

? ? ? ? ? windowHeight: res.windowHeight,

? ? ? ? ? scrollHeight: res.windowHeight - res.windowWidth / 750 * (getApp().globalData.statusBarHeight * 2 + 98)

? ? ? ? });

? ? ? },

? ? })

? },

? onReady: function(e) {

? ? let that = this,

? ? ? fps = 60, awardsConfig = that.data.awardsConfig,

? ? ? ? w = this.data.windowWidth / 750 * 600,

? ? ? ? h = this.data.windowWidth / 750 * 600,

? ? ? ? context = wx.createCanvasContext('canvas'),

? ? ? ? //定義canvas位置

? ? ? ? wheel = new Wheel(w / 2, w / 2, (w / 2) - 0, awardsConfig.slicePrizes),

? ? ? ? animation = new Animation(wheel, { w: w, h: h });

? ? ? ? wheel.prizeWidth = 30;

? ? ? ? wheel.prizeHeight = 30;

? ? // 更新動(dòng)畫

? ? let update = function () {

? ? ? // 清空

? ? ? context.clearRect(0, 0, w, h);

? ? ? // 畫轉(zhuǎn)盤

? ? ? wheel.draw(context);

? ? ? // 更新數(shù)據(jù)

? ? ? animation.draw(context);

? ? ? // 更新數(shù)據(jù)

? ? ? animation.update();

? ? ? // 繪圖?

? ? ? context.draw()

? ? };

? ? setTimeout(update, 1000 / fps, 1000 / fps)

? ? wx.getSystemInfo({

? ? ? success: function(res) {

? ? ? ? that.setData({

? ? ? ? ? contentHeight: res.windowHeight

? ? ? ? });

? ? ? },

? ? })

? ? that.setData({

? ? ? count: awardsConfig.count

? ? })

? ? let len = awardsConfig.slicePrizes.length,

? ? ? ? rotateDeg = 360 / len / 2 ,

? ? ? ? list = [],

? ? ? ? turnNum = 1 / len;

? ? for (var i = 0; i < len; i++) {

? ? ? list.push({

? ? ? ? award: awardsConfig.slicePrizes[i].text,

? ? ? });

? ? };

? ? that.setData({

? ? ? list: list.concat(list)

? ? });

? },

? /**

? * 抽獎(jiǎng)處理函數(shù):

? */

? getLottery: function () {

? ? let that = this;

? ? // 獲取獎(jiǎng)品配置

? ? let awardsConfig = that.data.awardsConfig,

? ? ? ? runNum = 12, len = awardsConfig.slicePrizes.length,

? ? ? ? awardIndex = 0;

? ? awardIndex = parseInt(Math.random() * 6)

? ? console.log("獎(jiǎng)品序號(hào):" + awardIndex);

? ? // 旋轉(zhuǎn)抽獎(jiǎng)

? ? app.runDegs = app.runDegs || 0

? ? app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / len))

? ? //創(chuàng)建動(dòng)畫

? ? let animationRun = wx.createAnimation({

? ? ? duration: 4000,

? ? ? timingFunction: 'ease'

? ? })

? ? console.log(awardsConfig.slicePrizes[awardIndex]);

? ? that.animationRun = animationRun

? ? animationRun.rotate(app.runDegs - (360 / len * 2 + (360 / len)) ).step()

? ? that.setData({

? ? ? animationData: animationRun.export()

? ? })

? },

})

?

看完有問(wèn)題 可以評(píng)論? 覺(jué)得還可以的話點(diǎn)個(gè)贊? 謝謝? 相互交流

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容