valaxy博客全局美化教程(六)

valaxy博客全局美化教程(六)

本系列教程共十篇

话不多说,先看效果

页面下滑时信封自动展开,上划自动闭合,可以自己换图片,但是尺寸要一样哈,由于涉及到图床,大家尽量只下载图片,不要直接使用站长的链接,因为站长不能保证什么时候就失效了 给出所有图片的图床链接:
text
https://pic1.imgdb.cn/item/6a26e5483c9809430d376f88.png
https://pic1.imgdb.cn/item/6a26e5483c9809430d376f87.png
https://pic1.imgdb.cn/item/6a26e5483c9809430d376f85.png
https://pic1.imgdb.cn/item/6a26e5483c9809430d376f86.png

从上到下分别是信纸、顶部信封、底部信封和横条,下面链接和这里一样,大家最好修改一下,测试用着可以,不要生产环境使用哦

新增文件

新增文件咯,只有一个文件,有点长哦 新增文件components\layouts\SakuraCommentLayout.vue

text
<script setup lang="ts">
import { useSiteConfig } from 'valaxy'
import { computed, onMounted, onUnmounted, ref } from 'vue'

const siteConfig = useSiteConfig()
const authorName = computed(() => siteConfig.value.author?.name || '站长')

const isOpened = ref(false)
const formWrapRef = ref<HTMLElement>()

const envelopeConfig = {
  images: {
    cover: 'https://pic1.imgdb.cn/item/6a26e5483c9809430d376f88.png',
    line: 'https://pic1.imgdb.cn/item/6a26e5483c9809430d376f86.png',
    beforeimg: 'https://pic1.imgdb.cn/item/6a26e5483c9809430d376f85.png',
    afterimg: 'https://pic1.imgdb.cn/item/6a26e5483c9809430d376f87.png',
  },
  wrapHeight: 447,
  openHeight: 1050,
  openOffset: -200,
  /** 滚回页面顶部时闭合(px) */
  scrollCloseTop: 80,
}

const message = [
  '本站有哪些做得好或者不好的地方?',
  '或者你有什么改进的建议?',
  '又或者你有什么具体的问题需要咨询?',
  '都可以在下方评论区留言哦~~~',
]

const bottomText = '小站站长亲自为您服务!'

let scrollRaf: number | undefined

function getScrollTop() {
  return window.pageYOffset
    || document.documentElement.scrollTop
    || document.body.scrollTop
    || 0
}

function openEnvelope() {
  isOpened.value = true
}

function closeEnvelope() {
  isOpened.value = false
}

function handleEnvelopeClick() {
  if (!isOpened.value)
    openEnvelope()
}

function isEnvelopeFullyVisible() {
  if (!formWrapRef.value || isOpened.value)
    return false

  const rect = formWrapRef.value.getBoundingClientRect()
  const viewportHeight = window.innerHeight

  // 桌面信封隐藏(移动端)时不触发
  if (rect.width === 0 || rect.height === 0)
    return false

  // 信封(闭合高度)完整出现在视口内时展开
  return rect.top >= 0 && rect.bottom <= viewportHeight + 1
}

function updateEnvelopeByScroll() {
  if (isEnvelopeFullyVisible()) {
    openEnvelope()
    return
  }

  if (isOpened.value && getScrollTop() <= envelopeConfig.scrollCloseTop)
    closeEnvelope()
}

function handleScroll() {
  if (scrollRaf)
    return

  scrollRaf = requestAnimationFrame(() => {
    scrollRaf = undefined
    updateEnvelopeByScroll()
  })
}

onMounted(() => {
  updateEnvelopeByScroll()
  window.addEventListener('scroll', handleScroll, { passive: true })
  window.addEventListener('resize', handleScroll, { passive: true })
})

onUnmounted(() => {
  if (scrollRaf)
    cancelAnimationFrame(scrollRaf)
  window.removeEventListener('scroll', handleScroll)
  window.removeEventListener('resize', handleScroll)
})
</script>

