Hexo 本身支持注入功能,可以实现无侵入式调整博客布局。Fluid 支持更优化的注入功能,本文记录 Fluid 代码注入的使用方法,并将背景视频功能转为注入实现。
<head>
和 <body>
节点中。scripts
文件夹,然后在里面任意命名创建一个 js 文件即可。例如创建一个
/blog/scripts/example.js
,内容为:
hexo.extend.injector.register('body_end', '<script src="/jquery.js"></script>', 'default');
上述代码会在生成的页面
</body>
注入加载jquery.js
的代码。
register
函数可接受三个参数,第一个参数是代码片段注入的位置,接受以下值:参数 | 含义 |
---|---|
head_begin | 注入在 <head> 之后(默认) |
head_end | 注入在 </head> 之前 |
body_begin | 注入在 <body> 之后 |
body_end | 注入在 </body> 之前 |
参数 | 含义 |
---|---|
default | 注入到每个页面(默认值) |
home | 只注入到主页(is_home() 为 true 的页面) |
post | 只注入到文章页面(is_post() 为 true 的页面) |
page | 只注入到独立页面(is_page() 为 true 的页面) |
archive | 只注入到归档页面(is_archive() 为 true 的页面) |
category | 只注入到分类页面(is_category() 为 true 的页面) |
tag | 只注入到标签页面(is_tag() 为 true 的页面) |
或是其他自定义 layout 名称,例如在Fluid 主题中
about
对应关于页、links
对应友联页
ejs
代码。ejs
文件一样编写自己的组件再注入进去。scripts
文件夹(如不存在则创建),在里面创建任意名称的 js 文件,在文件中写入如下内容:1234 | hexo.extend.filter.register('theme_inject', function(injects) { injects.header.file('default', 'source/_inject/test1.ejs', { key: 'value' }, -1); injects.footer.raw('default', '<script async src="https://xxxxxx" crossorigin="anonymous"></script>');}); |
---|
header
和 footer
是注入点的名称,表示代码注入到页面的什么位置;file
方法表示注入的是文件,第一个参数下面介绍,第二个参数则是文件的路径,第三个参数是传入文件的参数(可省略),第四个参数是顺序(可省略);raw
方法表示注入的是原生代码,第一个参数下面介绍,第二个参数则是一句原生的 HTML 语句;default
表示注入的键名,可以使用任意键名,同一个注入点下的相同键名会使注入的内容覆盖,而不同键名则会让内容依次排列(默认按执行先后顺序,可通过 file
第四个参数指定),这里 default 为主题默认键名,通常会替换掉主题默认的组件;注入点名称 | 注入范围 | 存在 default 键 |
---|---|---|
head | <head> 标签中的结尾 | 无 |
header | <header> 标签中所有内容 | 有 |
bodyBegin | <body> 标签中的开始 | 无 |
bodyEnd | <body> 标签中的结尾 | 无 |
footer | <footer> 标签中所有内容 | 有 |
postMetaTop | 文章页 <header> 标签中 meta 部分内容 | 有 |
postMetaBottom | 文章页底部 meta 部分内容 | 有 |
postMarkdownBegin | <div class="markdown-body"> 标签中的开始 | 无 |
postMarkdownEnd | <div class="markdown-body"> 标签中的结尾 | 无 |
postLeft | 文章页左侧边栏 | 有 |
postRight | 文章页右侧边栏 | 有 |
postCopyright | 文章页版权信息 | 有 |
postRight | 文章页右侧边栏 | 无 |
postComments | 文章页评论 | 有 |
pageComments | 自定义页评论 | 有 |
linksComments | 友链页评论 | 有 |
header
和 bodybegin
scripts
文件夹,在其中创建 page.js
文件,内容为:hexo.extend.filter.register('theme_inject', function(injects) {
injects.header.file('default', 'source/_inject/test1.ejs', { key: 'value' }, -1);
injects.footer.raw('default', '<script async src="https://xxxxxx" crossorigin="anonymous"></script>');
});
将两个文件嵌入到指定位置,由于 bodybegin 是空的,这里采用覆盖 default 的方式 现在创建注入的两个文件,创建
source/_inject
文件夹,在其中创建文件header.ejs
和bodyBegin.ejs
文件
bodyBegin.ejs
<div>
<div class='real_mask' style="
background-color: rgba(0,0,0,0.3);
width: 100%;
height: 100%;
position: fixed;
z-index: -777;
"></div>
<div id="banner_video_insert">
</div>
<div id='vvd_banner_img'>
</div>
</div>
<div id="banner"></div>
header.js
<%
var banner_video = theme.index.banner_video
var banner_img = page.banner_img || theme.index.banner_img
var banner_img_height = page.banner_img_height || theme.index.banner_img_height
var banner_mask_alpha = page.banner_mask_alpha || theme.index.banner_mask_alpha
%>
<script type="text/javascript" src="/vvd_js/jquery.js"></script>
<div class="banner" id='banner' >
<div class="full-bg-img" >
<% if(banner_video){ %>
<script>
var ua = navigator.userAgent;
var ipad = ua.match(/(iPad).*OS\s([\d_]+)/),
isIphone = !ipad && ua.match(/(iPhone\sOS)\s([\d_]+)/),
isAndroid = ua.match(/(Android)\s+([\d.]+)/),
isMobile = isIphone || isAndroid;
function set_video_attr(id){
var height = document.body.clientHeight
var width = document.body.clientWidth
var video_item = document.getElementById(id);
if (height / width < 0.56){
video_item.setAttribute('width', '100%');
video_item.setAttribute('height', 'auto');
} else {
video_item.setAttribute('height', '100%');
video_item.setAttribute('width', 'auto');
}
}
$.getJSON('/vvd_js/video_url.json', function(data){
if (true){
var video_list_length = data.length
var seed = Math.random()
index = Math.floor(seed * video_list_length)
video_url = data[index][0]
pre_show_image_url = data[index][1]
banner_obj = document.getElementById("banner")
banner_obj.style.cssText = "background: url('" + pre_show_image_url + "') no-repeat; background-size: cover;"
vvd_banner_obj = document.getElementById("vvd_banner_img")
vvd_banner_content = "<img id='banner_img_item' src='" + pre_show_image_url + "' style='height: 100%; position: fixed; z-index: -999'>"
vvd_banner_obj.innerHTML = vvd_banner_content
set_video_attr('banner_img_item')
if (!isMobile) {
video_html_res = "<video id='video_item' style='position: fixed; z-index: -888;' muted='muted' src=" + video_url + " autoplay='autoplay' loop='loop'></video>"
document.getElementById("banner_video_insert").innerHTML = video_html_res;
set_video_attr('video_item')
}
}
});
if (!isMobile){
window.onresize = function(){
set_video_attr('video_item')
}
}
</script>
<% } %>
</div>
</div>
</div>
_config.fluid.yml
1. 覆盖默认 banner 图为纯透明的 png 图像将所有的
#---------------------------
# 首页
# Home Page
#---------------------------
index:
# 首页 Banner 头图,可以是相对路径或绝对路径,以下相同
# Path of Banner image, can be a relative path or an absolute path, the same on other pages
banner_img: https://101.43.39.125/HexoFiles/new/bg-trans.png
# 首页 Banner 使用随机视频
# true 开启 false 关闭
banner_video: true
1. 将所有 `banner_mask_alpha` 设置为 0其余的如