Fluid -20- 使用 Fluid 注入功能实现背景视频

2022-08-06 09:52:32 浏览数 (1)

Hexo 本身支持注入功能,可以实现无侵入式调整博客布局。Fluid 支持更优化的注入功能,本文记录 Fluid 代码注入的使用方法,并将背景视频功能转为注入实现。

简介

什么是代码注入
  • 在项目之外将需要修改的代码动态插入到项目中的技术手段
为什么需要代码注入
  • 是的,直接修改源码是完全可以达到目的的,但是源码修改会破坏仓库的代码完整性,问题主要出现在需要对仓库进行更新的时候
  • 修改过的仓库很容易在更新时引入冲突,那时候很可能需要面对自己都不记得为什么改的代码和完全不懂的项目代码做出取舍,实在是很危险、痛苦而且不优雅的
  • 也就是说,我们又要调整项目代码功能,又要保持项目足够“干净”,以便享受将来的更新,此时代码注入的价值便显现出来了

注入代码

Hexo 注入
  • Hexo 注入器 是 Hexo 5 版本自身加入的一项新功能,所以在所有 Hexo 主题都是支持这个功能的。
  • 注入器可以将 HTML 片段注入生成页面的 <head><body> 节点中。
  • 编写注入代码,需要在博客的根目录下创建 scripts 文件夹,然后在里面任意命名创建一个 js 文件即可。

例如创建一个 /blog/scripts/example.js,内容为:

代码语言:javascript复制
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 对应友联页

Fluid 注入
  • Fluid 主题也提供了一套注入代码功能,相较于 Hexo 注入功能更细致更丰富,并且支持注入 ejs 代码。
  • 如果你想充分修改主题,又不想直接修改源码影响日后更新,本主题提供了代码注入功能,可以将代码无侵入式加入到主题里。
  • 你可以直接注入 HTML 片段,不过建议你了解一下 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>');});

  • headerfooter 是注入点的名称,表示代码注入到页面的什么位置;
  • 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

友链页评论

动态视频背景注入实现

背景
  • 为了实现动视频态博客背景,之前记录过经验 Fluid -2- 随机视频背景切换 , Fluid -11- 封面视频背景顺滑加载 , Fluid -13- 视频背景 fixed 成功实现对 fluid 主题的侵入式修改
  • 但在升级 fluid 1.9 的时候侵入修改的代价来了,由于主题升级了大版本,代码冲突太多,已经无从维护,现依赖代码注入功能重新实现上述功能
思路
  • fluid 的注入更加灵活,此处选择 fluid 的注入方式
  • 按照流程创建注入环境
  • 创建注入代码文件
  • 将文件嵌入到 headerbodybegin
  • 相应修改主题配置
实现
  1. 在博客根目录创建 scripts 文件夹,在其中创建 page.js 文件,内容为:
代码语言:javascript复制
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.ejsbodyBegin.ejs 文件

  1. bodyBegin.ejs
代码语言:javascript复制
<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>
  1. header.js
代码语言:javascript复制
<%
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).*OSs([d_] )/),
						isIphone = !ipad && ua.match(/(iPhonesOS)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>
  1. 修改主题配置文件 _config.fluid.yml
代码语言:txt复制
1. 覆盖默认 banner 图为纯透明的 png 图像将所有的 
代码语言:javascript复制
#---------------------------
# 首页
# 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://img.yuanmabao.com/zijie/pic/2022/08/06/e4b2f1zpkxt.png
  
  # 首页 Banner 使用随机视频
  # true 开启  false 关闭
  banner_video: true

代码语言:txt复制
1. 将所有 `banner_mask_alpha` 设置为 0其余的如 

参考资料

  • https://hexo.fluid-dev.com/docs/advance/

0 人点赞