Hexo Next为每篇文章设置不同的顶图

小试牛刀

想完成这样一个功能:

顶部banner默认读取images/background.jpg。当进入文章页面的时候,判断文件夹内是否存在header-banner.jpg图片存在,有就优先使用它,否则使用images/background.jpg

之前静态改变banner图是直接在custom.styl里改变.header-inner里的background属性的。

现在要动态改banner图,当然要在javascript中改。

首先我找到了整个宏观布局定义的代码在themes\next\layout\_layout.swig。swig其实可以看做是html的超集(类似于ejs),可以使用各种html属性,当然也就可以在里面插入js代码了。于是我试着往header那一端里面插入:

1
2
3
<script type="text/javascript">
console.log(window.location);
</script>

重启hexo服务器之后可以顺利地在控制台看到输出。

最终解决方案

知道了可以直接改动swig文件来往html中插入js之后,一切就都明了了。下面是最终的解决方案。

增加id

我们进入themes\next\layout\_layout.swig文件。

首先在class="header-inner"前面加上id。

1
2
3
4
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<!-- 添加了id,后面改变css样式用 -->
<div id="id-header-inner" class="header-inner"> {%- include '_partials/header.swig' %} </div>
</header>

新增js代码并调用

再下面一行,粘贴代码:

1
2
3
<!-- 改变css样式 -->
<script type="text/javascript" src="/js/src/bg-beautifier.js"></script>
<script>hexoChangeBanner();</script>

然后我们在themes\next\source\js\src\新建一个文件bg-beautifier.js,把下面这段代码粘进去:

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
function hexoChangeBanner() {
var url = document.location.pathname;
var folderName = url.substr(1, url.length - 2)
console.log(folderName);

var listPostUrl = [
"/" + folderName + "/" + "post-banner.png",
"/" + folderName + "/" + "post-banner.jpg",
];

var nSuccessCount = 0;
var nResponceCount = 0;
function OnHttpResponse(bSuccess, strUrl) {
console.log("OnHttpResponse: " + bSuccess + ", " + strUrl);
nResponceCount++;
if(nSuccessCount > 0){
return;
}
if(bSuccess) {
nSuccessCount++;
document.getElementById("id-header-inner").style.backgroundImage = "url(" + strUrl + ")";
}
if(nResponceCount >= listPostUrl.length && nSuccessCount <= 0){
// 使用默认图
document.getElementById("id-header-inner").style.backgroundImage = "url(/images/background.jpg)";
}
}

function changeBanner(strPostUrl, nIndex){
console.log("try to load" + strPostUrl);
var xmlhttp;
if (window.XMLHttpRequest)
{
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xmlhttp=new XMLHttpRequest();
}
else
{
// IE6, IE5 浏览器执行代码
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange=function()
{
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
OnHttpResponse(true, strPostUrl);
} else {
OnHttpResponse(false, strPostUrl);
}
}
xmlhttp.open("HEAD",strPostUrl,true);
xmlhttp.send();
}

listPostUrl.forEach(changeBanner);
}

这段代码的含义是在本文章的文件夹底下用head模式(只下载文件头,不下载文件内容)寻找名为post-banner.png的图,如果找到了就用这个图作为背景图,否则使用默认的在/images/background.jpg背景图。

以后就只需要在每篇文章的目录里面放一张post-banner.png的图,就可以用作自定义banner图片了。

实际使用的时候把下面的默认背景图改成你自己的默认背景图路径就可以了。

注意,这里使用background-image属性,不宜直接使用background属性,这是为了避免覆盖了我在custom.styl给banner设置的background-size: cover属性。

支持多个备选图片,所有图片都失败之后再使用默认图片,可用于同时支持png版本和jpg版本。

增加对js代码的引用

最后,我们打开themes\next\layout\_scripts\commons.swig,新增对刚刚新增js代码的引用:

1
2
3
4
5
6
7
{%
set js_commons = [
'src/utils.js',
'src/motion.js',
+ 'src/bg-beautifier.js',
]
%}

把header变大

进入到themes\next\source\css\_common\outline\outline.styl,修改header为:

1
2
3
4
5
6
7
8
9
10
11
12
// Header Section
// --------------------------------------------------
.header-inner {
margin: 0 auto;
padding: 100px 0 70px;
width: 100%;
height: 400px;

+desktop-large() {
.container & { width: 100%; height: 400px; }
}
}
Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//