項目需求運用到大轉盤 可設置概率 可直接自定義結果 效果如下?
?
兩種方法及結合法
一 通過canvas 實現 但是因為定時器原因 手機端卡頓嚴重 故而最終使用了方法二 但也是該記錄下 學習canvas
二 通過小程序Api?animation完成完美解決卡頓問題 更精確定位 有樣式缺陷 css無法解決樣式 自動分配問題 故結合一二兩種方法 出現第三種
三?通過小程序Api?animation 做動畫旋轉 樣式用canvas來實現 完美解決各類問題?
話不多說踩坑部分 就不展示 直接上第三種方法
創(chuàng)建動畫區(qū)域 (animation) 動畫可參考小程序官方API?animationData動畫參數 在點擊開始的時候填充數據
<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ū)域? 設置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;
? ? // 更新動畫
? ? let update = function () {
? ? ? // 清空
? ? ? context.clearRect(0, 0, w, h);
? ? ? // 畫轉盤
? ? ? wheel.draw(context);
? ? ? // 更新數據
? ? ? animation.draw(context);
? ? ? // 更新數據
? ? ? animation.update();
? ? ? // 繪圖?
? ? ? context.draw()
? ? };
? ? setTimeout(update, 1000 / fps, 1000 / fps)
}
1.awardsConfig.slicePrizes為獎品列表? 因為大轉盤是圓的 所以W H 是一樣的?
2.this.data.windowWidth 是屏幕的寬度 小程序有API 可以獲取? 600是設置的轉盤內容(canvas)的rpx寬度? 用屏幕寬度/750*設置內容寬度rpx = 實際內容寬度的px 值
3.wheel是canvas繪制轉盤的代碼 可自行修改參數
設置點擊抽獎按鈕 兩種方法 一直接在canvas內繪制? 二在HTML里面通過定位實現
提供二 HTML 定位實現按鈕
<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;">點擊抽獎</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;
? ? // 獲取獎品配置
? ? let awardsConfig = that.data.awardsConfig,
? ? ? ? runNum = 12, len = awardsConfig.slicePrizes.length,
? ? ? ? awardIndex = 0;
? ? awardIndex = parseInt(Math.random() * 6)
? ? console.log("獎品序號:" + awardIndex);
? ? // 旋轉抽獎
? ? app.runDegs = app.runDegs || 0
? ? app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / len))
? ? //創(chuà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()
? ? })
? },
點擊按鈕觸發(fā)getLottery 進行動畫數據填充 實現旋轉效果??runNum為旋轉的圈數?awardIndex為中獎的序號
整體如此完美實現獻上整體代碼
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;">點擊抽獎</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({
? /**
? * 頁面的初始數據
? */
? data: {
? ? awardsList: {},
? ? list: [],
? ? statusBarHeight: getApp().globalData.statusBarHeight,
? ? scrollHeight: 200,
? ? windowWidth:0,
? ? windowHeight:0,
? ? awardsConfig: {
? ? ? count: 50,
? ? ? slicePrizes: [
? ? ? ? { text: "恭喜中大獎", img: "/assets/coupon_gold.png", title: "積分券x1", num: "1200", x: "1" },
? ? ? ? { text: "醫(yī)療服務費", img: "/assets/coupon_gold.png", title: "積分券x1", num: "50", x: "2" },
? ? ? ? { text: "健康保養(yǎng)費", img: "/assets/coupon_gold.png", title: "積分券x1", num: "500", x: "1" },
? ? ? ? { text: "謝謝參與", img: "/assets/coupon_gold.png", title: "積分券x3", num: "0", x: "2" },
? ? ? ? { text: "青春補償費", img: "/assets/coupon_gold.png", title: "積分券x1", num: "200", x: "1" },
? ? ? ? { text: "感恩奉獻費", img: "/assets/coupon_gold.png", title: "積分券x1", num: "100", x: "2" },
? ? ? ? { text: "咨詢售后費", img: "/assets/coupon_gold.png", title: "積分券x1", num: "150", x: "1" },
? ? ? ? { text: "謝謝參與", img: "/assets/coupon_gold.png", title: "積分券x1", num: "0", x: "1" }, { text: "咨詢售后費", img: "/assets/coupon_gold.png", title: "積分券x1", num: "150", x: "1" },
? ? ? ? { text: "謝謝參與", img: "/assets/coupon_gold.png", title: "積分券x1", num: "0", x: "1" }
? ? ? ],
? ? },
? },
? /**
? * 生命周期函數--監(jiān)聽頁面加載
? */
? 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;
? ? // 更新動畫
? ? let update = function () {
? ? ? // 清空
? ? ? context.clearRect(0, 0, w, h);
? ? ? // 畫轉盤
? ? ? wheel.draw(context);
? ? ? // 更新數據
? ? ? animation.draw(context);
? ? ? // 更新數據
? ? ? 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)
? ? });
? },
? /**
? * 抽獎處理函數:
? */
? getLottery: function () {
? ? let that = this;
? ? // 獲取獎品配置
? ? let awardsConfig = that.data.awardsConfig,
? ? ? ? runNum = 12, len = awardsConfig.slicePrizes.length,
? ? ? ? awardIndex = 0;
? ? awardIndex = parseInt(Math.random() * 6)
? ? console.log("獎品序號:" + awardIndex);
? ? // 旋轉抽獎
? ? app.runDegs = app.runDegs || 0
? ? app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / len))
? ? //創(chuà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()
? ? })
? },
})
?
看完有問題 可以評論? 覺得還可以的話點個贊? 謝謝? 相互交流