本文章首发于语雀! 通过各种高科技功能同步到Hajeekn 的博客 由于每个人的博客目录都不相同,这里博客目录使用%brt%代替 本文章除 Pace wowjs 普通引入法以外,其他魔改都不适合 Butterfly3.6.0 及以上
通过 wowjs 给博客添加好看的样式
基础样式篇
- 1.创建 JS
前往%brt%themesbutterflysourcejs
新建一个 js,名称为wow-init.js
其 JS 内部写入如下内容
wow = new WOW({
boxClass: "wow",
// 用户滚动时显示隐藏框的类名称(可以自行配置)
animateClass: "animate__animated",
// 触发 CSS 动画的类名称(动画库默认为"animate.css"库)(可以自行配置)
offset: 0,
// 定义浏览器视口底部与隐藏框顶部之间的距离。
// 当用户滚动并到达此距离时,将显示隐藏的框。
// 可以自行配置
live: true,
// 在页面上检查新的 wow.js元素。
});
wow.init();
如果您觉得不想出现注释,也可以删掉注释。
- 2.前往
%brt%themesbutterflylayoutincludesthird-party
目录,新建一个名为wow-js.pug
的文件
其文件内部写入如下代码:
代码语言:javascript复制.pjax-reload
if theme.wowjs.animateitem
each item in theme.wowjs.animateitem
script(async).
var arr = document.getElementsByClassName('!{item.class}');
for(var i = 0;i<arr.length;i ){
arr[i].classList.add('wow');
arr[i].classList.add('!{item.style}');
arr[i].setAttribute('data-wow-duration', '!{item.duration}');
arr[i].setAttribute('data-wow-delay', '!{item.delay}');
arr[i].setAttribute('data-wow-offset', '!{item.offset}');
arr[i].setAttribute('data-wow-iteration', '!{item.iteration}');
}
script(defer src=url_for(theme.CDN.wowjs))
script(defer src=url_for(theme.CDN.wowjs_init))
- 3.修改
%brt%themesbutterflylayoutincludeshead.pug
的内容
在 //- font 的配置下 //- global config 的配置上的空白部分写入以下代码(请直接复制粘贴,避免出现缩进错误 ❌)
代码语言:javascript复制//- animate_css
if theme.wowjs.enable
link(rel='stylesheet' href=url_for(theme.CDN.animate_css) media="print" onload="this.media='all'")
- 4.修改
%brt&themesbutterflylayoutincludesadditional-js.pug
文件内部的内容
在 if theme.pjax.enable 配置大项的 baidu-push 小项下写入一下代码(请直接复制粘贴,避免出现缩进错误 ❌) V3.4.0 以下(不包括 3.4.0): 将其中的
代码语言:javascript复制$('script[data-pjax]').each(function () {
删除,并修改为:
代码语言:javascript复制$("script[data-pjax], .pjax-reload script").each(function () {
$(this).parent().append($(this).remove());
});
V3.4.0 以上(包括 3.4.0): 找到
代码语言:javascript复制document.querySelectorAll('script[data-pjax]').forEach(item => {
删除它,并写入以下代码(请直接复制粘贴,避免缩进错误 ❌)
代码语言:javascript复制document
.querySelectorAll("script[data-pjax], .pjax-reload script")
.forEach((item) => {
const newScript = document.createElement("script");
const content = item.text || item.textContent || item.innerHTML || "";
Array.from(item.attributes).forEach((attr) =>
newScript.setAttribute(attr.name, attr.value)
);
newScript.appendChild(document.createTextNode(content));
item.parentNode.replaceChild(newScript, item);
});
- 5.修改
%brt%config%_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视)
找到 CDN 配置项 在
代码语言:javascript复制utils: /js/utils.js
的配置项下添加 wowjs、wowjs-init、animate 的库(请直接复制粘贴以下代码,避免格式缩进导致的错误 ❌)
代码语言:javascript复制wowjs: https://cdn.jsdelivr.net/gh/graingert/[email protected]/dist/wow.min.js
wowjs_init: /js/wow_init.js
animate_css: https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css
- 6.修改
%brt%config%_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视)
在该配置文件内部添加 wow 的开关,其中 class 和 style 配置为必填项
代码语言:javascript复制wowjs:
enable: true #控制动画开关。true是打开,false是关闭
animateitem:
- class: recent-post-item #必填项,需要添加动画的元素的class
style: animate__zoomIn #必填项,需要添加的动画
duration: 3s #选填项,动画持续时间,单位可以是ms也可以是s。例如3s,700ms。
delay: 1s #选填项,动画开始的延迟时间,单位可以是ms也可以是s。例如3s,700ms。
offset: 100 #选填项,开始动画的距离(相对浏览器底部)
iteration: 2 #选填项,动画重复的次数
- class: CoolButton
style: animate__zoomIn
运行hexo clean && hexo g
后方可看到效果,更多 animate 动画样式可查看animate 官方文档
浮动样式篇
浮动样式篇参考Aklilar大佬的文章给博客元素添加浮动特效和洪哥的博客效果
- 1.前往
%brt%themesbutterflysourcejs
目录,新建一个名为floatpanel.js
的文件
在内部写入以下代码:
代码语言:javascript复制var ANGLE = 45; //控制浮动角度,数值越大,浮动幅度越大。
var panel = document.getElementsByClassName("wowpanels");
for (var i = 0; i < panel.length; i ) {
floatable(panel[i]);
}
function floatable(content) {
content.addEventListener("mouseout", (e) => {
content.style.transform = `perspective(300px)
rotateX(0deg)
rotateY(0deg)
rotateZ(0deg)`;
});
content.addEventListener("mousemove", (e) => {
var w = content.clientWidth;
var h = content.clientHeight;
var y = ((e.offsetX - w * 0.5) / w) * ANGLE;
var x = ((1 - (e.offsetY - h * 0.5)) / h) * ANGLE;
content.style.transform = `perspective(300px)
rotateX(${x}deg)
rotateY(${y}deg)`;
});
}
- 2.修改
%brt%config%_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视)
在 inject 大项的 bottom 小项中添加 script 引入项:
代码语言:javascript复制- <script async data-pjax src="/js/floatpanel.js"></script>
- 3.给你想要特效的类元素添加 wowpanels 属性,修改 floatpanel.js 的代码如下:
// 新增的内容
var arr = document.getElementsByClassName('element-class');
//把element-class替换成你想要添加特效的元素的类名
for(var i = 0;i<arr.length;i ){
arr[i].classList.add('wowpanels');
}
// 原来的内容
var ANGLE = 45; //控制浮动角度,数值越大,浮动幅度越大。
var panel= document.getElementsByClassName('wowpanels');
for(var i = 0;i<panel.length;i ){
floatable(panel[i]);
}
function floatable (content) {
content.addEventListener('mouseout', e => {
content.style.transform = `perspective(300px)
rotateX(0deg)
rotateY(0deg)
rotateZ(0deg)`;
});
content.addEventListener('mousemove', e => {
var w = content.clientWidth;
var h = content.clientHeight;
var y = (e.offsetX - w * 0.5) / w * ANGLE;
var x = (1 - (e.offsetY - h * 0.5)) / h * ANGLE;
content.style.transform = `perspective(300px)
rotateX(${x}deg)
rotateY(${y}deg)`;
});
}
当你完成了基础样式篇时,其实你可以直接将浮动效果看成一个动画样式 在之前的配置下直接添加以下配置项:
代码语言:javascript复制- class: #你想要更改的class类名
style: wowpanels
添加完成后 wowjs 的配置项应该与下面的截图类似
如果报错,请检查你的配置缩进是否正确 ✔,这里博主推荐使用微软爸爸出品的 VSC 编辑对于缩进格式邀请很强的文件格式 以下代码供您用来参考:
代码语言:javascript复制# wowjs
wowjs:
enable: true #控制动画开关。true是打开,false是关闭
animateitem:
- class: recent-post-item #必填项,需要添加动画的元素的class
style: animate__zoomIn #必填项,需要添加的动画
duration: 3s #选填项,动画持续时间,单位可以是ms也可以是s。例如3s,700ms。
delay: 0.5s #选填项,动画开始的延迟时间,单位可以是ms也可以是s。例如3s,700ms。
offset: 100 #选填项,开始动画的距离(相对浏览器底部)
iteration: 1 #选填项,动画重复的次数
- class: card-widget #必填项,需要添加动画的元素的class
style: animate__zoomInUp #必填项,需要添加的动画
duration: 3s #选填项,动画持续时间,单位可以是ms也可以是s。例如3s,700ms。
delay: 0.5s #选填项,动画开始的延迟时间,单位可以是ms也可以是s。例如3s,700ms。
offset: 100 #选填项,开始动画的距离(相对浏览器底部)
iteration: 1 #选填项,动画重复的次数
- class: layout hide-aside #必填项,需要添加动画的元素的class
style: animate__flipInY #必填项,需要添加的动画
duration: 3s #选填项,动画持续时间,单位可以是ms也可以是s。例如3s,700ms。
delay: 0.5s #选填项,动画开始的延迟时间,单位可以是ms也可以是s。例如3s,700ms。
offset: 100 #选填项,开始动画的距离(相对浏览器底部)
iteration: 1 #选填项,动画重复的次数
- class: CoolButton
style: wowpanels
如果您想让动画更滑丝滑流畅,可以新建 css,在内部写入以下代码:
代码语言:javascript复制.wowpanels {
transition: all 0.4s cubic-bezier(0.39, 0.575, 0.565, 1);
}
添加 BiliBili 同款的动态 Banner
由于每个人的博客目录都不相同,这里博客目录使用%brt%代替
下载Bilibili的Banner
- 1.前往
%brt%themesbutterflylayoutincludesheader
新建一个名为bilibili-banner.pug
的文件
在其内部写入
代码语言:javascript复制if (!is_home())
- var banner_style = (typeof(page.bilibili_banner) != "undefined" && page.bilibili_banner!=null) ? page.bilibili_banner : theme.bilibili_banner.style
if (banner_style === 'autumn')
#autumnBanner
div
img(src='/bilibiliBanner/autumn/bilibili-autumn-1.png')
div
img(src='/bilibiliBanner/autumn/bilibili-autumn-2.png')
div
img(src='/bilibiliBanner/autumn/bilibili-autumn-3.png')
div
img(src='/bilibiliBanner/autumn/bilibili-autumn-4.png')
div
img(src='/bilibiliBanner/autumn/bilibili-autumn-5.png')
div
img(src='/bilibiliBanner/autumn/bilibili-autumn-6.png')
else if (banner_style === 'winter')
#winterBanner
.view
img.morning(src='/bilibiliBanner/winter/bilibili-winter-view-1.png' alt='')
img.afternoon(src='/bilibiliBanner/winter/bilibili-winter-view-2.png' alt='')
video.evening(autoplay='' loop='' muted='')
source(src='/bilibiliBanner/winter/bilibili-winter-view-3.webm' type='video/webm')
img.window-cover(src='/bilibiliBanner/winter/bilibili-winter-view-3-snow.png' alt='')
.tree
img.morning(src='/bilibiliBanner/winter/bilibili-winter-tree-1.png' alt='')
img.afternoon(src='/bilibiliBanner/winter/bilibili-winter-tree-2.png' alt='')
img.evening(src='/bilibiliBanner/winter/bilibili-winter-tree-3.png' alt='')
script(async data-pjax src=url_for(theme.CDN.bilibili_banner))
- 2.前往
%brt%themesbutterflysourcecss
新建一个名为bilibiliBanner.css
的文件
在其内部写入以下代码:
代码语言:javascript复制/* autumnBanner */
@media screen and (max-width: 1000px) {
#autumnBanner {
display: none !important;
}
}
#autumnBanner {
height: 100%;
position: relative;
overflow: hidden;
filter: brightness(70%);
}
#autumnBanner > div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
--offset: 0px;
--blur: 2px;
}
#autumnBanner > div > img {
display: block;
width: 110%;
height: 100%;
object-fit: cover;
transform: translatex(var(--offset));
filter: blur(var(--blur));
}
/* winterBanner */
@media screen and (max-width: 1000px) {
#winterBanner {
display: none !important;
}
}
#winterBanner {
height: 100%;
position: relative;
width: 100%;
overflow: hidden;
--percentage: 0.5;
}
#winterBanner .view,
#winterBanner .tree {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: flex;
justify-content: center;
align-items: center;
}
#winterBanner img,
#winterBanner video {
position: absolute;
display: block;
max-width: 120% !important;
width: 120% !important;
height: 100%;
object-fit: cover;
filter: brightness(70%);
}
#winterBanner .morning {
z-index: 20;
opacity: calc(1 - (var(--percentage) - 0.25) / 0.25);
}
#winterBanner .afternoon {
z-index: 10;
opacity: calc(1 - (var(--percentage) - 0.5) / 0.5);
}
#winterBanner .view {
transform: translatex(calc(var(--percentage) * 100px));
}
#winterBanner .tree {
transform: translatex(calc(var(--percentage) * 50px));
filter: blur(3px);
}
#winterBanner .view,
#winterBanner .tree,
#winterBanner .morning,
#winterBanner .afternoon {
transition: 0.2s all ease-in;
}
#winterBanner.moving .view,
#winterBanner.moving .tree,
#winterBanner.moving .morning,
#winterBanner.moving .afternoon {
transition: none;
}
#winterBanner .window-cover {
opacity: calc((var(--percentage) - 0.9) / 0.1);
}
- 3.前往
%brt%themesbutterflysourcejs
新建一个名为bilibili-banner.js
的文件
在其内部写入以下代码
代码语言:javascript复制//autumn_banner
var autumnBanner = document.querySelector("#autumnBanner");
if (autumnBanner) {
var images = document.querySelectorAll("#autumnBanner > div > img");
autumnBanner.addEventListener("mousemove", (e) => {
let percentage = e.clientX / window.outerWidth;
let offset = 10 * percentage;
let blur = 20;
for (let [index, image] of images.entries()) {
offset *= 1.3;
let blurValue = Math.pow(index / images.length - percentage, 2) * blur;
image.style.setProperty("--offset", `${offset}px`);
image.style.setProperty("--blur", `${blurValue}px`);
}
});
}
//winter_banner
var winterBanner = document.querySelector("#winterBanner");
if (winterBanner) {
var startingPoint;
winterBanner.addEventListener("mouseenter", (e) => {
startingPoint = e.clientX;
winterBanner.classList.add("moving");
});
winterBanner.addEventListener("mouseout", (e) => {
winterBanner.classList.remove("moving");
winterBanner.style.setProperty("--percentage", 0.5);
});
winterBanner.addEventListener("mousemove", (e) => {
let percentage = (e.clientX - startingPoint) / window.outerWidth 0.5;
winterBanner.style.setProperty("--percentage", percentage);
});
}
- 4.在主题的 source 文件夹下新建
bilibiliBanner
文件夹,将我所提供的资源解压,直接放入进去(里面一定只有两个目录) - 5.进入
%brt%themesbutterflylayoutincludesheader
文件夹,找到index.pug
在内部注入 bilibili_banner 组件
在 include ./nav.pug 配置下 if is_post()配置上添加以下配置(请直接复制粘贴,避免代码缩进导致的错误 ❌)
代码语言:javascript复制- var bilibili_banner = (typeof(page.bilibili_banner) != "undefined" && page.bilibili_banner!=null) ? page.bilibili_banner : theme.bilibili_banner.enable
if (bilibili_banner)
include ./bilibili-banner.pug
- 6.修改
%brt%config%_config.butterfly.yml
(请将%config%替换为你主题配置文件的位置,如果在根目录请无视)
找到 CDN 配置,在 utils: /js/utils.js 配置的后面添加以下配置
代码语言:javascript复制bilibili_banner: /js/bilibili-banner.js
- 添加
_**css**_
配置项。此处使用了异步加载,同时做了媒体选择,对手机是不会生效的。因为手机的_**banner**_
高度会导致适配效果很差。
我们找到 inject 配置大项的 head 小项,在其内部添加以下配置:
代码语言:javascript复制- <link rel="stylesheet" href="/css/bilibiliBanner.css" media="defer" onload="this.media='screen'">
- 7.添加控制开关
在 butterfly 主题配置中添加以下配置:
代码语言:javascript复制# banner样式
bilibili_banner:
enable: true # 开关banner
style: winter # autumn 秋季样式 ;winter 冬季样式
- 除了在主题配置文件通过配置
bilibili_banner:
的默认项,还可以在每个页面的markdown
文件中通过front-matter
控制单页配置。提供了三个选项: false
: 关闭该页面的动态banner
显示autumn
: 开启该页面的动态banner
,并设置主题为秋季winter
: 开启该页面的动态banner
,并设置主题为冬季 页面配置项优先级高于主题配置
悬停左上角时在网站顶部中间位置会出现描述
- 1.进入
%brt%themesbutterflylayoutincludesheader
修改名为nav.pug
的文件
找到
代码语言:javascript复制span#blog_name
a#site-name(href=url_for('/')) #[=config.title]
将它们删除,并替换为以下代码(请直接复制粘贴,避免缩进错误 ❌):
代码语言:javascript复制- var pagedescr = (typeof(page.description) != "undefined" && page.description!=null) ? page.description : '欢迎您来到了Hajeekn的小木屋呢,不过看起来有点漏水