HaniBlindBox/honey_box/pages/shouye/canvas-prize-demo.vue
2026-01-01 21:01:55 +08:00

223 lines
5.9 KiB
Vue

<template>
<page-container title="Canvas抽奖特效演示" :showBack="true">
<view class="demo-container">
<view class="prize-wheel-wrapper">
<canvas-prize-wheel
ref="canvasPrizeWheel"
:prizes="prizes"
:duration="4"
:itemWidth="itemWidth"
:itemHeight="itemHeight"
:backgroundColor="'rgba(255, 255, 255, 0.9)'"
:highlightColor="'rgba(255, 215, 0, 0.5)'"
:highlightShadow="'rgba(255, 215, 0, 0.8)'"
:borderRadius="8"
@spin-start="onSpinStart"
@spin-end="onSpinEnd">
</canvas-prize-wheel>
</view>
<view class="control-panel">
<button class="start-btn" @click="startLottery" :disabled="isSpinning">开始抽奖</button>
<view class="result-display" v-if="prizeResult">
<text class="result-label">抽奖结果:</text>
<text class="result-value" :style="{ color: prizeResult.color }">{{prizeResult.value}}</text>
</view>
</view>
</view>
</page-container>
</template>
<script>
import CanvasPrizeWheel from '@/components/canvas-prize-wheel/canvas-prize-wheel.vue'
export default {
components: {
CanvasPrizeWheel
},
data() {
return {
// 奖品列表 - 使用简短名称更好显示
prizes: [
{ id: 1, value: '一等奖', color: '#ff0000', bgColor: 'rgba(255,0,0,0.1)' },
{ id: 2, value: '二等奖', color: '#00ff00', bgColor: 'rgba(0,255,0,0.1)' },
{ id: 3, value: '三等奖', color: '#0000ff', bgColor: 'rgba(0,0,255,0.1)' },
{ id: 4, value: '四等奖', color: '#ffff00', bgColor: 'rgba(255,255,0,0.1)' },
{ id: 5, value: '五等奖', color: '#ff00ff', bgColor: 'rgba(255,0,255,0.1)' },
{ id: 6, value: '六等奖', color: '#00ffff', bgColor: 'rgba(0,255,255,0.1)' },
{ id: 7, value: '谢谢', color: '#ff8800', bgColor: 'rgba(255,136,0,0.1)' }
],
isSpinning: false,
prizeResult: null,
itemWidth: uni.upx2px(150),
itemHeight: uni.upx2px(120)
}
},
mounted() {
// 确保界面加载后Canvas正确初始化
this.$nextTick(() => {
setTimeout(() => {
if (this.$refs.canvasPrizeWheel) {
this.$refs.canvasPrizeWheel.render()
}
}, 500)
})
},
methods: {
// 开始抽奖
startLottery() {
if (this.isSpinning) return
this.isSpinning = true
this.prizeResult = null
// 启动抽奖动画
this.$refs.canvasPrizeWheel.startSpin()
// 模拟异步获取抽奖结果
// 实际应用中应该调用后端API获取结果
setTimeout(() => {
// 随机选择一个奖品
const randomIndex = Math.floor(Math.random() * this.prizes.length)
const result = this.prizes[randomIndex]
// 设置最终奖品并开始减速
this.$refs.canvasPrizeWheel.setPrize(result)
}, 2000) // 2秒后获取结果
},
// 抽奖开始回调
onSpinStart() {
console.log('抽奖开始')
// 播放背景音乐或其他操作
uni.showToast({
title: '抽奖开始',
icon: 'none'
})
},
// 抽奖结束回调
onSpinEnd(prize) {
console.log('抽奖结束', prize)
this.isSpinning = false
this.prizeResult = prize
// 显示结果
uni.showToast({
title: `恭喜获得: ${prize.value}`,
icon: 'success',
duration: 2000
})
// 可以在这里添加截图分享功能
// this.saveAndShareResult()
},
// 保存并分享抽奖结果
async saveAndShareResult() {
try {
// 导出Canvas为图片
const imagePath = await this.$refs.canvasPrizeWheel.exportImage()
// 保存图片到相册
uni.saveImageToPhotosAlbum({
filePath: imagePath,
success: () => {
uni.showToast({
title: '已保存到相册',
icon: 'success'
})
},
fail: (err) => {
console.error('保存图片失败', err)
}
})
} catch (error) {
console.error('导出图片失败', error)
}
}
}
}
</script>
<style lang="scss">
.demo-container {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
background-image: url($imgurl + 'common/slot_bg.webp');
background-size: cover;
background-position: center;
.prize-wheel-wrapper {
width: 100%;
padding: 0;
height: 120rpx;
background-image: url($imgurl + 'common/slot1.png');
background-size: cover;
background-position: center;
position: relative;
margin: 40rpx 0;
display: flex;
align-items: center;
justify-content: center;
}
.control-panel {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
padding: 20rpx;
.start-btn {
width: 300rpx;
height: 90rpx;
background: linear-gradient(to right, #ff5a5f, #ff8a5f);
color: white;
border-radius: 45rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 32rpx;
margin-bottom: 30rpx;
box-shadow: 0 4rpx 10rpx rgba(255, 90, 95, 0.3);
&:active {
transform: scale(0.98);
}
&[disabled] {
background: #cccccc;
color: #888888;
}
}
.result-display {
margin-top: 20rpx;
background-color: rgba(255, 255, 255, 0.8);
padding: 20rpx 40rpx;
border-radius: 10rpx;
display: flex;
flex-direction: column;
align-items: center;
.result-label {
font-size: 28rpx;
color: #666;
margin-bottom: 10rpx;
}
.result-value {
font-size: 40rpx;
font-weight: bold;
}
}
}
}
</style>