title: Hexo Next为每篇文章设置自定义的banner图片
date: 2019-07-23 13:17:46
tags:
categories:
想完成这样一个功能:
顶部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那一端里面插入:
<script type="text/javascript">
console.log(window.location);
</script>
重启hexo服务器之后可以顺利地在控制台看到输出。
知道了可以直接改动swig文件来往html中插入js之后,一切就都明了了。下面是最终的解决方案。
我们看到post.swig
第一句,说明它扩展于_layout.swig
,仔细看_layout.swig
里面header一段,可以看到它又include了_partials/header.swig
,这就说明了我们改了_layout.swig
就可以覆盖到每种情况了。
首先在class="header-inner"
前面加上id。
<header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
<div id="id-header-inner" class="header-inner"> {%- include '_partials/header.swig' %} div>
header>
然后在下方粘贴上这段代码:
<script type="text/javascript">
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);
script>
这段代码的含义是在本文章的文件夹底下用head模式(只下载文件头,不下载文件内容)寻找名为post-banner.png
的图,如果找到了就用这个图作为背景图,否则使用默认的在/images/background.jpg
背景图。
以后就只需要在每篇文章的目录里面放一张post-banner.png
的图,就可以用作自定义banner图片了。
实际使用的时候把下面的默认背景图改成你自己的默认背景图路径就可以了。
注意,这里使用background-image
属性,不宜直接使用background
属性,这是为了避免覆盖了我在custom.styl
给banner设置的background-size: cover
属性。
支持多个备选图片,所有图片都失败之后再使用默认图片,可用于同时支持png版本和jpg版本。