前言
有一天上Github
看代码的时候,发现了一个有趣的网站:Volarjs的官网,可以看到他们首页的title不仅有渐变色,而且有一个动画效果,我们来尝试在我们的vitepress
工程中也实现这个效果
通过阅读本文章,你可以学会在使用pnpm
的时候,如何通过pnpm patch
命令修改源码内容
基本实现
我们可以通过以下demo来预先实现这个效果
可以看到,实现这个效果其实并不难,只需要文字部分的样式中添加以下代码:
#app {
background: -webkit-linear-gradient(315deg, rgb(210, 86, 53) 10%, #647eff 50%, rgb(238, 224, 112) 90%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400% 400%;
animation: gradient 10s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
在vitepress中实现
根据我之前的文章:vitepress趣玩系列——首页内容优化,我们可以使用插槽的方式,在文档中插入我们想要展示的组件,所以我们先实现一个带有这种动画效果的组件
在工程中的.vitepress/components
下新建组件AnimationTitle.vue
<script setup lang="ts"></script>
<template>
<div class="title">Vitepress Fun Animation Title</div>
</template>
<style scoped>
.title {
font-size: 48px;
line-height: 48px;
text-align: center;
margin-top: 20px;
background: -webkit-linear-gradient(
315deg,
rgb(210, 86, 53) 10%,
#647eff 50%,
rgb(238, 224, 112) 90%
);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400% 400%;
animation: gradient 5s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
</style>
然后在.vitepress/theme/index.ts
中使用插槽,通过查阅源码,找到合适的插槽位置:home-hero-after
import Theme from "vitepress/theme";
import "./style/var.css";
import { h } from "vue";
+ import AnimationTitle from "../components/AnimationTitle.vue";
export default {
...Theme,
Layout() {
return h(Theme.Layout, null, {
+ "home-features-after": () => h(AnimationTitle),
});
},
enhanceApp({ app }) {},
};
最终效果如下
进阶vitepress实现
通过插槽我们可以在文档中的预留位置使用我们的自定义组件,但如果我们希望修改首页图片隔壁的Title样式,也有渐变动画,我们要怎么做呢
首先我们想到的是通过插槽的方式,但通过查阅源码,发现这块并没有预留插槽,只有Hero
的上下部分预留了插槽,分别叫home-hero-before
和home-hero-after
,使用一下插槽看看效果
import Theme from "vitepress/theme";
import "./style/var.css";
import { h } from "vue";
import AnimationTitle from "../components/AnimationTitle.vue";
export default {
...Theme,
Layout() {
return h(Theme.Layout, null, {
+ "home-hero-before": () => h(AnimationTitle),
+ "home-hero-after": () => h(AnimationTitle),
"home-features-after": () => h(AnimationTitle),
});
},
enhanceApp({ app }) {},
};
- 方案一,我们不使用首页的
Hero
,通过插槽home-hero-before
来传入我们的自定义Hero
,效果如下
这种方法虽然确实能实现我们想要的效果,但同时我们也要实现图片和按钮组件来完善首页
- 方案二,修改源码,在title部分添加我们需要的插槽
这方法听着挺硬核,但实现起来其实并不难
一般我们想通过修改依赖来进行打补丁操作,都会首先想到patch-package
这个包,但由于我这里使用的是pnpm
,在patch-package
包的npm文档中能看到,pnpm
原生支持这个操作,所以并不需要额外引入工具包
关于pnpm patch
的使用方法,官方文档中有详细介绍使用方法,我们先来实操
首先在工程控制台中执行命令
pnpm patch vitepress@1.0.0-alpha.45
这时候会输出如下
执行这个命令,会创建一个临时工程,我们通过修改这个工程来实现修改依赖的效果,该工程可以通过vscode
来打开,在控制台中直接点击生成的路径就能用vscode
直接打开临时目录
可以看到跟vitepress
源码并没区别
接下来我们打开临时目录,来修改代码,这里我只贴出关键部分,剩下的会在文章最后说明
这部分就是标题部分的代码
在这部分添加一个插槽home-hero-info
,这样我们就能通过插槽的方式来修改标题使用自定义组件
代码修改好保存后,我们执行如下命令,用于保存补丁
pnpm patch-commit 临时目录路径
这样在你的工程中就会生成一个目录patches
,用来保存修改的内容
并且package.json
也会添加这部分内容
这样在你每次拉取工程安装依赖的时候,都会执行这部分命令,修改依赖内容
现在我们来试下新增的插槽home-hero-info
,修改我们的AnimationTitle.vue
组件
<script setup lang="ts"></script>
<template>
<h1 class="name">
<span class="clip">VitePress-Fun</span>
</h1>
<p class="text">VitePress趣玩系列</p>
<p class="tagline">Lorem ipsum...</p>
</template>
<style scoped>
.name {
background: -webkit-linear-gradient(
315deg,
rgb(210, 86, 53) 10%,
#647eff 50%,
rgb(238, 224, 112) 90%
);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-size: 400% 400%;
animation: gradient 5s ease infinite;
}
@keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.name,
.text {
max-width: 392px;
letter-spacing: -0.4px;
line-height: 40px;
font-size: 32px;
font-weight: 700;
white-space: pre-wrap;
}
@media (min-width: 640px) {
.name,
.text {
max-width: 576px;
line-height: 56px;
font-size: 48px;
}
}
@media (min-width: 960px) {
.name,
.text {
line-height: 64px;
font-size: 56px;
}
}
.tagline {
padding-top: 8px;
max-width: 392px;
line-height: 28px;
font-size: 18px;
font-weight: 500;
white-space: pre-wrap;
color: var(--vp-c-text-2);
}
@media (min-width: 640px) {
.tagline {
padding-top: 12px;
max-width: 576px;
line-height: 32px;
font-size: 20px;
}
}
@media (min-width: 960px) {
.tagline {
line-height: 36px;
font-size: 24px;
}
}
</style>
然后使用插槽
import Theme from "vitepress/theme";
import "./style/var.css";
import { h } from "vue";
import AnimationTitle from "../components/AnimationTitle.vue";
export default {
...Theme,
Layout() {
return h(Theme.Layout, null, {
+ "home-hero-info": () => h(AnimationTitle),
});
},
enhanceApp({ app }) {},
};
现在我们来看下效果
现在我们就能实现标题部分有渐变动画的效果了
后记
其实这篇文章在一个月前就想写了,因为看到Volarjs
的官网后灵感浮现,也想自己实现一个类似的效果,但无奈vitepress
官方并不支持修改标题,也就是不在这个位置预留插槽位,我本来也是跟Volarjs
文档一样,想自己重写一个Home
组件,无奈实在是太懒了,于是我就给官方提了个PR,希望他们能正式支持这个插槽,点击这里可以看到我3周前提的PR
但等了好久,官方始终不合这个PR,可能官方并不希望这个位置能被修改吧
完整的插槽修改方式代码可以查看我提的PR里的修改内容,其实添加一个插槽并不难,各位可以通过这个方法,来实现自己想要的效果