<template>
  <SakuraPage class="sakura-comment-page">
    <template #content>
      <RouterView v-slot="{ Component }">
        <component :is="Component">
          <template #main-content>
            <div id="envelope-maincontent" class="envelope-maincontent">
              <div
                id="form-wrap"
                ref="formWrapRef"
                class="form-wrap envelope-desktop"
                :class="{ opened: isOpened }"
                :style="{
                  '--wrap-height': `${envelopeConfig.wrapHeight}px`,
                  '--open-height': `${envelopeConfig.openHeight}px`,
                  '--open-offset': `${envelopeConfig.openOffset}px`,
                }"
                @click="handleEnvelopeClick"
              >
              <img
                id="beforeimg"
                class="beforeimg"
                :src="envelopeConfig.images.beforeimg"
                alt="信封背景"
                loading="lazy"
              >

              <div id="envelope" class="envelope">
                <div class="formmain">
                  <img
                    class="headerimg"
                    :src="envelopeConfig.images.cover"
                    alt="信笺封面"
                    loading="lazy"
                  >

                  <div class="comments-main">
                    <h3 class="title3">
                      ✨来自{{ authorName }}的留言:
                    </h3>

                    <div class="comments">
                      <p
                        v-for="(msg, index) in message"
                        :key="index"
                      >
                        {{ msg }}
                      </p>
                    </div>

                    <div class="bottomcontent">
                      <img
                        class="bottomimg"
                        :src="envelopeConfig.images.line"
                        alt="信笺底部装饰"
                        loading="lazy"
                      >
                    </div>

                    <p class="bottomhr">
                      {{ bottomText }}
                    </p>
                  </div>
                </div>
              </div>

              <img
                id="afterimg"
                class="afterimg"
                :src="envelopeConfig.images.afterimg"
                alt="信封前景"
                loading="lazy"
              >
            </div>

            <!-- 移动端:无信封图片,仅展示信笺 -->
            <div class="envelope-mobile">
              <div class="formmain">
                <img
                  class="headerimg"
                  :src="envelopeConfig.images.cover"
                  alt="信笺封面"
                  loading="lazy"
                >

                <div class="comments-main">
                  <h3 class="title3">
                    ✨来自{{ authorName }}的留言:
                  </h3>

                  <div class="comments">
                    <p
                      v-for="(msg, index) in message"
                      :key="index"
                    >
                      {{ msg }}
                    </p>
                  </div>

                  <div class="bottomcontent">
                    <img
                      class="bottomimg"
                      :src="envelopeConfig.images.line"
                      alt="信笺底部装饰"
                      loading="lazy"
                    >
                  </div>

                  <p class="bottomhr">
                    {{ bottomText }}
                  </p>
                </div>
              </div>
            </div>
          </div>
        </template>

        <template #comment>
          <div class="envelope-comment-wrap">
            <SakuraComment />
          </div>
        </template>
      </component>
    </RouterView>
    </template>
  </SakuraPage>
</template>

<style lang="scss" scoped>
.envelope-maincontent {
  width: 530px;
  max-width: 100%;
  margin-inline: auto;
  margin-top: 20px;
  position: relative;
  z-index: 1;
  box-sizing: border-box;
}

.form-wrap {
  overflow: hidden;
  width: 530px;
  max-width: 100%;
  height: var(--wrap-height, 447px);
  position: relative;
  top: 0;
  transition: all 1s ease-in-out 0.3s;
  z-index: 0;
  cursor: pointer;
  user-select: none;
  box-sizing: border-box;
  margin-inline: auto;
}

.form-wrap.opened {
  height: var(--open-height, 1050px);
  top: var(--open-offset, -200px);
}

.beforeimg {
  position: absolute;
  bottom: 126px;
  left: 0;
  right: 0;
  width: 100%;
  height: 317px;
  z-index: 0;
  pointer-events: none;
  display: block;
  object-fit: fill;
}

.afterimg {
  position: absolute;
  bottom: -2px;
  left: 0;
  right: 0;
  width: 100%;
  height: 259px;
  z-index: 100;
  pointer-events: none;
  display: block;
  object-fit: fill;
}

