123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397 |
- <template>
- <uni-popup ref="turntablePopup" type="center" :is-mask-click="false">
- <view class="turntable">
- <image class="bg" src="https://cos.his.cdwjyyh.com/fs/20250910/9a6263291ec0429ea5828a15b2b490dc.png" mode="aspectFit"></image>
- <view class="turntable-con">
- <image class="text" src="https://cos.his.cdwjyyh.com/fs/20250910/fc08b64307a344b4948568fa0f81401e.png" mode="heightFix"></image>
- <image class="base" src="https://cos.his.cdwjyyh.com/fs/20250910/9385e4a6d5e245dfb86f425f49235589.png" mode="aspectFit"></image>
- <image class="decoration_img" src="https://cos.his.cdwjyyh.com/fs/20250910/86577ed4fc50420d99b1153e2dd6e1df.png" mode="aspectFit"></image>
- <view class="ring">
- <view class="canvas-content" :class="{'infinite-spin': spinning}">
- <view :animation="animationData" class="canvas-content" id="zhuanpano" style="">
- <view class="canvas-line">
- <!-- <canvas canvas-id="sector" style="width:502rpx;height:502rpx" /> -->
- <view class="canvas-litem" v-for="(item,index) in list" :key="index"
- :style="{transform:'rotate('+(index * width + width / 2)+'deg)'}"></view>
- </view>
- <view class="canvas-list">
- <view class="canvas-item"
- :style="{transform: 'rotate('+((index) * width)+'deg)', zIndex:index}"
- v-for="(iteml,index) in list" :key="index">
- <view class="canvas-item-text" :style="'transform:rotate('+(index)+')'">
- <view class="b">{{iteml.name}}</view>
- <image class="icon-awrad iconfont" :src="iteml.iconUrl" mode="aspectFit">
- </image>
- </view>
- </view>
- </view>
- </view>
- </view>
- <image class="button" src="https://cos.his.cdwjyyh.com/fs/20250910/d05462c59e7f4ab98e5205b7f8172325.png" mode="aspectFit" @click="playReward">
- </image>
- </view>
- <image class="ring_bg" src="https://cos.his.cdwjyyh.com/fs/20250910/41bea8eda62e484d94a19f18316e509b.png" mode="aspectFit"></image>
- </view>
- </view>
- <image class="close" src="https://cos.his.cdwjyyh.com/fs/20250910/93608bad8ad1479a854ec26e8eaaacea.png" @click="close"></image>
- </uni-popup>
- </template>
- <script>
- import {
- getVideoRewardRules
- } from "@/api/course.js"
- export default {
- data() {
- return {
- running: false,
- spinning: false, // 是否处于无限旋转
- list: [],
- width: 0,
- animationData: {},
- btnDisabled: '',
- runDeg: 0,
- targetIdx: -1,
- duration: 1000,
- currentDeg: 0, // 实时角度
- idleTimer: null,
- animationRun: null
- }
- },
- methods: {
- getVideoRewardRules(urlOption) {
- const param = {
- type: 3,
- ...urlOption
- }
- getVideoRewardRules(param).then(res => {
- if (res.code == 200) {
- this.list = res.data || []
- this.width = 360 / this.list.length;
- } else {
- uni.showToast({
- title: res.msg,
- icon: 'none'
- })
- }
- })
- },
- open(urlOption) {
- this.animationRun = uni.createAnimation({
- duration: 0
- });
- this.animationRun.rotate(0).step();
- this.animationData = this.animationRun.export();
- this.running = false
- this.spinning = false;
- clearInterval(this.idleTimer);
- this.runDeg = 0
- this.targetIdx = -1
- this.$refs.turntablePopup.open()
- this.getVideoRewardRules(urlOption)
- },
- close(type) {
- if (type == 'close') {
- this.running = false
- this.spinning = false;
- clearInterval(this.idleTimer);
- }
- if (this.running) {
- uni.showToast({
- title: '抽取中,请勿关闭',
- icon: 'none'
- })
- return
- }
- this.$refs.turntablePopup.close()
- },
- drawFanWithAlternateColor(id, x, y, r, count) {
- const ctx = uni.createCanvasContext(id, this);
- const sweep = 360 / count; // 每份角度
- let start = -90 - sweep / 2; // 第一个扇形起始角度(deg)
- for (let i = 0; i < count; i++) {
- const end = start + sweep; // 结束角度
- let color;
- color = i % 2 === 0 ? '#FFDFD3' : '#FFF';
- ctx.beginPath();
- ctx.moveTo(x, y);
- ctx.arc(
- x, y, r,
- (start * Math.PI) / 180,
- (end * Math.PI) / 180
- );
- ctx.closePath();
- ctx.setFillStyle(color);
- ctx.fill();
- start = end; // 下一个扇形接着画
- }
- ctx.draw();
- },
- animation(index = null) {
- //中奖index
- let list = this.list;
- let runNum = 1; //旋转8周
- // 旋转角度
- this.runDeg = this.runDeg || 0;
- this.runDeg = this.runDeg + (360 - this.runDeg % 360) + (360 * runNum - index * (360 / list.length)) + 1
-
- // const a = 360 / list.length;
- // this.runDeg = this.currentDeg + 360 * 4 + (360 - this.currentDeg % 360) - index * a + 1;
- //创建动画
- this.animationRun = uni.createAnimation({
- duration: this.duration,
- timingFunction: 'ease'
- })
- console.log("=====animationRun=", this.animationRun)
- this.animationRun.rotate(this.runDeg).step();
- this.animationData = this.animationRun.export();
- },
- //发起抽奖
- playReward() {
- if (this.running) {
- uni.showToast({
- title: '抽取中',
- icon: 'none'
- })
- return
- }
- this.running = true
- this.startIdle();
- this.$emit('sendRewardFun',3)
- // setTimeout(() => {
- // this.endSuccess()
- // }, 2000)
- },
- startIdle() {
- this.spinning = true; // 打开 CSS 动画
- // 同时用定时器记录角度,方便后面衔接
- this.idleTimer = setInterval(() => {
- this.runDeg = (this.runDeg + 36) % 360; // 每 100ms 走 6°
- }, 100);
- },
- endSuccess(code) {
- // this.targetIdx = this.list.findIndex(it=>it.code == code)
- this.targetIdx = 4
- const that = this
- this.spinning = false;
- clearInterval(this.idleTimer);
- if (this.targetIdx == -1) {
- uni.showToast({
- title: '抽奖失败',
- icon: 'none'
- })
- this.running = false;
- return
- }
- this.animation(this.targetIdx)
- setTimeout(() => {
- this.running = false;
- uni.showModal({
- title: '恭喜,中奖',
- content: this.list[this.targetIdx].name,
- showCancel: false,
- success: function(res) {
- if (res.confirm) {
- that.$refs.turntablePopup.close()
- that.$emit("openAppPop")
- } else if (res.cancel) {
- that.$refs.turntablePopup.close()
- that.$emit("openAppPop")
- }
- }
- });
- }, this.duration + 1000)
- }
- }
- }
- </script>
- <style scoped lang="scss">
- @keyframes spin {
- from {
- transform: rotate(0deg);
- }
- to {
- transform: rotate(360deg);
- }
- }
- .infinite-spin {
- animation: spin 1s linear infinite;
- }
- .close {
- width: 64rpx;
- height: 64rpx;
- margin: 24rpx auto 0 auto;
- display: block;
- }
- .turntable {
- position: relative;
- width: 660rpx;
- height: 880rpx;
- .bg {
- width: 660rpx;
- height: 880rpx;
- position: absolute;
- top: 0;
- left: 0;
- }
- &-con {
- width: 660rpx;
- height: 880rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- position: relative;
- z-index: 2;
- }
- .text {
- width: 520rpx;
- height: 104rpx;
- margin-top: 47rpx;
- }
- .base {
- width: 451rpx;
- height: 177rpx;
- position: absolute;
- bottom: 55rpx;
- left: 50%;
- transform: translateX(-50%);
- z-index: 3;
- }
- .decoration_img {
- width: 637rpx;
- height: 592rpx;
- position: absolute;
- bottom: 85rpx;
- left: 50%;
- transform: translateX(-50%);
- z-index: 4;
- }
- .ring {
- width: 502rpx;
- height: 502rpx;
- background: #FFFDFD;
- border-radius: 50%;
- position: relative;
- margin-top: 79rpx;
- z-index: 9;
- }
- .button {
- width: 158rpx;
- height: 200rpx;
- position: absolute;
- top: calc(50% - 21rpx);
- left: 50%;
- transform: translate(-50%, -50%);
- z-index: 99;
- }
- .ring_bg {
- width: 620rpx;
- height: 620rpx;
- position: absolute;
- bottom: 74rpx;
- left: 50%;
- transform: translateX(-50%);
- z-index: 6;
- }
- .canvas-content {
- position: absolute;
- left: 0;
- top: 0;
- z-index: 1;
- display: block;
- width: 502rpx;
- height: 502rpx;
- border-radius: inherit;
- /* background-clip: padding-box; */
- /* background-color: #ffcb3f; */
- }
- .icon-awrad {
- width: 72rpx;
- height: 72rpx;
- margin-top: 10rpx;
- object-fit: contain;
- }
- .canvas-list {
- position: absolute;
- left: 0;
- top: 0;
- width: inherit;
- height: inherit;
- z-index: 99;
- }
- .canvas-item {
- position: absolute;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- color: #e4370e;
- /* text-shadow: 0 1rpx 1rpx rgba(255, 255, 255, 0.6); */
- }
- .canvas-item-text {
- position: relative;
- display: block;
- padding-top: 14rpx;
- margin: 0 auto;
- text-align: center;
- -webkit-transform-origin: 50% 251rpx;
- transform-origin: 50% 251rpx;
- display: flex;
- flex-direction: column;
- align-items: center;
- color: #F72F26;
- font-weight: 500;
- font-size: 24rpx;
- }
- .canvas-item-text text {
- font-size: 30rpx;
- }
- /* 分隔线 */
- .canvas-line {
- position: absolute;
- left: 0;
- top: 0;
- width: inherit;
- height: inherit;
- z-index: 99;
- }
- .canvas-litem {
- position: absolute;
- left: 251rpx;
- top: 0;
- width: 1rpx;
- height: 251rpx;
- background-color: #FF4D2C;
- overflow: hidden;
- -webkit-transform-origin: 50% 251rpx;
- transform-origin: 50% 251rpx;
- }
- }
- </style>
|