博客主题配置
博客也写了三年多了,一共用了三个主题,这里记录下碰到的问题以及相关主题优化,防止之后再换主题时碰到相同问题。
参考资料:
- https://blog.eurkon.com/post/61763977.html
- https://butterfly.js.org/posts/ea33ab97/#%E4%BE%8B%E5%AD%90
备注:
所有npm命令均在博客根目录下进行。
next
使用时间:2018/3 -> 2021/1
链接:https://github.com/theme-next/hexo-theme-next
第一款使用的主题,选择的原因是简洁加上使用者多,总体来说体验很好,不过当时一个数学公式显示的bug调了我半年,最后更换主题的原因是感觉过于简洁。
matery
使用时间:2021/1 -> 2021/6
链接:https://github.com/blinkfox/hexo-theme-matery
第二款使用的主题,确实比next好看不少,有一些方面有点小bug。
butterfly
使用时间:2021/6 -> 至今
链接:https://github.com/jerryc127/hexo-theme-butterfly
到目前为止碰到的最好看的主题,而且个性化配置较多,使用下来bug比较少,所以选择了这款,后续会记录下配置相关。
待配置项
- ☐ 文章封面。
- ☐ 主页以外的顶部图配置。
- ☐ 增加友链。
- ☐ 网站副标题。
- ☐ 标签外挂。
- ☐ pwa
- ☐ hexo-submit-urls-to-search-engine持续集成配置。
- ☐ 补充书籍,游戏相关信息
- ☐ 阅读排行榜。
- ☑ 全球访问统计。
- ☑ 文章日历以及雷达图。
- ☐ 研究matery的图标生成方式。
- themes\hexo-theme-matery\layout_widget
- ☐ 判断博客是否被搜索引擎收录。
问题
- ☐ 来必力评论缺失,目前只能显示https://doraemonzzz.com/about/
基本配置
menu
menu:
# 中文
首页: / || fas fa-home
时间轴: /archives/ || fas fa-archive
标签: /tags/ || fas fa-tags
分类: /categories/ || fas fa-folder-open
博客统计||fas fa-chart-pie:
文章统计: /charts/ || far fa-chart-bar
访问统计: /census/ || fas fa-chart-area
阅读排行榜: /top/ || fab fa-hotjar
娱乐||fa fa-heartbeat:
电影: /movies/ || fas fa-video
关于我: /about/ || fas fa-heart
大部分都是基本的,这里介绍下博客统计以及阅读排行榜的配置。
博客统计
安装cheerio:
npm i cheerio --save
文章统计
参考资料:
https://blog.eurkon.com/post/1213ef82.html
https://blog.csdn.net/kebi007/article/details/68488694
https://stackoverflow.com/questions/32734591/pie-chart-overlaps-with-legends
https://cndrew.cn/2020/03/03/calender/#%E5%88%86%E7%B1%BB%E9%9B%B7%E8%BE%BE%E5%9B%BE
https://github.com/blinkfox/hexo-theme-matery
添加了日历以及雷达图,并对第一份资料做了一些微调,保证标签能完全显示。
路径:
blog\source\census\index.md:
内容:
---
title: 文章统计
date: 2021-06-09 02:04:50
---
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/dist/echarts.min.js"></script>
<!-- 文章发布日历 -->
<div id="post-calendar" style="border-radius: 8px; height: 250px; padding: 10px;"></div>
<!-- 文章发布时间统计图 -->
<div id="posts-chart" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 文章标签统计图 -->
<div id="tags-chart" data-length="10" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 文章分类统计图 -->
<div id="categories-chart" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 文章分类雷达图 -->
<div id="categories-radar" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
新建的文件路径:
\blog\themes\butterfly\scripts\helpers\charts.js
在tagsChart中添加如下内容,
+ grid: {
+ left: '10%',
+ bottom:'25%'
+ },
最后得到:
function tagsChart (len) {
const tagArr = []
hexo.locals.get('tags').map(function (tag) {
tagArr.push({ name: tag.name, value: tag.length })
})
tagArr.sort((a, b) => { return b.value - a.value })
let dataLength = Math.min(tagArr.length, len) || tagArr.length
const tagNameArr = []
const tagCountArr = []
for (let i = 0; i < dataLength; i++) {
tagNameArr.push(tagArr[i].name)
tagCountArr.push(tagArr[i].value)
}
const tagNameArrJson = JSON.stringify(tagNameArr)
const tagCountArrJson = JSON.stringify(tagCountArr)
return `
<script id="tagsChart">
var color = '#000'
var tagsChart = echarts.init(document.getElementById('tags-chart'), 'light');
var tagsOption = {
textStyle: {
color: color
},
title: {
text: 'Top ${dataLength} 标签统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {},
xAxis: {
name: '标签',
type: 'category',
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
axisLabel: {
interval:0,
rotate:20
},
grid: {
left: '10%',
bottom:'25%'
},
data: ${tagNameArrJson}
},
yAxis: {
name: '文章篇数',
type: 'value',
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '文章篇数',
type: 'bar',
data: ${tagCountArrJson},
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
emphasis: {
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 195)'
},
{
offset: 1,
color: 'rgba(1, 211, 255)'
}])
}
},
markLine: {
data: [{
name: '平均值',
type: 'average'
}]
}
}]
};
tagsChart.setOption(tagsOption);
window.addEventListener("resize", () => {
tagsChart.resize();
});
</script>`
}
修改categoriesChart,删除lengend的原因是我的标签较多,图表会产生重叠:
+ showLegendSymbol: false,
- legend: {
- top: 'bottom',
- textStyle: {
- color: color
- }
- },
文章日历
代码修改自matery主题,路径为
hexo-theme-matery\layout\_widget
新增的文件路径:
\blog\themes\butterfly\scripts\helpers\calendar.js
内容:
const cheerio = require('cheerio')
const moment = require('moment')
hexo.extend.filter.register('after_render:html', function (locals) {
const $ = cheerio.load(locals)
const post = $('#post-calendar')
let htmlEncode = false
if (post.length > 0) {
if (post.length > 0 && $('#postCalender').length === 0) {
if (post.attr('data-encode') === 'true') htmlEncode = true
post.after(postCalender())
}
if (htmlEncode) {
return $.root().html().replace(/&#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)
function postCalender () {
var nameMap = 'cn';
var titleText = '文章日历';
// calculate range.
var startDate = moment().subtract(1, 'years');
var endDate = moment();
var rangeArr = '["' + startDate.format('YYYY-MM-DD') + '", "' + endDate.format('YYYY-MM-DD') + '"]';
// post and count map.
var dateMap = new Map();
hexo.locals.get('posts').forEach(function (post) {
var date = post.date.format('YYYY-MM-DD');
var count = dateMap.get(date);
dateMap.set(date, count == null || count == undefined ? 1 : count + 1);
});
// loop the data for the current year, generating the number of post per day
var i = 0;
var datePosts = '[';
var dayTime = 3600 * 24 * 1000;
for (var time = startDate; time <= endDate; time += dayTime) {
var date = moment(time).format('YYYY-MM-DD');
datePosts = (i === 0 ? datePosts + '["' : datePosts + ', ["') + date + '", '
+ (dateMap.has(date) ? dateMap.get(date) : 0) + ']';
i++;
}
datePosts += ']';
return `
<script id="postCalender">
var myChart = echarts.init(document.getElementById('post-calendar'));
console.log(1);
console.log('${titleText}');
var option = {
title: {
top: 0,
text: '${titleText}',
left: 'center',
textStyle: {
color: '#3C4858'
}
},
tooltip: {
padding: 10,
backgroundColor: '#555',
borderColor: '#777',
borderWidth: 1,
formatter: function (obj) {
var value = obj.value;
return '<div style="font-size: 14px;">' + value[0] + ':' + value[1] + '</div>';
}
},
visualMap: {
show: true,
showLabel: true,
categories: [0, 1, 2, 3, ">=4"],
calculable: true,
inRange: {
symbol: 'rect',
color: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']
},
itemWidth: 12,
itemHeight: 12,
orient: 'horizontal',
left: 'center',
bottom: 40
},
calendar: [{
left: 'center',
range: ${rangeArr},
cellSize: [13, 13],
splitLine: {
show: false
},
itemStyle: {
color: '#196127',
borderColor: '#fff',
borderWidth: 2
},
yearLabel: {
show: false
},
monthLabel: {
nameMap: '${nameMap}',
fontSize: 11
},
dayLabel: {
formatter: '{start} 1st',
nameMap: '${nameMap}',
fontSize: 11
}
}],
series: [{
type: 'heatmap',
coordinateSystem: 'calendar',
calendarIndex: 0,
data: ${datePosts}
}]
};
myChart.setOption(option);
window.addEventListener("resize", () => {
myChart.resize();
});
</script>`
}
文章分类雷达图
代码修改自matery主题,路径为
hexo-theme-matery\layout\_widget\category-radar.ejs
新增的文件路径:
\blog\themes\butterfly\scripts\helpers\radar.js
内容为:
const cheerio = require('cheerio')
const moment = require('moment')
hexo.extend.filter.register('after_render:html', function (locals) {
const $ = cheerio.load(locals)
const category = $('#categories-radar')
let htmlEncode = false
if (category.length > 0) {
if (category.length > 0 && $('#categoriesRadar').length === 0) {
if (category.attr('data-encode') === 'true') htmlEncode = true
category.after(categoriesRadar())
}
if (htmlEncode) {
return $.root().html().replace(/&#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)
function categoriesRadar () {
var categories = hexo.locals.get('categories');
// Find the maximum and average values of the post categories.
var radarValueArr = [];
categories.some(function(category) {
radarValueArr.push(category.length);
});
var max = Math.max.apply(null, radarValueArr) + Math.min.apply(null, radarValueArr);
// Calculate the data needed for the radar chart.
var indicatorArr = [];
categories.map(function(category) {
indicatorArr.push({'name': category.name, 'max': max});
});
var indicatorData = JSON.stringify(indicatorArr);
var radarValueData = JSON.stringify(radarValueArr);
return `
<script id="categoriesRadar">
var radarChart = echarts.init(document.getElementById('categories-radar'));
var option = {
title: {
left: 'center',
text: '文章分类雷达图',
textStyle: {
// fontWeight: 500,
// fontSize: 22
color: '#000'
}
},
tooltip: {},
radar: {
name: {
textStyle: {
color: '#3C4858'
}
},
indicator: ${indicatorData},
nameGap: 5,
// center: ['50%','55%'],
center: ['50%','50%'],
radius: '66%',
left: 'center'
},
series: [{
type: 'radar',
color: ['#3ecf8e'],
itemStyle: {normal: {areaStyle: {type: 'default'}}},
data : [
{
value : ${radarValueData},
name : 'test'
}
]
}]
};
radarChart.setOption(option);
</script>`
}
访问统计
参考资料:
https://blog.eurkon.com/post/ef1da941.html
https://akilar.top/posts/1f9c68c9/
基本按照上述资料进行了配置,增加了全球访客图,变更如下:
路径:
blog\source\census\index.md:
内容:
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/dist/echarts.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/map/js/china.js"></script> <!-- 中国地图 -->
<script src="https://cdn.jsdelivr.net/npm/echarts@4.7.0/map/js/world.js"></script> <!-- 世界地图 -->
<!-- 全球访问地图 -->
<div id="world-map-chart" style="border-radius: 8px; height: 500px; padding: 10px;"></div>
<!-- 全国访问地图 -->
<div id="map-chart" style="border-radius: 8px; height: 600px; padding: 10px;"></div>
<!-- 访问趋势 -->
<div id="trends-chart" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
<!-- 访问来源 -->
<div id="sources-chart" style="border-radius: 8px; height: 300px; padding: 10px;"></div>
路径
blog\themes\butterfly\scripts\helpers\census.js
内容:
const cheerio = require('cheerio')
const moment = require('moment')
const fetch = require('node-fetch')
hexo.extend.filter.register('after_render:html', async function (locals) {
const $ = cheerio.load(locals)
const worldmap = $('#world-map-chart')
const map = $('#map-chart')
const trend = $('#trends-chart')
const source = $('#sources-chart')
let htmlEncode = false
if (worldmap.length > 0 || map.length > 0 || trend.length > 0 || source.length > 0) {
if (worldmap.length > 0 && $('#worldMapChart').length === 0) {
worldmap.after(await worldMapChart())
}
if (map.length > 0 && $('#mapChart').length === 0) {
map.after(await mapChart())
}
if (trend.length > 0 && $('#trendsChart').length === 0) {
trend.after(await trendsChart())
}
if (source.length > 0 && $('#sourcesChart').length === 0) {
source.after(await sourcesChart())
}
if (htmlEncode) {
return $.root().html().replace(/&#/g, '&#')
} else {
return $.root().html()
}
} else {
return locals
}
}, 15)
const startDate = '20000101' // 开始日期
const endDate = moment().format('YYYYMMDD') // 结束日期
const accessToken = '' // accessToken
const siteId = '' // 网址id
const dataUrl = 'https://openapi.baidu.com/rest/2.0/tongji/report/getData?access_token=' + accessToken + '&site_id=' + siteId;
// const dataUrl = 'https://baidu-tongji-api-lime.vercel.app/api?access_token=' + accessToken + '&site_id=' + siteId;
const metrics = 'pv_count' // 统计访问次数 PV 填写 'pv_count',统计访客数 UV 填写 'visitor_count',二选一
const metricsName = (metrics === 'pv_count' ? '访问次数' : (metrics === 'visitor_count' ? '访客数' : ''))
// 全球访问地图
function worldMapChart () {
return new Promise(resolve => {
const paramUrl = '&start_date=' + startDate + '&end_date=' + endDate + '&metrics=' + metrics + '&method=visit/world/a';
fetch(dataUrl + paramUrl)
.then(data => data.json())
.then(data => {
monthArr = [];
let mapName = data.result.items[0]
let mapValue = data.result.items[1]
let mapArr = []
let max = mapValue[0][0]
for (let i = 0; i < mapName.length; i++) {
mapArr.push({ name: mapName[i][0].name, value: mapValue[i][0] })
}
const mapArrJson = JSON.stringify(mapArr)
resolve(`
<script id="worldMapChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var worldmap = echarts.init(document.getElementById('world-map-chart'), 'light');
var worldmapOption = {
title: {
text: '博客访问来源地图(全球)',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item'
},
visualMap: {
min: 0,
max: ${max},
// max: 1000,
left: 'left',
top: 'bottom',
text: ['高','低'],
color: ['#1E90FF', '#AAFAFA'],
textStyle: {
color: color
},
calculable: true
},
series: [{
name: '${metricsName}',
type: 'map',
mapType: 'world',
showLegendSymbol: false,
nameMap: {
"Afghanistan":"阿富汗",
"Albania":"阿尔巴尼亚",
"Algeria":"阿尔及利亚",
"Angola":"安哥拉",
"Argentina":"阿根廷",
"Armenia":"亚美尼亚",
"Australia":"澳大利亚",
"Austria":"奥地利",
"Azerbaijan":"阿塞拜疆",
"Bahamas":"巴哈马",
"Bahrain":"巴林",
"Bangladesh":"孟加拉国",
"Belarus":"白俄罗斯",
"Belgium":"比利时",
"Belize":"伯利兹",
"Benin":"贝宁",
"Bhutan":"不丹",
"Bolivia":"玻利维亚",
"Bosnia and Herz.":"波斯尼亚和黑塞哥维那",
"Botswana":"博茨瓦纳",
"Brazil":"巴西",
"British Virgin Islands":"英属维京群岛",
"Brunei":"文莱",
"Bulgaria":"保加利亚",
"Burkina Faso":"布基纳法索",
"Burundi":"布隆迪",
"Cambodia":"柬埔寨",
"Cameroon":"喀麦隆",
"Canada":"加拿大",
"Cape Verde":"佛得角",
"Cayman Islands":"开曼群岛",
"Central African Rep.":"中非共和国",
"Chad":"乍得",
"Chile":"智利",
"China":"中国",
"Colombia":"哥伦比亚",
"Comoros":"科摩罗",
"Congo":"刚果",
"Costa Rica":"哥斯达黎加",
"Croatia":"克罗地亚",
"Cuba":"古巴",
"Cyprus":"塞浦路斯",
"Czech Rep.":"捷克共和国",
"Côte d'Ivoire":"科特迪瓦",
"Dem. Rep. Congo":"刚果民主共和国",
"Dem. Rep. Korea":"朝鲜",
"Denmark":"丹麦",
"Djibouti":"吉布提",
"Dominican Rep.":"多米尼加共和国",
"Ecuador":"厄瓜多尔",
"Egypt":"埃及",
"El Salvador":"萨尔瓦多",
"Equatorial Guinea":"赤道几内亚",
"Eritrea":"厄立特里亚",
"Estonia":"爱沙尼亚",
"Ethiopia":"埃塞俄比亚",
"Falkland Is.":"福克兰群岛",
"Fiji":"斐济",
"Finland":"芬兰",
"Fr. S. Antarctic Lands":"所罗门群岛",
"France":"法国",
"Gabon":"加蓬",
"Gambia":"冈比亚",
"Georgia":"格鲁吉亚",
"Germany":"德国",
"Ghana":"加纳",
"Greece":"希腊",
"Greenland":"格陵兰",
"Guatemala":"危地马拉",
"Guinea":"几内亚",
"Guinea-Bissau":"几内亚比绍",
"Guyana":"圭亚那",
"Haiti":"海地",
"Honduras":"洪都拉斯",
"Hungary":"匈牙利",
"Iceland":"冰岛",
"India":"印度",
"Indonesia":"印度尼西亚",
"Iran":"伊朗",
"Iraq":"伊拉克",
"Ireland":"爱尔兰",
"Isle of Man":"马恩岛",
"Israel":"以色列",
"Italy":"意大利",
"Jamaica":"牙买加",
"Japan":"日本",
"Jordan":"约旦",
"Kazakhstan":"哈萨克斯坦",
"Kenya":"肯尼亚",
"Korea":"韩国",
"Kuwait":"科威特",
"Kyrgyzstan":"吉尔吉斯斯坦",
"Lao PDR":"老挝",
"Latvia":"拉脱维亚",
"Lebanon":"黎巴嫩",
"Lesotho":"莱索托",
"Liberia":"利比里亚",
"Libya":"利比亚",
"Lithuania":"立陶宛",
"Luxembourg":"卢森堡",
"Macedonia":"马其顿",
"Madagascar":"马达加斯加",
"Malawi":"马拉维",
"Malaysia":"马来西亚",
"Maldives":"马尔代夫",
"Mali":"马里",
"Malta":"马耳他",
"Mauritania":"毛利塔尼亚",
"Mauritius":"毛里求斯",
"Mexico":"墨西哥",
"Moldova":"摩尔多瓦",
"Monaco":"摩纳哥",
"Mongolia":"蒙古",
"Montenegro":"黑山共和国",
"Morocco":"摩洛哥",
"Mozambique":"莫桑比克",
"Myanmar":"缅甸",
"Namibia":"纳米比亚",
"Nepal":"尼泊尔",
"Netherlands":"荷兰",
"New Caledonia":"新喀里多尼亚",
"New Zealand":"新西兰",
"Nicaragua":"尼加拉瓜",
"Niger":"尼日尔",
"Nigeria":"尼日利亚",
"Norway":"挪威",
"Oman":"阿曼",
"Pakistan":"巴基斯坦",
"Panama":"巴拿马",
"Papua New Guinea":"巴布亚新几内亚",
"Paraguay":"巴拉圭",
"Peru":"秘鲁",
"Philippines":"菲律宾",
"Poland":"波兰",
"Portugal":"葡萄牙",
"Puerto Rico":"波多黎各",
"Qatar":"卡塔尔",
"Reunion":"留尼旺",
"Romania":"罗马尼亚",
"Russia":"俄罗斯",
"Rwanda":"卢旺达",
"S. Geo. and S. Sandw. Is.":"南乔治亚和南桑威奇群岛",
"S. Sudan":"南苏丹",
"San Marino":"圣马力诺",
"Saudi Arabia":"沙特阿拉伯",
"Senegal":"塞内加尔",
"Serbia":"塞尔维亚",
"Sierra Leone":"塞拉利昂",
"Singapore":"新加坡",
"Slovakia":"斯洛伐克",
"Slovenia":"斯洛文尼亚",
"Solomon Is.":"所罗门群岛",
"Somalia":"索马里",
"South Africa":"南非",
"Spain":"西班牙",
"Sri Lanka":"斯里兰卡",
"Sudan":"苏丹",
"Suriname":"苏里南",
"Swaziland":"斯威士兰",
"Sweden":"瑞典",
"Switzerland":"瑞士",
"Syria":"叙利亚",
"Tajikistan":"塔吉克斯坦",
"Tanzania":"坦桑尼亚",
"Thailand":"泰国",
"Togo":"多哥",
"Tonga":"汤加",
"Trinidad and Tobago":"特立尼达和多巴哥",
"Tunisia":"突尼斯",
"Turkey":"土耳其",
"Turkmenistan":"土库曼斯坦",
"U.S. Virgin Islands":"美属维尔京群岛",
"Uganda":"乌干达",
"Ukraine":"乌克兰",
"United Arab Emirates":"阿拉伯联合酋长国",
"United Kingdom":"英国",
"United States":"美国",
"Uruguay":"乌拉圭",
"Uzbekistan":"乌兹别克斯坦",
"Vanuatu":"瓦努阿图",
"Vatican City":"梵蒂冈城",
"Venezuela":"委内瑞拉",
"Vietnam":"越南",
"W. Sahara":"西撒哈拉",
"Yemen":"也门",
"Yugoslavia":"南斯拉夫",
"Zaire":"扎伊尔",
"Zambia":"赞比亚",
"Zimbabwe":"津巴布韦"
},
label: {
emphasis: {
show: false
}
},
itemStyle: {
normal: {
areaColor: 'rgba(255, 255, 255, 0.1)',
borderColor: '#20232a'
},
emphasis: {
areaColor: 'gold'
}
},
data: ${mapArrJson}
}]
};
worldmap.setOption(worldmapOption);
window.addEventListener("resize", () => {
worldmap.resize();
});
</script>`);
}).catch(function (error) {
console.log(error);
});
})
}
// 访问地图
function mapChart () {
return new Promise(resolve => {
const paramUrl = '&start_date=' + startDate + '&end_date=' + endDate + '&metrics=' + metrics + '&method=visit/district/a';
fetch(dataUrl + paramUrl)
.then(data => data.json())
.then(data => {
monthArr = [];
let mapName = data.result.items[0]
let mapValue = data.result.items[1]
let mapArr = []
let max = mapValue[0][0]
for (let i = 0; i < mapName.length; i++) {
mapArr.push({ name: mapName[i][0].name, value: mapValue[i][0] })
}
const mapArrJson = JSON.stringify(mapArr)
resolve(`
<script id="mapChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var mapChart = echarts.init(document.getElementById('map-chart'), 'light');
var mapOption = {
title: {
text: '博客访问来源地图(全国)',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item'
},
visualMap: {
min: 0,
max: ${max},
left: 'left',
top: 'bottom',
text: ['高','低'],
color: ['#1E90FF', '#AAFAFA'],
textStyle: {
color: color
},
calculable: true
},
series: [{
name: '${metricsName}',
type: 'map',
mapType: 'china',
showLegendSymbol: false,
label: {
emphasis: {
show: false
}
},
itemStyle: {
normal: {
areaColor: 'rgba(255, 255, 255, 0.1)',
borderColor: '#20232a'
},
emphasis: {
areaColor: 'gold'
}
},
data: ${mapArrJson}
}]
};
mapChart.setOption(mapOption);
window.addEventListener("resize", () => {
mapChart.resize();
});
</script>`);
}).catch(function (error) {
console.log(error);
});
})
}
// 访问趋势
function trendsChart () {
return new Promise(resolve => {
const paramUrl = '&start_date=' + startDate + '&end_date=' + endDate + '&metrics=' + metrics + '&method=trend/time/a&gran=month'
fetch(dataUrl + paramUrl)
.then(data => data.json())
.then(data => {
const monthArr = []
const monthValueArr = []
const monthName = data.result.items[0]
const monthValue = data.result.items[1]
for (let i = Math.min(monthName.length, 12) - 1; i >= 0; i--) {
monthArr.push(monthName[i][0].substring(0, 7).replace('/', '-'))
if (monthValue[i][0] !== '--') {
monthValueArr.push(monthValue[i][0])
} else {
monthValueArr.push(null)
}
}
const monthArrJson = JSON.stringify(monthArr)
const monthValueArrJson = JSON.stringify(monthValueArr)
resolve(`
<script id="trendsChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var trendsChart = echarts.init(document.getElementById('trends-chart'), 'light');
var trendsOption = {
textStyle: {
color: color
},
title: {
text: '博客访问统计图',
x: 'center',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'axis'
},
xAxis: {
name: '日期',
type: 'category',
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: color
}
},
data: ${monthArrJson}
},
yAxis: {
name: '${metricsName}',
type: 'value',
splitLine: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: true,
lineStyle: {
color: color
}
}
},
series: [{
name: '${metricsName}',
type: 'line',
smooth: true,
lineStyle: {
width: 0
},
showSymbol: false,
itemStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
},
{
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
areaStyle: {
opacity: 1,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(128, 255, 165)'
}, {
offset: 1,
color: 'rgba(1, 191, 236)'
}])
},
data: ${monthValueArrJson},
markLine: {
data: [{
name: '平均值',
type: 'average'
}]
}
}]
};
trendsChart.setOption(trendsOption);
window.addEventListener("resize", () => {
trendsChart.resize();
});
</script>`)
}).catch(function (error) {
console.log(error);
});
})
}
// 访问来源
function sourcesChart () {
return new Promise(resolve => {
const paramUrl = '&start_date=' + startDate + '&end_date=' + endDate + '&metrics=' + metrics + '&method=source/all/a';
fetch(dataUrl + paramUrl)
.then(data => data.json())
.then(data => {
monthArr = [];
let sourcesName = data.result.items[0]
let sourcesValue = data.result.items[1]
let sourcesArr = []
for (let i = 0; i < sourcesName.length; i++) {
sourcesArr.push({ name: sourcesName[i][0].name, value: sourcesValue[i][0] })
}
const sourcesArrJson = JSON.stringify(sourcesArr)
resolve(`
<script id="sourcesChart">
var color = document.documentElement.getAttribute('data-theme') === 'light' ? '#4c4948' : 'rgba(255,255,255,0.7)'
var sourcesChart = echarts.init(document.getElementById('sources-chart'), 'light');
var sourcesOption = {
textStyle: {
color: color
},
title: {
text: '博客访问来源统计图',
x: 'center',
textStyle: {
color: color
}
},
legend: {
top: 'bottom',
textStyle: {
color: color
}
},
tooltip: {
trigger: 'item',
formatter: "{a} <br/>{b} : {c} ({d}%)"
},
series: [{
name: '${metricsName}',
type: 'pie',
radius: [30, 80],
center: ['50%', '50%'],
roseType: 'area',
label: {
formatter: "{b} : {c} ({d}%)"
},
data: ${sourcesArrJson},
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(255, 255, 255, 0.5)'
}
}
}]
};
sourcesChart.setOption(sourcesOption);
window.addEventListener("resize", () => {
sourcesChart.resize();
});
</script>`);
}).catch(function (error) {
console.log(error);
});
})
}
阅读排行榜
todo。
娱乐
电影
参考资料:
https://butterfly.js.org/posts/4073eda/#%E9%9B%BB%E5%BD%B1
https://github.com/jerryc127/butterfly-plugins/tree/main/hexo-butterfly-douban
首页增加字数总计,阅读时长
原生的butterfly首页无法显示字数总计,阅读时长,这里对其进行了修改,具体见配置方法。
文章页无法显示标签
更新:
标签显示在文章底部,并不是没有显示,所以后续操作可以忽略。
在主题的3.7.8版本中,即使将主题配置文件中如下tags设置为true,依然没有显示标签
post_meta:
post:
tags: true # true or false 文章頁是否顯示標籤
检查后发现是缺少对应代码,配置文件为
\blog\themes\butterfly\layout\includes\header\post-info.pug
搜索
i.fas.fa-angle-right.post-meta-separator
在其后添加
//- add
if (theme.post_meta.page.tags && page.tags.data.length > 0)
span.post-meta-categories
span.post-meta-separator |
i.fas.fa-tag
each item, index in page.tags.data
a(href=url_for(item.path)).article-meta__tags #[=item.name]
if (index < page.tags.data.length - 1)
span.article-meta__link #[='•']
注意该if要和
if (theme.post_meta.post.categories && page.categories.data.length > 0)
的缩进相同,最后的效果为:
if (theme.post_meta.post.categories && page.categories.data.length > 0)
span.post-meta-categories
if (theme.post_meta.post.date_type)
span.post-meta-separator |
each item, index in page.categories.data
i.fas.fa-inbox.fa-fw.post-meta-icon
a(href=url_for(item.path)).post-meta-categories #[=item.name]
if (index < page.categories.data.length - 1)
i.fas.fa-angle-right.post-meta-separator
//- add
if (theme.post_meta.page.tags && page.tags.data.length > 0)
span.post-meta-categories
span.post-meta-separator |
i.fas.fa-tag
each item, index in page.tags.data
a(href=url_for(item.path)).article-meta__tags #[=item.name]
if (index < page.tags.data.length - 1)
span.article-meta__link #[='•']
访客地图
参考资料:
https://butterfly.js.org/posts/ea33ab97/#%E4%BE%8B%E5%AD%90
https://www.cnblogs.com/DHUtoBUAA/p/12283754.html
按照链接1配置,将代码替换为链接2中自己的代码即可。
数学公式
参考资料:
https://butterfly.js.org/posts/ceeb73f/#Math-%E6%95%B8%E5%AD%B8
https://ranmaosong.github.io/2017/11/29/hexo-support-mathjax/
选了mathjax,首先进行安装:
npm uninstall hexo-renderer-marked --save
npm install hexo-renderer-kramed --save
npm uninstall hexo-math --save
npm install hexo-renderer-mathjax --save
如果安装后部分数学公式显示不正确,可以按照如下方式调整。
文件位置:
D:\blog\node_modules\hexo-renderer-kramed\lib\renderer.js
修改内容:
// Change inline math rule
function formatText(text) {
// Fit kramed's rule: $$ + \1 + $$
- return text.replace(/`\$(.*?)\$`/g, '$$$$$1$$$$');
+ return text;
}
文件位置:
\blog\node_modules\kramed\lib\rules\inline.js
修改内容:
- escape: /^\\([\\`*{}\[\]()#$+\-.!_>])/,
+ escape: /^\\([`*\[\]()#$+\-.!_>])/,
- em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
+ em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
还有一些显示的问题,已经在issue中提出:
- https://github.com/jerryc127/hexo-theme-butterfly/issues/587
- https://github.com/jerryc127/hexo-theme-butterfly/issues/586
目前(截至20210612)作者已经在dev分支修复上述问题,修改的文件为
\blog\themes\butterfly\layout\includes\third-party\math\mathjax.pug
添加社交图标
b站
参考资料:
https://blog.imzjw.cn/posts/b74f504f/
以b站为例,按照教程中的方法下载css,内容如下:
@font-face {
font-family: "iconfont"; /* Project id 2604084 */
src: url('//at.alicdn.com/t/font_2604084_fh638f3m5rm.woff2?t=1623256482370') format('woff2'),
url('//at.alicdn.com/t/font_2604084_fh638f3m5rm.woff?t=1623256482370') format('woff'),
url('//at.alicdn.com/t/font_2604084_fh638f3m5rm.ttf?t=1623256482370') format('truetype');
}
.iconfont {
font-family: "iconfont" !important;
/* font-size: 16px; */
font-size: 18px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-bilibili:before {
content: "\e601";
}
在如下路径
\blog\themes\butterfly\source\css
新建bilibili.css,将这些内容复制到css文件中。
在主题的_config.yml中添加:
inject:
head:
- <link rel="stylesheet" href="/css/bilibili.css" media="defer" onload="this.media='all'">
在主题的_config.yml文件中social添加如下内容即可:
social:
iconfont icon-bilibili: b站主页 || Bilibili
其他的社交图标用同样方式添加即可。
rss
参考资料:
https://lilu.org.cn/2021/01/31/butterfly/
安装插件:
npm install hexo-generator-feed --save
配置:
social:
fa fa-rss: /atom.xml
文章meta信息
加载动画
网页加载动画:
# Loading Animation (加載動畫)
preloader: true
图片加载动画:
# Lazyload (圖片懶加載)
# https://github.com/verlok/vanilla-lazyload
lazyload:
enable: true
field: site # site/post
placeholder: /img/loading.gif
blur: false
loading.gif即为加载动画,路径如下
\blog\themes\butterfly\source\img
顶部图
配置命令如下:
# Disable all banner image
disable_top_img: false
# The banner image of home page
index_img: picture
美化页面
# Beautify (美化頁面顯示)
beautify:
enable: true
field: site # site/post
title-prefix-icon: '\f0c1'
title-prefix-icon-color: '#F47466'
评论系统
目前配置了valine以及来必力(遗留问题,早期的评论来自于来必力,目前来必力只通过qq浏览器成功登陆,chrome以及edge均无法登陆)。
配置如下:
comments:
# Up to two comments system, the first will be shown as default
# Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo
use:
- Valine
- Livere
# - Disqus
text: true # Display the comment name next to the button
# lazyload: The comment system will be load when comment element enters the browser's viewport.
# If you set it to true, the comment count will be invalid
lazyload: false
count: true # Display comment count in post's top_img
card_post_count: true # Display comment count in Home Page
搜索
使用了hexo-generator-search,注意hexo c并清除浏览器缓存。
分析系统
目前配置了百度分析以及谷歌分析,谷歌分析的跟踪 ID获取方法见:
https://git.mrhao.xyz/blog/2020/04/25/GoogleAnalytics/
https://iamlay.com/2020/06/27/HexoGoogleAnalytics/
搜索引擎收录
参考资料如下:
https://github.com/cjh0613/hexo-submit-urls-to-search-engine
https://cjh0613.com/20200603HexoSubmitUrlsToSearchEngine.html
插件为hexo-submit-urls-to-search-engine