Fluid -11- 封面视频背景顺滑加载

本文最后更新于:2022年8月10日 上午

Fluid -2- 随机视频背景切换 中记录了 Fluid 主题背景随机切换的实现方法,但存在加载视频覆盖原始图像背景的情况,本文记录顺滑加载解决方案 。

当前问题

  • 当前问题为背景图像加载较快,视频稍慢
  • 导致背景加载时会有先出现图像,再覆盖另一个视频的尴尬场景

解决思路

放弃图像加载

  • 放弃图像加载是一种解决方案,这样就只会加载视频,没有图像的闪动
  • 但手机端需要加载图像,不能放弃图像背景
  • 更重要的原因是图像加载快,用户可以更早地感受到网页在加载
  • 因此不能放弃加载图像

加载更小的视频第一帧图像

  • 又需要图像,同时又让视频覆盖起来顺滑
  • 于是就有了使用视频第一帧图像作为背景图像加载的思路

实现思路

  • 实现思路为在加载视频路径json时顺带加载相应的第一帧图像
  • 动态替换原始背景的 style background 链接地址,实现顺滑加载
  • 该方案不会影响手机端的原始背景图像正常加载

解决方案

实现动态背景视频加载

获取视频图像第一帧

保存质量可以低一些,使得图像文件小,更快加载

  • 上传图像,获取和视频对应的图像链接

修改 video_url.json

  • 修改 video_url.json 文件

  • 之前的视频链接改为 [视频链接, 图像链接]

  • 示例:

1
2
3
"https://101.43.39.125/HexoFiles/vvd-dell-2021-win-10/20210808220318.mp4"
# 改为
["https://101.43.39.125/HexoFiles/vvd-dell-2021-win-10/20210808220318.mp4", "https://101.43.39.125/HexoFiles/vvd-dell-2021-win-10/20210808220318.jpg"]

修改 layout.ejs 文件

  • 修改 Hexo -> themes -> fluid -> layout -> layout.ejs文件:

  • 将之前的 <% if(banner_video){ %> 段改为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<% 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.children[0].clientHeight
var width = document.body.children[0].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 (!isMobile){
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;"

video_html_res = "<video id='video_item' style='position: absolute;' 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>
<% } %>
  • 完整的 layout.ejs 文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<%
var subtitle = page.subtitle || page.title
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
var colorSchema = theme.dark_mode && theme.dark_mode.enable && theme.dark_mode.default ? theme.dark_mode.default : ''
var banner_video = theme.index.banner_video
%>

<!DOCTYPE html>

<html lang="<%= config.language %>" <%= colorSchema ? `data-default-color-scheme=${colorSchema}` : '' %>>
<script type="text/javascript" src="/vvd_js/jquery.js"></script>

<%- partial('_partial/head') %>

<body>

<header style="height: <%- banner_img_height %>vh;">
<%- partial('_partial/nav') %>

<div class="banner" id="banner" <%- theme.banner && theme.banner.parallax && 'parallax=true' %>
style="background: url('<%- url_for(banner_img) %>') no-repeat center center;
background-size: cover;">

<div class="full-bg-img" >
<div id="banner_video_insert">
</div>
<% 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.children[0].clientHeight
var width = document.body.children[0].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 (!isMobile){
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;"

video_html_res = "<video id='video_item' style='position: absolute;' 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 class="mask flex-center" style="background-color: rgba(0, 0, 0, <%= parseFloat(banner_mask_alpha) %>)">
<div class="page-header text-center fade-in-up">
<span class="h2" id="subtitle" title="<%= subtitle %>">
<% if(!theme.fun_features.typing.enable) { %>
<%- subtitle %>
<% } %>
</span>

<% if(is_post() && page.meta !== false) { %>
<%- partial('_partial/post-meta') %>
<% } %>
</div>

<% if (theme.scroll_down_arrow.enable && theme.scroll_down_arrow.banner_height_limit <= banner_img_height && page.layout !== '404') { %>
<div class="scroll-down-bar">
<i class="iconfont icon-arrowdown"></i>
</div>
<% } %>
</div>
</div>
</div>
</header>

<main>
<% if(is_post() || page.layout === '404') { %>
<%- body %>
<% } else { %>
<div class="container nopadding-x-md">
<div class="py-5" id="board"
<%- banner_img_height >= 100 && theme.banner && theme.banner.parallax ? 'style=margin-top:0' : '' %>>
<% if(page.layout === 'about') { %>
<div class="about-avatar">
<img src="<%= url_for(theme.about.avatar) %>"
class="img-fluid" alt="avatar">
</div>
<% } %>
<div class="container">
<div class="row">
<div class="col-12 col-md-10 m-auto">
<%- body %>
</div>
</div>
</div>
</div>
</div>
<% } %>

<% if (theme.scroll_top_arrow.enable) { %>
<a id="scroll-top-button" aria-label="TOP" href="#" role="button">
<i class="iconfont icon-arrowup" aria-hidden="true"></i>
</a>
<% } %>

<% if (theme.search.enable) { %>
<%- partial('_partial/search') %>
<% } %>

<% if (theme.custom_html) { %>
<div class="col-lg-7 mx-auto nopadding-x-md">
<div class="container custom mx-auto">
<%- theme.custom_html %>
</div>
</div>
<% } %>
</main>

<%- partial('_partial/footer', { params: { subtitle: subtitle } }) %>

<!-- SCRIPTS -->
<%- partial('_partial/scripts') %>

</body>
</html>

效果展示

参考资料


Fluid -11- 封面视频背景顺滑加载
https://www.zywvvd.com/notes/hexo/theme/fluid/fluid-smooth-video-load/fluid-smooth-video-load/
作者
Yiwei Zhang
发布于
2021年9月16日
许可协议