07_微信小程式之大轉盤自定義組件撰寫
一.界面布局
通過傳入的size控制圓盤大小
<!--components/turntable/index.wxml-->
<view class="turntable" style="width:{{size}}rpx; height:{{size}}rpx;">
<image class="outer" src="../../images/outer.png"></image>
<canvas class="canvas" type="2d" id="canvas"></canvas>
<image class="start" src="../../images/start.png"></image>
</view>
/* components/turntable/index.wxss */
.turntable {
position: relative;
margin-left: 50%;
transform: translateX(-50%);
}
.outer {
width: 100%;
height: 100%;
}
.canvas {
position: absolute;
left: 40rpx;
top: 40rpx;
width: calc(100% - 80rpx);
height: calc(100% - 80rpx);
}
.start {
position: absolute;
width: 112rpx;
height: 124rpx;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 99;
}
// components/turntable/index.js
Component({
/**
* 組件的屬性串列
*/
properties: {
size: {
type: Number,
value: 600,
observer: function(newVal, oldVal) {
this.setData({
size: newVal
})
}
}
},
/**
* 組件的初始資料
*/
data: {
},
/**
* 組件的方法串列
*/
methods: {
}
})

二.根據獎品個數繪制扇形組成圓盤
// components/turntable/index.js
Component({
/**
* 組件的屬性串列
*/
properties: {
size: {
type: Number,
value: 600,
observer: function(newVal, oldVal) {
this.setData({
size: newVal
})
}
},
prizeList: {
type: Array,
value: [],
observer: function(newVal, oldVal) {
this.setData({
prizeList: newVal
})
this.initTurntable()
}
}
},
/**
* 組件的初始資料
*/
data: {
},
/**
* 組件的方法串列
*/
methods: {
initTurntable: function() {
var that = this
const query = that.createSelectorQuery()
query.select('#canvas')
.fields({ node: true, size: true })
.exec((res) => {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
//圓心坐標
var centerX = (res[0].width/2)
var centerY = (res[0].height/2)
//半徑
var radius = (res[0].width/2)
//獎品數量
var num = that.data.prizeList.length
// 扇形旋轉轉角度
var rotateDeg = 360 / num / 2 + 90
//繪制扇形
for(var i = 0; i < num; i++) {
// 保存當前狀態
ctx.save();
// 開始一條新路徑
ctx.beginPath();
// 位移到圓心,下面需要圍繞圓心旋轉
ctx.translate(centerX, centerY);
// 從(0, 0)坐標開始定義一條新的子路徑
ctx.moveTo(0, 0);
// 旋轉弧度,需將角度轉換為弧度,使用 degrees * Math.PI/180 公式進行計算,
ctx.rotate((360 / num * i - rotateDeg) * Math.PI / 180);
// 繪制圓弧
ctx.arc(0, 0, radius, 0, 2 * Math.PI / num, false);
var k = i%3
var colors = ['#D7D7D7', '#FEF43E', '#EF7683']
var color = colors[k]
ctx.fillStyle = color
// 填充扇形
ctx.fill();
// 繪制邊框
ctx.lineWidth = 0.5;
ctx.strokeStyle = '#e4370e';
ctx.stroke();
// 恢復前一個狀態
ctx.restore();
}
})
}
}
})
坑坑坑,由于canvas2d在模擬器上的兼容性不是很理想,按理說canvas以2d模式渲染時,開始按鈕應該會覆寫在畫布上顯示,但是如下圖所示,并沒有:

那么再用真機試試看:


可以看到在ios是正常的,但是在android端卻還是不顯示開始按鈕,這就尷尬了,而且本人親測,前面幾天在android端canvas2d的渲染一切正常,于是乎開始檢查代碼,最侄訓是沒發現什么問題🐶
最后發現微信小程式的sdk 2.14.0 版本顯示灰度中,正好本人手機上小程式的sdk版本是2.14.0,于是大膽猜想應該是這個原因了,當然,這種情況可以等待微信的灰度完成后,在看下正常與否

