yuanjing/src/views/Home.vue
2026-04-01 11:05:03 +08:00

309 lines
8.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<div class="home">
<div class="background-video-stack">
<video v-for="(video, index) in videoList" :key="index" class="background-video"
:class="{ 'is-active': activeIndex === index }" autoplay muted loop :poster="video.poster">
<source :src="video.src" type="video/mp4" />
</video>
</div>
<header>
<div class="left">
<img src="../assets/images/favicon.png" alt="logo" />
<span class="header-title">元境</span>
</div>
<div class="right">
<div class="btn" @click="$router.push('/index')">立即体验</div>
</div>
</header>
<main>
<div class="container">
<h2 class="slogan">元启万象境由心生</h2>
<!-- 输入框容器 -->
<div class="input-container">
<!-- 头像区域使用 transition 实现淡入淡出 -->
<div class="avatar">
<!-- <transition name="fade" mode="out-in"> -->
<img :key="activeIndex" :src="videoList[activeIndex].poster" alt="avatar" />
<!-- </transition> -->
</div>
<!-- 输入框添加动态闪烁类提示占位符变化 -->
<input ref="inputRef" type="text" class="prompt-input" :placeholder="currentPlaceholder"
:class="{ 'placeholder-flash': isFlashing }" />
<div class="create-btn">创作</div>
</div>
</div>
</main>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed, watch } from 'vue'
// 视频数据:包含视频地址、封面图、对应的占位文本
const videoList = [
{
src: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/01-%E5%A5%B3%E4%BA%BA%E4%B8%8E%E8%8A%B1.mp4',
poster: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/%E5%A5%B3%E4%BA%BA%E4%B8%8E%E8%8A%B11.webp',
placeholder: '一位优雅的女性与花丛,午后阳光洒在花瓣上...'
},
{
src: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/04-%E5%B0%8F%E5%A5%B3%E5%AD%A9%E4%B8%8E%E7%8C%AB.mp4',
poster: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/%E5%B0%8F%E5%A5%B3%E5%AD%A9%E4%B8%8E%E7%8C%AB1.webp',
placeholder: '小女孩抱着猫,眼神温柔,毛茸茸的尾巴轻轻摆动...'
},
{
src: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/03-%E8%A1%97%E5%A4%B4%E6%BB%91%E6%9D%BF.mp4',
poster: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/%E8%A1%97%E5%A4%B4%E6%BB%91%E6%9D%BF1.webp',
placeholder: '街头滑板少年,腾空跃起,动作流畅充满活力...'
},
{
src: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/05-%E4%B9%90%E9%AB%98%E9%A3%8E%E6%A0%BC%E6%9C%BA%E8%BD%A6.mp4',
poster: 'https://console-download.s3.cn-north-1.jdcloud-oss.com/-lingjing-only/pre_creation/first_page/%E4%B9%90%E9%AB%98%E9%A3%8E%E6%A0%BC%E6%9C%BA%E8%BD%A61.webp',
placeholder: '乐高风格的机车,色彩鲜艳,齿轮转动充满机械感...'
}
]
const activeIndex = ref(0) // 当前显示的视频索引
let timer: number | null = null // 轮播定时器
// 根据当前激活的视频返回对应的占位文本
const currentPlaceholder = computed(() => videoList[activeIndex.value].placeholder)
// 用于触发输入框闪烁动画
const inputRef = ref<HTMLInputElement | null>(null)
const isFlashing = ref(false)
// 监听 activeIndex 变化,触发占位符闪烁动画
watch(activeIndex, () => {
isFlashing.value = true
setTimeout(() => {
isFlashing.value = false
}, 300) // 与动画时长保持一致
})
// 开始轮播每5秒切换到下一个视频
const startCarousel = () => {
timer = setInterval(() => {
activeIndex.value = (activeIndex.value + 1) % videoList.length
}, 5000) // 5秒切换一次
}
onMounted(() => {
startCarousel()
})
onUnmounted(() => {
if (timer) clearInterval(timer)
})
</script>
<style scoped lang="less">
.home {
width: 100%;
height: 100vh;
overflow: hidden;
}
.background-video-stack {
position: absolute;
inset: 0;
// z-index: 0; // 可根据需要取消注释
}
.background-video {
position: absolute;
inset: 0;
height: 100%;
width: 100%;
object-fit: cover;
opacity: 0; // 默认隐藏所有视频
pointer-events: none;
transition: opacity .4s ease-in-out;
}
.background-video.is-active {
opacity: 1; // 当前激活的视频显示
}
header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 24px;
position: relative;
.left {
display: flex;
align-items: center;
gap: 8px;
img {
width: 50px;
height: 50px;
}
.header-title {
font-family: "Microsoft Yahei", "PingFang SC", sans-serif;
font-size: 30px;
font-weight: 550;
color: #fff;
transform: skew(-8deg);
-webkit-transform: skew(-12deg);
}
}
.right {
.btn {
background-color: #000;
color: #fff;
border: none;
border-radius: 40px;
padding: 10px 28px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: background-color 0.2s, transform 0.1s;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.05);
letter-spacing: 0.3px;
&:hover {
background-color: #2a2a2a;
}
&:active {
transform: scale(0.97);
}
}
}
}
main {
padding: 80px 0;
width: 100%;
position: absolute;
top: 50%;
left: 0%;
.container {
// z-index: 999;
.slogan {
font-size: 64px;
font-weight: 600;
color: #fff;
text-align: center;
margin-bottom: 40px;
}
.input-container {
display: flex;
align-items: center;
width: 90%;
max-width: 1000px;
height: 56px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.15);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 28px;
overflow: hidden;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
.avatar {
width: 40px;
height: 24px;
margin: 0 12px;
// border-radius: 50%;
overflow: hidden;
flex-shrink: 0;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.prompt-input {
flex: 1;
height: 100%;
padding: 0 8px;
background: transparent;
border: none;
outline: none;
font-size: 16px;
color: #333;
caret-color: #000;
transition: border-color 0.2s, background-color 0.2s;
&::placeholder {
color: #fff;
font-size: 15px;
line-height: 1.4;
}
}
.placeholder-flash {
border-color: rgba(255, 255, 255, 0.8) !important;
background-color: rgba(255, 255, 255, 0.2) !important;
animation: pulse 0.3s ease;
}
@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.4);
}
70% {
box-shadow: 0 0 0 6px rgba(255, 255, 255, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 255, 255, 0);
}
}
.create-btn {
height: 44px;
min-width: 100px;
margin: 0 6px;
background-color: #000;
color: #fff;
border-radius: 22px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.2s ease;
flex-shrink: 0;
&:hover {
background-color: #333;
transform: translateY(-1px);
}
&:active {
transform: scale(0.98);
}
}
}
}
}
/* 头像淡入淡出动画 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>