Browse Source

转盘完成

master
zhaoruhui 3 weeks ago
parent
commit
aa3aecbe63
  1. BIN
      src/assets/img/liveEvent/bg.png
  2. BIN
      src/assets/img/liveEvent/bg1.png
  3. BIN
      src/assets/img/liveEvent/close.png
  4. BIN
      src/assets/img/liveEvent/notice.png
  5. BIN
      src/assets/img/liveEvent/rotate.png
  6. BIN
      src/assets/img/liveEvent/show.png
  7. BIN
      src/assets/img/liveEvent/tanchuang3.png
  8. BIN
      src/assets/img/liveEvent/tanchuang4.png
  9. BIN
      src/assets/img/liveEvent/wheel.png
  10. 7
      src/router/index.js
  11. 287
      src/views/platform/liveEvent.vue

BIN
src/assets/img/liveEvent/bg.png

After

Width: 1920  |  Height: 1080  |  Size: 1.8 MiB

BIN
src/assets/img/liveEvent/bg1.png

After

Width: 3840  |  Height: 2160  |  Size: 1.8 MiB

BIN
src/assets/img/liveEvent/close.png

After

Width: 104  |  Height: 104  |  Size: 3.8 KiB

BIN
src/assets/img/liveEvent/notice.png

After

Width: 498  |  Height: 126  |  Size: 18 KiB

BIN
src/assets/img/liveEvent/rotate.png

After

Width: 430  |  Height: 492  |  Size: 194 KiB

BIN
src/assets/img/liveEvent/show.png

After

Width: 1190  |  Height: 254  |  Size: 130 KiB

BIN
src/assets/img/liveEvent/tanchuang3.png

After

Width: 1710  |  Height: 1238  |  Size: 1.1 MiB

BIN
src/assets/img/liveEvent/tanchuang4.png

After

Width: 1710  |  Height: 1238  |  Size: 1.5 MiB

BIN
src/assets/img/liveEvent/wheel.png

After

Width: 1360  |  Height: 1360  |  Size: 2.5 MiB

7
src/router/index.js