這個問題其實我們不必擔心,因為我們只需要把畫布畫出的圓盤轉換成圖片,作為背景顯示在view標簽上,這里的畫布只是用來繪制圓盤,并不用于顯示,所以需要將畫布移出顯示范圍
三.將圓盤轉為base64并顯示
<!--components/turntable/index.wxml-->
<view class="turntable" style="width:{{size}}rpx; height:{{size}}rpx;">
<image class="outer" src="./images/outer.png"></image>
<canvas class="canvas" type="2d" id="canvas"></canvas>
<view class="secs" style="background-size: cover; background-image: url({{secs}});"></view>
<image class="start" src="./images/start.png"></image>
</view>
/* components/turntable/index.wxss */
.turntable {
position: relative;
margin-left: 50%;
transform: translateX(-50%);
}
.outer {
width: 100%;
height: 100%;
}
.canvas {
position: fixed;
left: 40rpx;
top: -10000px;
width: calc(100% - 80rpx);
height: calc(100% - 80rpx);
}
.secs {
position: absolute;
left: 40rpx;
top: 40rpx;
width: calc(100% - 80rpx);
height: calc(100% - 80rpx);
}
.start {
position: absolute;
width: 112rpx;
height: 124rpx;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 99;
}
// components/turntable/index.js
Component({
/**
* 組件的屬性串列
*/
properties: {
size: {
type: Number,
value: 600,
observer: function(newVal, oldVal) {
this.setData({
size: newVal
})
}
},
prizeList: {
type: Array,
value: [],
observer: function(newVal, oldVal) {
this.setData({
prizeList: newVal
})
this.initTurntable()
}
}
},
/**
* 組件的初始資料
*/
data: {
},
/**
* 組件的方法串列
*/
methods: {
initTurntable: function() {
var that = this
const query = that.createSelectorQuery()
query.select('#canvas')
.fields({ node: true, size: true })
.exec((res) => {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
//圓心坐標
var centerX = (res[0].width/2)
var centerY = (res[0].height/2)
//半徑
var radius = (res[0].width/2)
//獎品數量
var num = that.data.prizeList.length
// 扇形旋轉轉角度
var rotateDeg = 360 / num / 2 + 90
//繪制扇形
for(var i = 0; i < num; i++) {
// 保存當前狀態
ctx.save();
// 開始一條新路徑
ctx.beginPath();
// 位移到圓心,下面需要圍繞圓心旋轉
ctx.translate(centerX, centerY);
// 從(0, 0)坐標開始定義一條新的子路徑
ctx.moveTo(0, 0);
// 旋轉弧度,需將角度轉換為弧度,使用 degrees * Math.PI/180 公式進行計算,
ctx.rotate((360 / num * i - rotateDeg) * Math.PI / 180);
// 繪制圓弧
ctx.arc(0, 0, radius, 0, 2 * Math.PI / num, false);
var k = i%3
var colors = ['#D7D7D7', '#FEF43E', '#EF7683']
var color = colors[k]
ctx.fillStyle = color
// 填充扇形
ctx.fill();
// 繪制邊框
ctx.lineWidth = 0.5;
ctx.strokeStyle = '#e4370e';
ctx.stroke();
// 恢復前一個狀態
ctx.restore();
}
//轉換畫布內容為base64圖片
var dataURL=canvas.toDataURL('image/png', 1);
that.setData({
secs: dataURL
})
})
}
}
})

