更新样式和功能:添加背景图、打字机效果,优化留言板和吐槽区布局

This commit is contained in:
qingfeng1121
2025-09-29 18:39:10 +08:00
parent ade67e4411
commit aaf326ed1f
8 changed files with 519 additions and 422 deletions

View File

@@ -3,14 +3,12 @@
<el-row justify="center">
<el-col :span="4" v-if="windowwidth">
<div class="grid-content ep-bg-purple-dark">
<!-- <div><img src="../public/favicon.ico" alt=""></div> -->
<div>清疯不颠</div>
</div>
</el-col>
<el-col :span="14" justify="center">
<div class="grid-content ep-bg-purple-dark">
<el-menu :default-active="activeIndex" class="el-menu-demo" :collapse="false"
@select="handleSelect">
<el-menu :default-active="activeIndex" class="el-menu-demo" :collapse="false" @select="handleSelect">
<el-menu-item index="/:type">
首页
</el-menu-item>
@@ -35,7 +33,7 @@
</el-row>
</div>
<div class="hero" :class="{ 'newhero': classhero }" v-if="windowwidth">
<h1>如果感到累了撸一管就好了</h1>
<h1 class="typewriter">{{ heroText }}</h1>
</div>
<div id="content-section" :class="{ 'visible': isconts }">
@@ -54,309 +52,161 @@
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import { useRouter } from 'vue-router'
import leftmodlue from '@/views/leftmodlue.vue'
import { ref, onMounted, onUnmounted } from 'vue';
import { useRouter } from 'vue-router';
import leftmodlue from '@/views/leftmodlue.vue';
// hero 的高度更新
// hero 区域样式控制
const classhero = ref(false);
const isconts = ref(false); // 内容
// 内容区可见性
const isconts = ref(false);
// 左侧模块滚动状态
const isScrollingleftmodlue = ref(false);
const elrowtop = ref(); // 导航
const classnonsenset = ref(false) // 疯言疯语
const windowwidth = ref(true) // 屏幕
// 路由
const router = useRouter()
// 导航栏样式类名
const elrowtop = ref('transparent');
// 疯言疯语标题区显示
const classnonsenset = ref(false);
// 屏幕宽度标记true为大屏false为小屏
const windowwidth = ref(true);
// 当前激活菜单
const activeIndex = ref('/:type');
// 打字机效果相关
const fullHeroText = '如果感到累了撸一管就好了';
const heroText = ref('');
let heroIndex = 0;
let heroTimer: number | undefined;
const startTypewriter = () => {
heroText.value = '';
heroIndex = 0;
if (heroTimer) clearInterval(heroTimer);
heroTimer = window.setInterval(() => {
if (heroIndex < fullHeroText.length) {
heroText.value += fullHeroText[heroIndex];
heroIndex++;
} else {
clearInterval(heroTimer);
}
}, 100);
};
const router = useRouter();
/**
* 菜单选择跳转
*/
const handleSelect = (key: string) => {
router.push({
path: key
})
}
// 是否在某页面
const isclass = (url: any) => {
classhero.value = url != '/:type';
classnonsenset.value = url == '/nonsense'
}
router.push({ path: key });
};
// url监听
// 使用router.beforeEach或router.afterEach全局守卫
/**
* 根据路由路径设置页面状态
*/
const updatePageState = (url: string) => {
classhero.value = url !== '/:type';
classnonsenset.value = url === '/nonsense';
};
/**
* 路由切换时处理页面状态和滚动
*/
router.beforeEach((to) => {
// console.log("从", from.path, "到", to.path);
isclass(to.path)
// 回到顶部
window.scrollTo({
top: 0,
behavior: 'smooth' // 平滑滚动
});
});
// 滚动事件
const handleScroll = () => {
const scrollYmo = window.scrollY;
// 只有首页才会执行页面内容滚动效果
if (location.pathname == '/:type') {
isconts.value = window.scrollY > 200;
isScrollingleftmodlue.value = window.scrollY > 600;
}else{
updatePageState(to.path);
setActiveIndex(to.path);
// 跳转后回到顶部
window.scrollTo({ top: 0, behavior: 'smooth' });
// 首页内容区滚动动画仅大屏下生效
if (to.path === '/:type') {
isconts.value = window.innerWidth <= 768 ? true : false;
// 首页时启动打字机
startTypewriter();
} else {
isconts.value = true;
isScrollingleftmodlue.value = true;
heroText.value = '';
if (heroTimer) clearInterval(heroTimer);
}
// 导航
if (scrollYmo > 1200) {
elrowtop.value = 'hide'
});
/**
* 滚动事件处理
*/
const handleScroll = () => {
// 屏幕小于768时只切换导航栏样式不做内容动画
if (window.innerWidth < 768) {
elrowtop.value = window.scrollY > 100 ? 'solid' : 'transparent';
return;
}
// 导航栏样式切换
if (window.scrollY > 1200) {
elrowtop.value = 'hide';
} else {
elrowtop.value = window.scrollY > 100 ? 'solid' : 'transparent';
}
// 首页内容区滚动动画
if (location.pathname === '/:type') {
isconts.value = window.scrollY > 200;
isScrollingleftmodlue.value = window.scrollY > 600;
} else {
isconts.value = true;
isScrollingleftmodlue.value = true;
}
};
/**
* 添加滚动监听
*/
const addScrollListener = () => {
window.addEventListener('scroll', handleScroll);
};
/**
* 移除滚动监听
*/
const removeScrollListener = () => {
window.removeEventListener('scroll', handleScroll);
};
const mediaquery = () => {
// 在这里处理屏幕大小变化
/**
* 屏幕尺寸变化处理
* 小屏时移除滚动监听并设置相关状态
* 大屏时添加滚动监听
*/
const handleResize = () => {
if (window.innerWidth < 768) {
removeScrollListener();
windowwidth.value = false
isScrollingleftmodlue.value = true
classnonsenset.value = false
windowwidth.value = false;
isScrollingleftmodlue.value = true;
classnonsenset.value = false;
isconts.value = true;
removeScrollListener();
} else {
windowwidth.value = true;
addScrollListener();
windowwidth.value = true
}
};
// 页面加载完成后执行
const activeIndex = ref('/:type')
const isactiveindex = () => {
// 获取当前路径
const currentPath = window.location.pathname;
// 判断路径并设置hero值
activeIndex.value = currentPath;
}
/**
* 设置当前激活菜单
*/
const setActiveIndex = (locationpathname) => {
activeIndex.value = locationpathname;
};
window.addEventListener('DOMContentLoaded', () => {
isactiveindex();
mediaquery();
// 生命周期钩子
onMounted(() => {
handleResize();
window.addEventListener('resize', handleResize);
// 初始进入时如果是首页,启动打字机
if (window.location.pathname === '/:type') {
startTypewriter();
}
});
window.addEventListener('resize', mediaquery);
window.addEventListener('DOMContentLoaded', isactiveindex);
// 输入框
onUnmounted(() => {
removeScrollListener();
window.removeEventListener('resize', handleResize);
if (heroTimer) clearInterval(heroTimer);
});
</script>
<style></style>
<!-- <style>
body {
/* background-image: url(./img/8.21.1.jpg); */
background-size: 120% 120%;
background-repeat: no-repeat;
background-position: center;
background-attachment: fixed;
}
body ul {
border-bottom: 0px;
}
.h1,
.h2,
.h3,
.h4,
.h5,
.h6,
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: inherit;
font-weight: 400;
line-height: 1.5;
margin-bottom: .5rem;
color: #32325d;
}
p {
font-size: 1rem;
font-weight: 300;
line-height: 1.7;
}
.cont {
margin-top: 5%;
}
/* 导航 */
.elrow-top {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 20px 40px;
justify-content: space-between;
align-items: center;
z-index: 1000;
transition: all 0.4s ease;
font-size: inherit;
}
.elrow-top.transparent {
background-color: transparent;
}
.elrow-top.solid {
background-color: rgba(145, 196, 238, 0.85);
padding: 15px 40px;
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1);
}
.elrow-top.hide {
background-color: rgba(145, 196, 238, 0);
box-shadow: 0 5px 20px rgba(0, 0, 0, 0);
top: -100px;
transition: all 0.8s ease;
}
.elrow-top .el-row .el-col .grid-content .el-menu--horizontal {
border-bottom: 0px;
}
.el-menu--horizontal {
background: rgb(0, 0, 0, 0);
}
.el-menu-demo {
font-weight: bold;
font-size: 20px;
left: 10%;
}
.el-menu-demo .el-menu-item {
margin-left: 10px;
}
.el-menu.el-menu--horizontal.el-menu-demo .el-menu-item {
font-size: inherit;
}
.el-menu.el-menu--horizontal.el-menu-demo .el-menu-item:hover,
.el-menu.el-menu--horizontal.el-menu-demo .el-menu-item.is-active {
background-color: rgb(0, 0, 0, 0);
}
/* 内容 */
#content-section {
min-height: 100vh;
padding: 100px 10%;
opacity: 0;
transform: translateY(50px);
transition: all 0.8s ease-out;
/* margin: 20px 0; */
border-radius: 10px;
display: flex;
}
#content-section.visible {
opacity: 1;
transform: translateY(0);
}
.search {
margin-top: 12px;
}
.grid-content {
text-align: center;
}
.RouterViewpage {
width: 80%;
margin-left: 5%;
margin-right: 5%;
}
/* 分页 */
.Pagination {
align-self: center;
background-color: aqua;
}
#search {
display: flex;
}
.el-button {
background-color: rgb(0, 0, 0, 0);
border: 0px;
}
/* 状态栏 */
.leftmodluepage {
width: 20%;
}
/* 开头标题样式*/
.hero {
height: 600px;
margin-top: 5%;
display: flex;
justify-content: center;
align-items: center;
text-align: center;
color: white;
}
.hero.newhero {
height: 200px;
transition: all 0.3s ease;
}
.hero h1 {
font-size: 3.5rem;
margin-bottom: 20px;
}
.hero p {
font-size: 1.5rem;
max-width: 700px;
margin: 0 auto 30px;
}
/* 疯言疯语标题 */
.nonsensetitle {
text-align: center;
position: absolute;
top: 0;
width: 76.5%;
padding: 20px;
margin-bottom: 50px;
background: rgba(255, 255, 255, 0.1) !important;
backdrop-filter: blur(10px);
border-radius: 20px;
}
.nonsensetitle .nonsensetitleconst {
padding: 1.5rem;
flex: 1 1 auto;
box-sizing: border-box;
}
.nonsensetitle .nonsensetitleconst p {
font-size: 1rem;
}
/* 调整样式 */
.nonsensetmargintop {
margin-top: 130px;
}
/* 输入框 */
</style> -->
<style>
</style>