效果圖
wxml
<view class="turntable">
<canvas type="2d" style="transform:{{'rotate(' + rotate + 'deg)'}};width: 600rpx;height: 600rpx" class="turntableCanvas" id='turntable'></canvas>
<image bindtap="start" class="zhizhen" src="../../img/zhizhen.png"></image>
</view>
wxss
.turntable{
position:relative;
}
.turntableCanvas{
margin:0 auto;
transform-origin:50% 50%;
}
.zhizhen{
position:absolute;
z-index:2;
top:0;
left:0;
bottom:0;
right:0;
margin:auto;
width:162rpx;
height:207rpx;
}
js
// pages/index2/index.js
Page({
/**
* 頁面的初始數據
*/
data: {
canvasWidth:600,
canvasHeight:600,
rotate:0,
prizeList:[
{
text:'獎品一',
imgurl:'../../img/koushuidou.png'
},
{
text: '獎品二',
imgurl: '../../img/maozi.png'
},
{
text: '獎品一一',
imgurl: '../../img/naiping.png'
},
{
text: '獎品',
imgurl: '../../img/shuibei.png'
},
{
text: '獎',
imgurl: '../../img/xiaohuangya.png'
},
{
text: '獎123',
imgurl: '../../img/yingerche.png'
},
]
},
onLoad(){
let that = this;
wx.getSystemInfo({
success(res) {
//圓邊背景色
that.colorBj = "red"
//圓邊寬度
that.outsideWidth = 20;
//小燈個數 建議 lightNum % 2 == 0 && 360 % lightNum == 0
that.lightNum = 12;
//小燈半徑 必須小於圓邊寬度的一半
that.lightWidth = 4;
//小燈顏色(一個正常,一個高亮,初始都正常)
that.lightBgType = ['#fff', '#f5c058'];
that.lightBg = [];
for (var i = 0; i < that.lightNum; i++) {
that.lightBg.push(that.lightBgType[0]);
}
//獎品個數
that.prizeNum = that.data.prizeList.length;
//扇形顏色
that.sectorBjOne = "#ffe8b5";
that.sectorBjTwo = "#ffb933";
//文字顏色
that.textColor = "#5c1e08";
//文字大小及字體
that.textStyle = "16px Georgia";
//文字距離圓邊的距離
that.textTop = 14;
//圖片距離圓邊的距離
that.imgTop = 40;
//圖片寬度(建議按圖片實際寬高縮放)
that.imgWidth = 32;
that.imgHeight = 32;
//旋轉結束值(start函數中已默認配置)
that.rotateEnd = 0;
//偏差角(無需更改)
that.deviation = 0;
for (var i = 0; i < that.prizeNum;) {
if (i * 360 / that.prizeNum > 270) {
that.deviation = i * 360 / that.prizeNum - 270;
break;
} else {
i++;
}
}
//使轉盤初始是正直向上的(可註釋)
that.setData({
rotate: that.data.rotate - that.deviation + 180 / that.prizeNum
})
that.canvas();
}
})
},
canvas() {
const query = wx.createSelectorQuery();
query.select('#turntable')
.fields({ node: true, size: true })
.exec((res) => {
var canvas = res[0].node;
var dpr = wx.getSystemInfoSync().windowWidth / 750;
canvas.width = this.data.canvasWidth * dpr;
canvas.height = this.data.canvasHeight * dpr;
this.canvasWidth = this.data.canvasWidth * dpr;
this.canvasHeight = this.data.canvasHeight * dpr;
var canvasContext = canvas.getContext('2d')
canvasContext.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
//繪製圓邊背景
canvasContext.beginPath();
canvasContext.fillStyle = this.colorBj;
canvasContext.arc(this.canvasWidth / 2, this.canvasHeight / 2, this.canvasWidth / 2, 0, 2 * Math.PI);
canvasContext.fill();
canvasContext.closePath();
//繪製周邊小燈
for (var i = 0; i < this.lightNum; i++) {
canvasContext.beginPath();
canvasContext.fillStyle = this.lightBg[i];
canvasContext.arc(this.canvasWidth / 2 + (this.canvasWidth / 2 - this.outsideWidth / 2) * Math.cos(360 / this.lightNum * i * Math.PI / 180), this.canvasHeight / 2 + (this.canvasHeight / 2 - this.outsideWidth / 2) * Math.sin(360 / this.lightNum * i * Math.PI / 180), this.lightWidth, 0, 2 * Math.PI);
canvasContext.fill();
canvasContext.closePath();
}
//獎品扇形
for (var i = 0; i < this.prizeNum; i++){
canvasContext.beginPath();
canvasContext.moveTo(this.canvasWidth / 2, this.canvasHeight / 2);
canvasContext.lineTo(this.canvasWidth / 2 + (this.canvasWidth / 2 - this.outsideWidth) * Math.cos(360 / this.prizeNum * i * Math.PI / 180), this.canvasHeight / 2 + (this.canvasHeight / 2 - this.outsideWidth) * Math.sin(360 / this.prizeNum * i * Math.PI / 180));
canvasContext.arc(this.canvasWidth / 2, this.canvasHeight / 2, this.canvasWidth / 2 - this.outsideWidth, 360 / this.prizeNum * Math.PI / 180 * i, 360 / this.prizeNum * Math.PI / 180 * (i + 1));
canvasContext.moveTo(this.canvasWidth / 2, this.canvasHeight / 2);
canvasContext.lineTo(this.canvasWidth / 2 + (this.canvasWidth / 2 - this.outsideWidth) * Math.cos(360 / this.prizeNum * (i + 1) * Math.PI / 180), this.canvasHeight / 2 + (this.canvasHeight / 2 - this.outsideWidth) * Math.sin(360 / this.prizeNum * (i + 1) * Math.PI / 180));
if (i % 2 == 0) {
canvasContext.fillStyle = this.sectorBjOne;
} else {
canvasContext.fillStyle = this.sectorBjTwo;
}
canvasContext.fill();
canvasContext.closePath();
}
//繪製文字與圖片
let img = [];
for (let i = 0; i < this.prizeNum; i++) {
img[i] = canvas.createImage();
img[i].src = this.data.prizeList[i].imgurl;
img[i].onload = () => {
canvasContext.save();
canvasContext.beginPath();
canvasContext.translate(this.canvasWidth / 2, this.canvasHeight / 2);
canvasContext.rotate((this.deviation - 360 / (this.prizeNum * 2) * (i * 2 + 1)) * Math.PI / 180);
canvasContext.translate(-this.canvasWidth / 2, -this.canvasHeight / 2);
canvasContext.fillStyle = this.textColor;
canvasContext.font = this.textStyle;
canvasContext.textAlign = 'center';
canvasContext.textBaseline = 'top';
canvasContext.fillText(this.data.prizeList[i].text, this.canvasWidth / 2, this.outsideWidth + this.textTop);
canvasContext.drawImage(img[i], this.canvasWidth / 2 - this.imgWidth / 2, this.outsideWidth + this.imgTop, this.imgWidth, this.imgHeight)
canvasContext.closePath();
canvasContext.restore();
}
}
})
},
start() {
//逆時針
// this.rotateEnd = this.rotateEnd+ -360 * 3 + -this.rand(0, 360);
// Math.floor
this.timerApi = setInterval(()=>{
//下面的初始速度speed大約60,所以此處+60
this.setData({
rotate: this.data.rotate + 60
})
},100)
console.log('請求中...')
setTimeout(() => {
console.log('請求成功...')
clearInterval(this.timerApi);
this.setData({
rotate: 0
})
//請求接口返回獲得了哪個獎,現在是下標爲1的獎
var i = 1;
this.rotateEnd = 360 * 3 + this.rand(360 / this.prizeNum * i + 1, 360 / this.prizeNum * (i + 1) - 1) - this.deviation;
let speed = Math.ceil(((this.rotateEnd - this.data.rotate) / 20));
// console.log(this.rotateEnd, speed);
this.timerInterval = setInterval(() => {
speed = Math.ceil(((this.rotateEnd - this.data.rotate) / 20));
// console.log(this.data.rotate, speed)
if (this.data.rotate + speed >= this.rotateEnd) {
this.setData({
rotate: this.rotateEnd % 360
})
this.rotateEnd = this.rotateEnd % 360;
let prize = (Math.floor((Math.abs(this.data.rotate) + this.deviation) / (360 / this.prizeNum)));
if (prize == this.prizeNum) {
prize = 0;
}
console.log(this.data.prizeList[prize]);
clearInterval(this.timerInterval);
// clearTimeout(this.timerTimeout);
} else {
this.setData({
rotate: this.data.rotate + speed
})
}
}, 100)
//取消重繪(取消效果:周邊燈閃爍;原因:小程序性能差,重繪太慢;解決方法:單獨爲周邊燈繪製一個canvas,此處不予解決)
// this.timerTimeout = setInterval(() => {
// this.lightBg = [];
// for (var i = 0; i < this.lightNum; i++) {
// if (this.rand(0, 9) < 2) {
// this.lightBg.push(this.lightBgType[1]);
// } else {
// this.lightBg.push(this.lightBgType[0]);
// }
// }
// console.log(this.lightBg);
// this.canvas();
// }, 2000)
}, 1000)
},
rand(n, m){
var c = m - n + 1;
return Math.floor(Math.random() * c + n);
}
})
tips:版本庫不要太低,要支持同層渲染,同時編輯器內可能存在問題,請用真機測試
小程序片段:點擊跳轉
github地址:點擊跳轉
npm下載: npm i wx-turntable-canvas
博客個人博客地址:點擊跳轉