到此,大轉盤的樣子算是出來了,接下來我們讓它轉起來吧
四.控制轉盤旋轉
<!--components/turntable/index.wxml-->
<view class="turntable" style="width:{{size}}rpx; height:{{size}}rpx;">
<image class="outer" src="./images/outer.png"></image>
<canvas class="canvas" type="2d" id="canvas"></canvas>
<view class="secs" style="background-size: cover; background-image: url({{secs}}); transform: {{transform}}" bindtransitionend="transitionEnd"></view>
<image class="start" src="./images/start.png" bindtap="start"></image>
</view>
// components/turntable/index.js
Component({
/**
* 組件的屬性串列
*/
properties: {
size: {
type: Number,
value: 600,
observer: function(newVal, oldVal) {
this.setData({
size: newVal
})
}
},
prizeList: {
type: Array,
value: [],
observer: function(newVal, oldVal) {
this.setData({
prizeList: newVal
})
this.initTurntable()
}
}
},
/**
* 組件的初始資料
*/
data: {
transform: ""
},
/**
* 組件的方法串列
*/
methods: {
initTurntable: function() {
var that = this
const query = that.createSelectorQuery()
query.select('#canvas')
.fields({ node: true, size: true })
.exec((res) => {
console.log(res)
const canvas = res[0].node
const ctx = canvas.getContext('2d')
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.scale(dpr, dpr)
//圓心坐標
var centerX = (res[0].width/2)
var centerY = (res[0].height/2)
//半徑
var radius = (res[0].width/2)
//獎品數量
var num = that.data.prizeList.length
// 扇形旋轉轉角度
var rotateDeg = 360 / num / 2 + 90
//繪制扇形
for(var i = 0; i < num; i++) {
// 保存當前狀態
ctx.save();
// 開始一條新路徑
ctx.beginPath();
// 位移到圓心,下面需要圍繞圓心旋轉
ctx.translate(centerX, centerY);
// 從(0, 0)坐標開始定義一條新的子路徑
ctx.moveTo(0, 0);
// 旋轉弧度,需將角度轉換為弧度,使用 degrees * Math.PI/180 公式進行計算,
ctx.rotate((360 / num * i - rotateDeg) * Math.PI / 180);
// 繪制圓弧
ctx.arc(0, 0, radius, 0, 2 * Math.PI / num, false);
var k = i%3
var colors = ['#D7D7D7', '#FEF43E', '#EF7683']
var color = colors[k]
ctx.fillStyle = color
// 填充扇形
ctx.fill();
// 繪制邊框
ctx.lineWidth = 0.5;
ctx.strokeStyle = '#e4370e';
ctx.stroke();
// 恢復前一個狀態
ctx.restore();
}
//轉換畫布內容為base64圖片
var dataURL=canvas.toDataURL('image/png', 1);
that.setData({
secs: dataURL
})
})
},
start: function(event) {
this.goto(0)
},
goto: function(index) {
var isTurning = this.data.isTurning
if(isTurning) {
return
}
this.setData({
transform: "rotate(" + 0 + "deg); transition: transform 5s ease-in-out"
})
this.setData({
isTurning: true
})
this.setData({
runRotate:0
})
var prizeNum = this.data.prizeList.length
var rotate = 360/prizeNum * (prizeNum-index)
var sRotate = 360*10+rotate
this.setData({
transform: "rotate(" + sRotate + "deg); transition: transform 5s ease-in-out"
})
},
transitionEnd: function(event) {
//這里轉盤停止直接就重置轉盤了,實際應該是先彈窗提示用戶中獎與否,在用戶關閉彈窗時,再重置轉盤
var that = this
setTimeout(function() {
that.setData({
transform: "",
isTurning: false
})
}, 3000)
}
}
})

錄屏效果不是很好😂
五.擺放獎品
<!--components/turntable/index.wxml-->
<view class="turntable" style="width:{{size}}rpx; height:{{size}}rpx;">
<image class="outer" src="./images/outer.png"></image>
<canvas class="canvas" type="2d" id="canvas"></canvas>
<view class="secs" style="background-size: cover; background-image: url({{secs}}); transform: {{transform}}" bindtransitionend="transitionEnd">
<view class="sec" wx:for="{{prizeList}}" style="transform:rotate({{index*360/prizeList.length}}deg);transform-origin: {{centerX}}px {{centerY}}px;">
<view class="prize-name">大禮包</view>
<image class="prize-image" src="./images/gift.png"></image>
</view>
</view>
<image class="start" src="./images/start.png" bindtap="start"></image>
</view>
/* components/turntable/index.wxss */
.turntable {
position: relative;
margin-left: 50%;
transform: translateX(-50%);
}
.outer {
width: 100%;
height: 100%;
}
.canvas {
position: fixed;
left: 40rpx;
top: -10000px;
width: calc(100% - 80rpx);
height: calc(100% - 80rpx);
}
.secs {
position: absolute;
left: 40rpx;
top: 40rpx;
width: calc(100% - 80rpx);
height: calc(100% - 80rpx);
}
.start {
position: absolute;
width: 112rpx;
height: 124rpx;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
z-index: 99;
}
.sec {
position: absolute;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding-top: 10%;
}
.prize-name {
font-size: 28rpx;
color: 666;
}
.prize-image {
width: 50rpx;
height: 50rpx;
margin-top: 8rpx;
}

完
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/226889.html
標籤:其他