.envelope {
  position: relative;
  overflow: visible;
  width: 500px;
  max-width: calc(100% - 30px);
  margin-inline: auto;
  padding-top: 200px;
  transition: all 1s ease-in-out 0.3s;
  z-index: 10;
  box-sizing: border-box;
}

.headerimg {
  width: 100%;
  display: block;
  overflow: hidden;
  pointer-events: none;
  object-fit: cover;
}

.formmain {
  background: #fff;
  width: 95%;
  max-width: 800px;
  margin: 0 auto;
  border-radius: 5px;
  border: 1px solid rgba(0, 0, 0, 0.08);
  overflow: hidden;
  box-shadow: 0 0 20px rgba(0, 0, 0, 0.18);
  pointer-events: none;
}

.comments-main {
  padding: 5px 20px 16px;
}

.title3 {
  margin: 12px 0 8px;
  text-decoration: none;
  color: var(--sakura-color-primary, #fe9500);
  text-align: center;
  font-size: 1.15rem;
  font-weight: 700;
}

.comments {
  text-align: center;
  border: 1px solid #ddd;
  padding: 20px;
  margin: 15px 0;
  background-color: #eee;
  line-height: 2;

  p {
    margin: 0;
    font-size: 15px;
    color: #333;
  }
}

.bottomcontent {
  text-align: center;
  margin-top: 24px;
}

.bottomimg {
  width: 100%;
  margin: 5px auto;
  display: block;
  pointer-events: none;
}

.bottomhr {
  margin: 8px 0 0;
  font-size: 12px;
  text-align: center;
  color: #999;
}

.envelope-mobile {
  display: none;
}

.envelope-comment-wrap {
  position: relative;
  z-index: 20;
  width: 100%;
  max-width: 800px;
  margin-inline: auto;
  margin-top: 24px;
  margin-bottom: 40px;
  padding-inline: 10px;
  box-sizing: border-box;
}

@media screen and (max-width: 600px) {
  .envelope-desktop {
    display: none !important;
  }

  .envelope-mobile {
    display: block;
  }

  .envelope-maincontent {
    max-width: 100%;
    margin-top: 12px;
  }

  .formmain {
    width: 100%;
  }

  .comments-main {
    padding: 5px 16px 12px;
  }

  .comments p {
    font-size: 14px;
  }
}

:global(html.dark) {
  .formmain {
    background: rgb(50, 50, 50);
    border-color: rgba(255, 255, 255, 0.12);
    box-shadow: 0 0 24px rgba(0, 0, 0, 0.45);
  }

  .title3 {
    color: rgb(246, 214, 175);
  }

  .comments {
    background: rgba(90, 90, 90, 0.8);
    border-color: rgba(255, 255, 255, 0.85);
    color: #fff;

    p {
      color: #fff;
    }
  }

  .bottomhr {
    color: #aaa;
  }
}
</style>

<style lang="scss">
.sakura-comment-page {
  width: 100%;
  overflow-x: clip;

  .sakura-one-columns,
  .sakura-triple-columns {
    width: 100%;
    max-width: 100%;
    justify-items: center;
  }

  .sakura-page-content {
    width: 100%;
    max-width: 900px;
    margin-inline: auto;
    overflow: visible;
    display: flex;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;
  }

  .sakura-page-content > * {
    width: 100%;
    max-width: 800px;
    margin-inline: auto;
    box-sizing: border-box;
  }

  main {
    width: 100%;
    overflow: visible;
  }
}
</style>

提一句

留言页面要新建页面,index.md文件如下配置:

text
---
layout: comment
title: 不留下点什么吗
icon: i-ri-chat-1-line
nav: false
cover: https://你的图床.jpg
---

具体怎么创建页面看第一章教程末尾,顺便提一句,页面的访问方法,比如pages文件夹有一个comment文件夹,comment文件夹中有index.md文件,这就是一个页面了,在浏览器打开页面的方式就是:https://你的域名.com/comment