@ -3,7 +3,7 @@ import { useAuthStore } from '../stores/auth';
const routes = [ const routes = [
{ {
path: '/', path: '/',
redirect: '/anniversary'
redirect: '/liveEvent'
}, },
{ {
path: '/homePage', path: '/homePage',
@ -37,6 +37,11 @@ const routes = [
path: '/anniversary', path: '/anniversary',
name: 'anniversary', name: 'anniversary',
component: () => import('../views/platform/anniversary.vue'), component: () => import('../views/platform/anniversary.vue'),
},
{
path: '/liveEvent',
name: 'liveEvent',
component: () => import('../views/platform/liveEvent.vue'),
} }
] ]
// 创建路由实例 // 创建路由实例

287
src/views/platform/liveEvent.vue

@ -0,0 +1,287 @@
<template>
<div class="wheel-page">
<!-- 背景 -->
<div class="bg-container">
<img class="bg-image" :src="bgImage" alt="Background" />
</div>
<!-- 转盘 + 按钮 -->
<div class="wheel-container">
<img
class="wheel"
:src="wheelImage"
alt="Wheel"
:style="{ transform: `rotate(${rotationDegrees}deg)` }"
/>
<img
class="rotate-btn"
:src="rotateImage"
alt="Rotate Button"
:class="{ disabled: isRotated }"
@click="startRotation"
/>
</div>
<!-- 弹窗 -->
<div class="dialog-overlay" v-if="showDialog">
<div class="dialog-content">
<img class="dialog-bg" :src="tanchuangImage" alt="Dialog Background" />
<img class="close-btn" :src="closeImage" alt="Close" @click="closeDialog" />
<img class="notice-img" :src="noticeImage" alt="Notice" />
<div class="show-container">
<img class="show-bg" :src="showImage" alt="Show Background" />
<div class="prize-number">-1880</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
/* -------------------- 图片引入 -------------------- */
import bgImage from '@/assets/img/liveEvent/bg.png'
import wheelImage from '@/assets/img/liveEvent/wheel.png'
import rotateImage from '@/assets/img/liveEvent/rotate.png'
import tanchuangImage from '@/assets/img/liveEvent/tanchuang4.png'
import closeImage from '@/assets/img/liveEvent/close.png'
import noticeImage from '@/assets/img/liveEvent/notice.png'
import showImage from '@/assets/img/liveEvent/show.png'
/* -------------------- 核心常量 -------------------- */
const SEGMENT = 360 / 7
const TARGET_ANGLE = 360 - SEGMENT // 308.57° 12 -1880
/* -------------------- 响应式状态 -------------------- */
import { ref, onUnmounted } from 'vue'
const isRotated = ref(false) // true
const showDialog = ref(false)
const rotationDegrees = ref(0)
let rotationTimeout = null
/* -------------------- 仅允许转一次 -------------------- */
function startRotation() {
if (isRotated.value) return
isRotated.value = true
const current = rotationDegrees.value % 360
const extra = 2160 // 6 360
rotationDegrees.value = extra + TARGET_ANGLE - current
rotationTimeout = setTimeout(() => (showDialog.value = true), 4000)
}
/* -------------------- 关闭弹窗(不再重置按钮)-------------------- */
function closeDialog() {
showDialog.value = false
// isRotated.value = false
}
onUnmounted(() => {
if (rotationTimeout) {
clearTimeout(rotationTimeout)
rotationTimeout = null
}
})
</script>
<style scoped>
/* ---------- 基础重置 ---------- */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wheel-page {
width: 100vw;
height: 100vh;
position: relative;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
}
/* ---------- 背景 ---------- */
.bg-container {
position: absolute;
inset: 0;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
.bg-image {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center 42%;
}
/* ---------- 转盘容器(放大 + 下移) ---------- */
.wheel-container {
position: relative;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
width: 600px;
height: 600px;
max-width: 85vmin;
max-height: 85vmin;
margin-top: 60px;
margin-bottom: 2%;
transform: translateY(40px);
}
/* ---------- 转盘 ---------- */
.wheel {
width: 100%;
height: 100%;
transition: transform 4s cubic-bezier(0.3, 0.1, 0.1, 1);
transform-origin: center;
}
/* ---------- 按钮(永久一次)---------- */
.rotate-btn {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%); /* 几何中心对齐 */
width: 215px; /* 原图宽度 */
aspect-ratio: 1 / 1; /* 强制正方形盒子,高度=215px */
cursor: pointer;
z-index: 3;
transition: transform 0.2s, opacity 0.2s, filter 0.2s;
object-fit: contain; /* 原图等比完整显示 */
object-position: center;
}
.rotate-btn:hover:not(.disabled) {
transform: translate(-50%, -50%) scale(1.05);
}
.rotate-btn.disabled {
cursor: not-allowed;
opacity: 1;
filter: grayscale(40%);
}
/* ---------- 弹窗 ---------- */
.dialog-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
animation: fadeIn 0.5s;
}
.dialog-content {
position: relative;
width: 600px;
height: 412px;
max-width: 85vw;
max-height: 65vh;
}
.dialog-bg {
width: 100%;
height: 100%;
object-fit: contain;
}
.close-btn {
position: absolute;
top: 22%;
right: 13.2%;
width: 5%;
cursor: pointer;
}
.notice-img {
position: absolute;
top: 22%;
left: 50%;
transform: translateX(-50%);
width: 33%;
}
.show-container {
position: absolute;
top: 41%;
left: 0;
width: 100%;
display: flex;
justify-content: center;
}
.show-bg {
width: 71.6%;
}
.prize-number {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 66px;
font-weight: bold;
color: #ffeb3b;
text-shadow: 0 0 10px rgba(255, 235, 59, 0.8);
animation: pulse 1s infinite alternate;
}
/* ---------- 动画 ---------- */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes pulse {
from {
transform: translate(-50%, -50%) scale(1);
text-shadow: 0 0 10px rgba(255, 235, 59, 0.8);
}
to {
transform: translate(-50%, -50%) scale(1.1);
text-shadow: 0 0 20px rgba(255, 235, 59, 1);
}
}
/* ---------- 响应式 ---------- */
@media (max-width: 900px) {
.wheel-container {
width: 75vmin;
height: 75vmin;
margin-top: 40px;
}
}
@media (max-width: 600px) {
.wheel-container {
width: 80vmin;
height: 80vmin;
margin-top: 30px;
}
.dialog-content {
max-height: 55vh;
}
}
@media (max-height: 600px) and (orientation: landscape) {
.wheel-container {
width: 65vmin;
height: 65vmin;
margin-top: 20px;
}
.bg-image {
object-position: center 30%;
}
}
@media (max-width: 375px) {
.wheel-container {
width: 70vmin;
height: 70vmin;
margin-top: 20px;
}
.dialog-content {
max-width: 80vw;
max-height: 50vh;
}
}
</style>
Loading…
Cancel
Save