Hexo添加站内本地搜索

前言

  虽然 Shaun 博客目前数量不多,质量也不高,但抱着搞事的心态,先弄它一个站内本地搜索再说。

前言

  虽然 Shaun 博客目前数量不多,质量也不高,但抱着搞事的心态,先弄它一个站内本地搜索再说。

准备篇

  要想使用本地搜索功能,首先需要安装相应的搜索插件 hexo-generator-searchdb,网上可能大多数用的是 hexo-generator-search 这个插件,也有都装的,但 Shaun 就只安装这一个了,好像 hexo-generator-searchdb 更完善一点,由于 Shaun 前端接触的极少,所以就没有一一对比了,网上也没查到具体对比情况,有兴趣的童靴可以试试 (╯▽╰)。至于具体安装如下,在站点根目录执行:

1
npm install hexo-generator-searchdb --save

  安装完之后重新生成页面,将会发现 public文件夹 下多出一个 search.xml 文件。然后在配置文件 _config.yml 中添加:

1
2
3
4
# 站点本地搜索
search:
path: search.xml
field: all

其中:

  • path - 指定生成的索引数据的文件名。默认为 search.xml 。
  • field - 指定索引数据的生成范围。可选值包括:
    • post - 只生成博客文章(post)的索引(默认);
    • page - 只生成其他页面(page)的索引;
    • all - 生成所有文章和页面的索引。

  至于是在 主题配置文件,还是在 站点配置文件 中添加,个人觉得都没关系,附:Shaun 是在主题配置文件中添加的。

接下来就需要修改原主题的代码了。

改码篇

  由于 Shaun 博客主题是基于 SPFK 对照着 black-blue 进行修改的,而且因为 black-blue 是有搜索的(Shaun 不知道 black-blue 主题的作者是如何完成的,借助了什么技术),所以 Shaun 就看 black-blue 的搜索功能是修改了 SPFK 哪个地方,再将相应的代码添加至 SPFK 中(其中相应的代码来自让 Hexo 博客支持本地站内搜索),从而逐渐完成本次搜索功能。

首先找到 spfk 主题下的 left-col.ejs 文件,对其修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
<% if (theme.search_box){ %>
<!-- <form>
<input type="text" class="st-default-search-input search" id="search" placeholder=" Search...">
</form> -->

<form id="search-form"> <!-- 搜索框相关 -->
<input type="text" id="local-search-input" name="q" results="0" placeholder="Search..." class="search form-control" autocomplete="off" autocorrect="off"/>
<i class="fa fa-times" onclick="resetSearch()"></i> <!-- 清空/重置搜索框 -->
</form>
<div id="local-search-result"></div> <!-- 搜索结果区 -->
<p class='no-result'>No results found </p> <!-- 无匹配时显示,注意请在 CSS 中设置默认隐藏 -->
<%}%>

其次找到 spfk 主题下的 after-footer.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
<% if (theme.search_box){ %>
<!-- <script type="text/javascript">
window.onload = function(){
document.getElementById("search").onclick = function(){
console.log("search")
search();
}
}
function search(){
(function(w,d,t,u,n,s,e){w['SwiftypeObject']=n;w[n]=w[n]||function(){
(w[n].q=w[n].q||[]).push(arguments);};s=d.createElement(t);
e=d.getElementsByTagName(t)[0];s.async=1;s.src=u;e.parentNode.insertBefore(s,e);
})(window,document,'script','//s.swiftypecdn.com/install/v2/st.js','_st');

_st('install','A1Pz-LKMXbrzcFg2FWi6','2.0.0');
}
</script> -->

<script type="text/javascript">
// 激活搜索框时才搜索
var inputArea = document.querySelector("#local-search-input");
var getSearchFile = function(){
// 调用搜索函数
var search_path = "<%- config.search.path %>";
if (search_path.length == 0) {
search_path = "search.xml";
}
var path = "<%- config.root %>" + search_path;
searchFunc(path, 'local-search-input', 'local-search-result');
}
inputArea.onfocus = function(){ getSearchFile() }

// 搜索重置
var $resetButton = $("#search-form .fa-times");
var $resultArea = $("#local-search-result");
inputArea.oninput = function(){ $resetButton.show(); }
resetSearch = function(){
$resultArea.html("");
document.querySelector("#search-form").reset();
$resetButton.hide();
$(".no-result").hide();
}

// 屏蔽回车
inputArea.onkeydown = function(){ if(event.keyCode==13) return false}

// 无搜索结果
$resultArea.bind("DOMNodeRemoved DOMNodeInserted", function(e) {
if (!$(e.target).text()) {
$(".no-result").show(200);
} else {
$(".no-result").hide();
}
})

// 搜索函数
var searchFunc = function(path, search_id, content_id) {
'use strict';
$.ajax({
url: path,
dataType: "xml",
success: function( xmlResponse ) {
// get the contents from search data
var datas = $( "entry", xmlResponse ).map(function() {
return {
title: $( "title", this ).text(),
content: $("content",this).text(),
url: $( "url" , this).text()
};
}).get();
var $input = document.getElementById(search_id);
var $resultContent = document.getElementById(content_id);
$input.addEventListener('input', function(){
var str='<ul class=\"search-result-list\">';
var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
$resultContent.innerHTML = "";
if (this.value.trim().length <= 0) {
return;
}
// perform local searching
datas.forEach(function(data) {
var isMatch = true;
var content_index = [];
var data_title = data.title.trim().toLowerCase();
var data_content = data.content.trim().replace(/<[^>]+>/g,"").toLowerCase();
var data_url = data.url;
var index_title = -1;
var index_content = -1;
var first_occur = -1;
// only match artiles with not empty titles and contents
if(data_title != '' && data_content != '') {
keywords.forEach(function(keyword, i) {
index_title = data_title.indexOf(keyword);
index_content = data_content.indexOf(keyword);
if( index_title < 0 && index_content < 0 ){
isMatch = false;
} else {
if (index_content < 0) {
index_content = 0;
}
if (i == 0) {
first_occur = index_content;
}
}
});
}
// show search results
if (isMatch) {
str += "<li><a href='/"+ data_url +"' class='search-result-title' target='_blank'>"+ "> " + data_title +"</a>";
var content = data.content.trim().replace(/<[^>]+>/g,"");
if (first_occur >= 0) {
// cut out characters
var start = first_occur - 6;
var end = first_occur + 6;
if(start < 0){
start = 0;
}
if(start == 0){
end = 10;
}
if(end > content.length){
end = content.length;
}
var match_content = content.substr(start, end);
// highlight all keywords
keywords.forEach(function(keyword){
var regS = new RegExp(keyword, "gi");
match_content = match_content.replace(regS, "<em class=\"search-keyword\">"+keyword+"</em>");
})
str += "<p class=\"search-result\">" + match_content +"...</p>"
}
}
})
$resultContent.innerHTML = str;
})
}
})
}
</script>
<%}%>

最后找到 spfk 主题下的 main.styl 文件,在其末尾添加:

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
/*搜索框*/
.search {
width: 68%;
height: 18px;
margin-top: 1px;
padding: 0;
font-family: inherit;
border: 2px solid transparent;
border-bottom: 2px solid #d3d3d3;
border-radius: 2px;
opacity: 0.65;
background: none;
}
.search:hover {
border: 2px solid #d3d3d3;
opacity: 1;
box-shadow: 0 0 10px rgba(0,0,0,0.3);
}

/*搜索重置按钮*/
#search-form .fa-times {
display: none;
padding: 1px 0.7em;
box-shadow: 0 0 3px rgba(0,0,0,0.15);
cursor: pointer;
color: #4094c7;
}
#search-form .fa-times:active {
background: #d3d3d3;
}
#search-form .fa-times:hover {
zoom: 1.1;
padding: 1px 0.6em;
border: 1px solid #d3d3d3;
box-shadow: 0 0 6px rgba(0,0,0,0.25);
}

/*搜索结果区*/
#local-search-result {
//margin: auto -12% auto -6%;
margin: 0;
font-size: 0.9em;
text-align: left;
word-break: break-all;

box-shadow: 4px 4px 6px rgba(0,0,0,0.46);
}

#local-search-result ul.search-result-list li:hover {
font-weight: normal;
}

/*单条搜索结果*/
#local-search-result li {
margin: 0.5em auto;
border-bottom: 2px solid #d3d3d3;
}
#local-search-result .search-result-list li:hover {
background: rgba(47,46,46,0.8);
box-shadow: 0 0 5px rgba(0,0,0,0.2);
}

/*匹配的标题*/
#local-search-result a.search-result-title {
line-height: 1.2;
font-weight: bold;
color: #4094c7;
}

/*搜索预览段落*/
#local-search-result p.search-result {
margin: 0.4em auto;
line-height: 1.2em;
max-height: 3.6em;
overflow: hidden;
font-size: 0.8em;
text-align: justify;
color: #ffffffb3;
}

/*匹配的关键词*/
#local-search-result em.search-keyword {
color: #f58e90;
border-bottom: 1px dashed #f58e90;
font-weight: bold;
font-size: 1em;
}

/*无匹配搜索结果时显示*/
p.no-result {
display: none;
margin: 2em 0 2em 6%;
padding-bottom: 0.5em;
text-align: left;
color: #808080;
font-family: font-serif serif;
border-bottom: 2px solid #d3d3d3;
}

  这里请注意,当对 main.styl 文件做以上修改时,可能会发现有两个 .search 样式,而且相差不大,这时,不要对其原有的 .search 进行修改,更不要去注释掉它,只做上述修改就不用管了,不然可能会发生一些奇怪的事 o(>﹏<)o。Shaun 当时做以上修改时,将其原有的 .search 样式注释掉之后,整个页面的 css 布局全部都乱了 (╯﹏╰),不知道为什么 (⊙_⊙?),这两个同名样式看起来明明差不多的,最后只能维持现状了,等以后有机会再看看吧,业余前端伤不起啊! ╮(╯_╰)╭。

  至此整个站内本地搜索功能基本完成,勉强可以使用站内搜索功能了。

问题篇

  *注:以下问题于 2018-03-02 都已经解决 ╮(╯▽╰)╭。

1、搜索函数返回的 url 地址有问题。

  问题描述:当点击搜索结果时,新弹出的标签页地址栏中 url 地址会有部分乱码情况;当鼠标移到搜索的结果列表上时,浏览器左下角显示的 url 地址虽然没有乱码情况,但其中有一个重复的/符号。所幸这两个问题并没有造成浏览器解析错误,浏览器还是可以正常显示页面的。

================= 修改日期:2018-03-02 =================

  解决办法:\blog\node_modules\hexo-generator-searchdb\templates\xml.ejs 文件中的 <url><%- encodeURIComponent(config.root + post.path) %></url> 修改为 <url><%- encodeURI(post.path) %></url> ,使其中一些 url 中常见的字符(如:&, ?, /, =)不被十六进制的转义序列进行替换。

参考:escape,encodeURI,encodeURIComponent有什么区别?JavaScript encodeURIComponent() 函数

=====================================================

2、搜索结果区布局有问题。

  问题描述:当显示搜索结果时,搜索结果区会上下扩张,从而将其上下本来存在的一些布局挤开,造成布局混乱。这其实不算是一个 spfk 主题或者新添加的搜索功能的问题,而是新添加的一个东西又没有相应的和原本布局结合的布局文件,那就极大可能会有布局混乱的问题,至于这个要和原本布局契合的搜索结果区布局文件就只有等 Shaun 以后有机会有时间再完善去喽 ╮(╯▽╰)╭。

3、搜索框激活问题。

  问题描述:搜索框激活延迟很大,有时过很久或者需要切换站内页面它才能激活,给人的感觉就是好像没有搜索功能似的。添加搜索框激活功能据作者 MOxFIVE 所说是为了不让索引文件影响页面加载速度,MOxFIVE 同时也在文末指出了一些不足之处,如果索引文件太大,可能还是会造成一些问题,但 Shaun 的博客数量又不多,所以估计还是 Shaun 的代码混合问题,而且 MOxFIVE 的博客搜索功能好像没这个问题(至少 Shaun 目前没发现)。这个问题同样只有等以后再说了 (*^__^*) 嘻嘻……。

后记

  本文添加的本地搜索还很粗糙,还有很多地方需要以后去完善。但这好歹是一个好的开始,搜索功能至少勉强能够正常使用,总比以前是个空壳要好,以后有机会再慢慢去去完善吧 ↖(^ω^)↗。

参考资料

[1] jQuery-based Local Search Engine for Hexohttp://www.hahack.com/categories/codes/

[2] 让 Hexo 博客支持本地站内搜索http://moxfive.xyz/tags/Hexo/

[3] Hexo博客添加站内搜索https://www.ezlippi.com/categories/hexo/

[4] Hexo本地搜索及部分SEO优化https://www.oyohyee.com/categories/Note/

用OpenCV显示OpenGL图形

前言

  本文就是一个小实验,试验 OpenCV 到底能不能支持 OpenGL 图形显示。

前言

  本文就是一个小实验,试验 OpenCV 到底能不能支持 OpenGL 图形显示。

正文

  如果在 OpenCV 用 CMake 编译时勾选 WITH_OPENGL 且编译一切顺利的话,编译和配置的具体步骤和情况可以看 Shaun 写的一篇文档:Win10+VS2013+CMake-gui编译和配置OpenCV-3.2.0 ,那么就可以用 OpenCV 窗口显示 OpenGL 图形。

  在 VS 下使用 Windows 原有的 OpenGL 函数需要包含以下头文件和库文件:

1
2
3
4
5
6
#include <Windows.h>
#include <GL/gl.h>
#include <GL/glu.h>

#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "glu32.lib")

  在 OpenCV 中显示 OpenGL 图形需要 cv::namedWindow(openGLWindowName, cv::WINDOW_OPENGL),在 namedWindow 函数中添加 cv::WINDOW_OPENGL 参数说明该窗口支持 OpenGL 图形。

附示例程序:

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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#include <opencv.hpp>

#include <Windows.h>
#include <GL/gl.h>
#include <GL/glu.h>

#pragma comment(lib, "OpenGL32.lib")
#pragma comment(lib, "glu32.lib")

static const float vertex_list[][3] =
{
-0.5f, -0.5f, -0.5f,
0.5f, -0.5f, -0.5f,
-0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f,
-0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f,
-0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f,
};

// 将要使用的顶点的序号保存到一个数组里面

static const GLint index_list[][2] =
{
{ 0, 1 },
{ 2, 3 },
{ 4, 5 },
{ 6, 7 },
{ 0, 2 },
{ 1, 3 },
{ 4, 6 },
{ 5, 7 },
{ 0, 4 },
{ 1, 5 },
{ 7, 3 },
{ 2, 6 }
};

static float rotate = 0;
static int times = 0;

GLint windowWidth = 800;
GLint windowHeight = 800;

GLfloat xRotAngle = -75.0f;
GLfloat yRotAngle = 0.0f;
GLfloat zRotAngle = -135.0f;

float MIN_X = -200;
float MAX_X = 200;

float MIN_Y = -200;
float MAX_Y = 200;

float MIN_Z = -200;
float MAX_Z = 200;

GLfloat coordinatesize = 200.0f;
GLfloat ratio = 1;

void drawLine(float x1, float y1, float z1, float x2, float y2, float z2)
{
glBegin(GL_LINES);
glVertex3f(x1, y1, z1);
glVertex3f(x2, y2, z2);
glEnd();
glFlush();
}

// 绘制立方体
void DrawCube(void)
{
int i, j;
glBegin(GL_LINES);
for (i = 0; i < 12; ++i) // 12 条线段
{
for (j = 0; j < 2; ++j) // 每条线段 2个顶点
{
glVertex3fv(vertex_list[index_list[i][j]]);
}
}
glEnd();
glFlush();
}

void reshapeOperate()
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (ratio < 1)
glOrtho(-coordinatesize, coordinatesize, -coordinatesize / ratio, coordinatesize / ratio, -coordinatesize, coordinatesize);
else
glOrtho(-coordinatesize*ratio, coordinatesize*ratio, -coordinatesize, coordinatesize, -coordinatesize, coordinatesize);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void reshape(int w, int h)
{
if ((w == 0) || (h == 0))
return;

glViewport(0, 0, w, h);

ratio = (GLfloat)w / (GLfloat)h;

reshapeOperate();
}

GLfloat AngleX = 45.0f;
GLfloat AngleY = 315.0f;

void reshape1(int w, int h)
{
GLfloat aspect = (GLfloat)w / (GLfloat)h;
GLfloat nRange = 100.0f;

glViewport(0, 0, w, h);

glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影模式
glLoadIdentity();

//设置三维投影区

if (w <= h)
{
glOrtho(-nRange, nRange, -nRange * aspect, nRange * aspect, -nRange, nRange);
}
else
{
glOrtho(-nRange, nRange, -nRange / aspect, nRange / aspect, -nRange, nRange);
}
}

void onDraw(void*)
{
// Draw something using OpenGL here
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除所有的像素

//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
//glPushMatrix();

////glTranslatef(-0.2, 0, 0); // 平移
////glScalef(2, 1, 1); // 缩放

//glRotatef(xRotAngle, 1.0f, 0.0f, 0.0f);
//glRotatef(yRotAngle, 0.0f, 1.0f, 0.0f);
//glRotatef(zRotAngle, 0.0f, 0.0f, 1.0f);

//glColor3f(1, 0, 0);
//drawLine(0, 0, 0, MAX_X, 0, 0); //x轴

//glColor3f(0, 1, 0);
//drawLine(0, 0, 0, 0, MAX_Y, 0); //y轴

//glColor3f(0, 0, 1);
//drawLine(0, 0, 0, 0, 0, MAX_Z); //z轴

//times++;
//if (times > 1)
//{
// times = 0;
//}

//if (times % 1 == 0)
//{
// rotate += 0.3;
//}

//glRotatef(rotate, 0, 1, 0);
//glRotatef(rotate, 1, 0, 0);

//glColor3f(0, 1, 1);

//DrawCube();

//glPopMatrix();

reshape1(windowWidth, windowHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
AngleX++;
AngleY++;
glPushMatrix();
{
glRotatef(AngleX, 1.0f, 0.0f, 0.0f);
glRotatef(AngleY, 0.0f, 1.0f, 0.0f);

glBegin(GL_POLYGON); //前表面
glColor3ub((GLubyte)255, (GLubyte)255, (GLubyte)255);//颜色设置为白色
glVertex3f(50.0f, 50.0f, 50.0f);

glColor3ub((GLubyte)255, (GLubyte)255, (GLubyte)0);//颜色设置为黄色
glVertex3f(50.0f, -50.0f, 50.0f);

glColor3ub((GLubyte)255, (GLubyte)0, (GLubyte)0);//颜色设置为红色
glVertex3f(-50.0f, -50.0f, 50.0f);

glColor3ub((GLubyte)255, (GLubyte)0, (GLubyte)255);//颜色设置为白色
glVertex3f(-50.0f, 50.0f, 50.0f);
glEnd();

glBegin(GL_POLYGON); //后表面
glColor3f(0.0f, 1.0f, 1.0f);//颜色设置为青色
glVertex3f(50.0f, 50.0f, -50.0f);

glColor3f(0.0f, 1.0f, 0.0f);//颜色设置为绿色
glVertex3f(50.0f, -50.0f, -50.0f);

glColor3f(0.0f, 0.0f, 0.0f);//颜色设置为黑色
glVertex3f(-50.0f, -50.0f, -50.0f);

glColor3f(0.0f, 0.0f, 1.0f);//颜色设置为蓝色
glVertex3f(-50.0f, 50.0f, -50.0f);
glEnd();

glBegin(GL_POLYGON); //上表面
glColor3d(0.0, 1.0, 1.0);//颜色设置为青色
glVertex3f(50.0f, 50.0f, -50.0f);

glColor3d(1.0, 1.0, 1.0);//颜色设置为白色
glVertex3f(50.0f, 50.0f, 50.0f);

glColor3d(1.0, 0.0, 1.0);//颜色设置为品红色
glVertex3f(-50.0f, 50.0f, 50.0f);

glColor3d(0.0, 0.0, 1.0);//颜色设置为蓝色
glVertex3f(-50.0f, 50.0f, -50.0f);
glEnd();

glBegin(GL_POLYGON); //下表面
glColor3ub(0u, 255u, 0u);//颜色设置为绿色
glVertex3f(50.0f, -50.0f, -50.0f);

glColor3ub(255u, 255u, 0u);//颜色设置为黄色
glVertex3f(50.0f, -50.0f, 50.0f);

glColor3ub(255u, 0u, 0u);//颜色设置为红色
glVertex3f(-50.0f, -50.0f, 50.0f);

glColor3ub(0u, 0u, 0u);//颜色设置为黑色
glVertex3f(-50.0f, -50.0f, -50.0f);
glEnd();

glBegin(GL_POLYGON); //左表面
glColor3ub((GLubyte)255, (GLubyte)255, (GLubyte)255);//颜色设置为白色
glVertex3f(50.0f, 50.0f, 50.0f);

glColor3ub((GLubyte)0, (GLubyte)255, (GLubyte)255);//颜色设置为青色
glVertex3f(50.0f, 50.0f, -50.0f);

glColor3ub((GLubyte)0, (GLubyte)255, (GLubyte)0);//颜色设置为绿色
glVertex3f(50.0f, -50.0f, -50.0f);

glColor3ub((GLubyte)255, (GLubyte)255, (GLubyte)0);//颜色设置为黄色
glVertex3f(50.0f, -50.0f, 50.0f);
glEnd();

glBegin(GL_POLYGON); //右表面
glColor3f(1.0f, 0.0f, 1.0f);//颜色设置为品红色
glVertex3f(-50.0f, 50.0f, 50.0f);

glColor3f(0.0f, 0.0f, 1.0f);//颜色设置为蓝色
glVertex3f(-50.0f, 50.0f, -50.0f);

glColor3f(0.0f, 0.0f, 0.0f);//颜色设置为黑色
glVertex3f(-50.0f, -50.0f, -50.0f);

glColor3f(1.0f, 0.0f, 0.0f);//颜色设置为红色
glVertex3f(-50.0f, -50.0f, 50.0f);
glEnd();
}
glPopMatrix();
}

void opencvWithOpenGLTest()
{
std::string openGLWindowName = "OpenGL Test";
cv::namedWindow(openGLWindowName, cv::WINDOW_OPENGL);
cv::resizeWindow(openGLWindowName, windowWidth, windowHeight);
cv::setOpenGlContext(openGLWindowName);
cv::setOpenGlDrawCallback(openGLWindowName, onDraw, NULL);

while (cv::waitKey(30) != 27)
{
cv::updateWindow(openGLWindowName); // when needed
}
}

int main(int argc, char *argv[])
{
opencvWithOpenGLTest();

return 0;
}

运行成功后可看到一个旋转的彩色立方体。

结论

  从实验结果来看,OpenCV 确实能支持 OpenGL 图形的显示,但其不足之处也很明显:没有提供鼠标和键盘的交互操作(可能是 Shaun 还没发现,毕竟只是尝试一下看它能不能显示),仅仅只是提供一个显示窗口。如果真想用 OpenGL 做一些好玩的东西,还是用 glut 和 glew 吧,不过 glut 已经停止更新许久,glew 在调试时可能会出现一些莫名其妙的错误,所以网上有人用 freeglut 代替 glut,glee 代替 glew,具体的东西 Shaun 也没试过,Shaun 目前还没做过 OpenGL 相关的事,这次用 OpenCV 显示 OpenGL 图形纯粹是为了好玩 (*^__^ *) 嘻嘻……。

后记

  本篇文档也是上次编译配置完 OpenCV-3.2 后做的一次小实验,但当时并没有记录,所以还有一些参考资料也已经不知道了 :-(。

参考资料

[1] OpenCV学习笔记(六十一)——建立支持OpenGL的OpenCV工程“Master OpenCV”chp.3http://blog.csdn.net/yang_xian521/article/category/910716

[2] 几个opengl立方体绘制案例http://blog.csdn.net/bcbobo21cn/article/category/3104565

Win10+VS2013+CMake-gui编译和配置OpenCV-3.2.0

Shaun 的系统环境:Win10_x64 英文企业版;VS2013-update5 英文旗舰版;CMake-3.6.3-win64-x64 免安装版;Qt-opensource-windows-x86-msvc2013-5.6.2。

  *注:Shaun 写的这篇文档主要用来编译 x86 版的动态 debug 库,想编译其它类型的库请自行参考其它资料,做相关改变。( 其实如果想编译 x64 版的可以在用 VS2013 编译时将上方的 Win32 平台选择 x64 平台;想编译 release 版的可以在用 VS2013 编译时将上方的 Debug 模式选择 Release 模式;想编译静态库的可以在用 CMake 生成时取消勾选 BUILD_SHARED_LIBS 选项即可。:-P )

前言

  因为 OpenCV-3.2 官方的 release 版只有支持 VS2015 的库,而且不包括扩展包( opencv_contrib )中的库,而由于某些历史原因,Shaun 目前使用的编译器还是 VS2013,又想用用扩展包中一些有趣的算法,在加上上个月 opencv-3.3 还没有正式 release,所以上个月 Shaun 就利用 VS2013 对 opencv-3.2 进行编译。具体编译过程如下:

Shaun 的系统环境:Win10_x64 英文企业版;VS2013-update5 英文旗舰版;CMake-3.6.3-win64-x64 免安装版;Qt-opensource-windows-x86-msvc2013-5.6.2。

  *注:Shaun 写的这篇文档主要用来编译 x86 版的动态 debug 库,想编译其它类型的库请自行参考其它资料,做相关改变。( 其实如果想编译 x64 版的可以在用 VS2013 编译时将上方的 Win32 平台选择 x64 平台;想编译 release 版的可以在用 VS2013 编译时将上方的 Debug 模式选择 Release 模式;想编译静态库的可以在用 CMake 生成时取消勾选 BUILD_SHARED_LIBS 选项即可。:-P )

前言

  因为 OpenCV-3.2 官方的 release 版只有支持 VS2015 的库,而且不包括扩展包( opencv_contrib )中的库,而由于某些历史原因,Shaun 目前使用的编译器还是 VS2013,又想用用扩展包中一些有趣的算法,在加上上个月 opencv-3.3 还没有正式 release,所以上个月 Shaun 就利用 VS2013 对 opencv-3.2 进行编译。具体编译过程如下:

准备篇

  先在 GitHub 上下载对应的 opencv 源码包:opencv-3.2.0opencv_contrib-3.2.0https://github.com/opencv),扩展包版本一定要和 opencv 版本相同。Shaun 为了添加 Qt 后端显示支持(为了好看和方便 :-P),所以还下载安装了支持 VS2013 的 Qt-5.6.2http://download.qt.io/archive/qt/)。再下载 CMake-3.6.3-win64-x64 免安装版https://cmake.org/files/)。至于微软的东西,推荐直接去 MSDN 我告诉你去下载。

  由于网上有的资料(具体是哪篇文章 Shaun 忘记了 o(╯□╰)o)说编译时的文件结构可能会影响编译是否成功,再加上为了方便编译管理,Shaun 编译时的文件结构为:

opencv-3.2.0_build
├── build
└── sources
​   ├── opencv-3.2.0
​   └── opencv_contrib-3.2.0

4 directories, 0 files

其中 opencv-3.2.0 用来装 opencv-3.2.0.zip 解压后的源码;opencv_contrib-3.2.0 用来装opencv_contrib-3.2.0.zip 解压后的源码;build 用来装 CMake 编译完成后的文件。

编译篇

  打开 /cmake-3.6.3-win64-x64/bin/cmake-gui.exe,在 Where is the source code 文本框中选择 /opencv-3.2.0_build/sources/opencv-3.2.0;在 Where to build the binaris 文本框中选择 /opencv-3.2.0_build/build,点击 Configure,在弹出的编译器选择框中选择 Visual Studio 12 2013,一直 Configure 直到红色的条变白。

  网上有人在这一步可能会出现ffmpeg not downloaded“ippicv_windows_20151201.zip”not downloaded这两个问题,Shaun 没出现这两个问题,所以没有机会验证 cmake-gui和vs2013编译opencv和opencv_contrib源码 中的解决办法是否正确。

  接下来就是添加扩展包,在白色条中找到 OPENCV_EXTRA_MODULES_PATH 文本框,在其中选择 opencv_contrib 源码中 modeles 所在路径:/opencv-3.2.0_build/sources/opencv_contrib-3.2.0/modules。

  至于想要支持 OpenGL 和 Qt 就需要勾选 WITH_OPENGLWITH_QTConfigure 后选择好 Qt 的安装目录,如果配置好 Qt 的环境变量 Cmake 将会自动选择好 Qt 所在路径。

  随后再次反复 Configure 直到界面不再出现红色背景,之后单击 Generate。不出意外的话,你会看到 Configure doneGenerate done

  Shaun 在这一步出现了 VS2013_CMake_opencv3.1动态库与静态库的配置与编译 中的问题,原因是同时勾选了同时勾选了 BUILD_opencv_worldBUILD_opencv_contirb_world,Shaun 的解决办法是将它们全部取消勾选,再次 ConfigureGenerate

  如果上面一切顺利的话就可以进行下一步了:使用 VS2013 编译 OpenCV。打开 /opencv-3.2.0_build/build 目录,将会看到一大堆文件和文件夹,双击 /opencv-3.2.0_build/build 目录下的 OpenCV.sln,用 VS2013 打开。找到 CMakeTargets 中的 INSTALL ,然后右键选择“Project Only”-->“Build Only INSTALL”。

漫长的等待。。。。。。 (╯﹏╰)b

  Shaun 在这一步出现了一个问题,具体问题和解决方法详见问题篇。

  一切顺利的话,应该会比 Shaun 下面的库多两个,Shaun 最后生成的 Debug 库为:

opencv_aruco320d.lib

opencv_bgsegm320d.lib

opencv_bioinspired320d.lib

opencv_calib3d320d.lib

opencv_ccalib320d.lib

opencv_core320d.lib

opencv_datasets320d.lib

opencv_dnn320d.lib

opencv_dpm320d.lib

opencv_face320d.lib

opencv_features2d320d.lib

opencv_flann320d.lib

opencv_fuzzy320d.lib

opencv_highgui320d.lib

opencv_imgcodecs320d.lib

opencv_imgproc320d.lib

opencv_line_descriptor320d.lib

opencv_ml320d.lib

opencv_objdetect320d.lib

opencv_optflow320d.lib

opencv_phase_unwrapping320d.lib

opencv_photo320d.lib

opencv_plot320d.lib

opencv_reg320d.lib

opencv_rgbd320d.lib

opencv_saliency320d.lib

opencv_shape320d.lib

opencv_stereo320d.lib

opencv_stitching320d.lib

opencv_structured_light320d.lib

opencv_superres320d.lib

opencv_surface_matching320d.lib

opencv_text320d.lib

opencv_tracking320d.lib

opencv_video320d.lib

opencv_videoio320d.lib

opencv_videostab320d.lib

opencv_xfeatures2d320d.lib

opencv_ximgproc320d.lib

opencv_xobjdetect320d.lib

opencv_xphoto320d.lib

共41个。

配置篇

  因为 Shaun 只编译了 x86 版动态 debug 库,所以以下环境配置都只针对 x86 版动态 debug 库。(其实要配置 x64 的库就只需将 x86 换成 x64 即可;要配置 release 模式的库就只需在添加附加依赖项中的库文件选择 release 模式的库(即数字后没有 d的 lib);若要配置静态库就需要选择静态库文件夹以及在附加依赖项中添加相应的静态库文件。:-P)

  首先把 /opencv-3.2.0_build/build/install 中的文件都提取出来,这和 OpenCV 官方 release 的 opencv 文件结构差不多,具体两层结构如下

.
├── bin
│  └── opencv_waldboost_detectord.exe
├── etc
│  ├── haarcascades
│  └── lbpcascades
├── include
│  ├── opencv
│  └── opencv2
├── LICENSE
├── OpenCVConfig.cmake
├── OpenCVConfig-version.cmake
└── x86
​   └── vc12

9 directories, 4 files

x86 文件夹就是 VS2013 生成的对应 VS 版本 32位 的各种库,include 文件夹就是 opencv 的各项模块。Shaun 将其中提取出的文件全部放入了 C:\Program Files\OpenCV\3.2.0\build 文件夹中。

  首先配置环境变量,系统(或用户)环境变量如下:

变量名变量值
PathC:\Program Files\OpenCV\3.2.0\build\x86\vc12\bin
OPENCVC:\Program Files\OpenCV\3.2.0\build

不然可能会报错:程序“XXXXXX”已退出,返回值为 -1073741701 (0xc000007b)。其中下面那行可以选择不要添加。

  然后在 VS 中配置环境。新建工程,然后在“属性管理器”中对应项目下 Debug | Win32 文件夹右键“添加新项目属性表”。(方便一次配置,多次使用,以后再使用只要在相应项目下右键“添加现有属性表”即可),Shaun 新项目属性表取名为:opencv-3.2.0_msvc2013_x86d.props。

接下来就是真正的 VS 环境配置了:

  双击打开刚才新建的属性表,选中“VC++目录”,注意在进行以下配置时建议都勾选左下角的“从父级或项目默认设置继承

可执行文件目录”中添加:

C:\Program Files\OpenCV\3.2.0\build\x86\vc12\bin

包含目录”中添加:

C:\Program Files\OpenCV\3.2.0\build\include

C:\Program Files\OpenCV\3.2.0\build\include\opencv

C:\Program Files\OpenCV\3.2.0\build\include\opencv2

库目录”中添加:

C:\Program Files\OpenCV\3.2.0\build\x86\vc12\lib

选中“链接器” –> “常规”,“附加库目录”中添加:

C:\Program Files\OpenCV\3.2.0\build\x86\vc12\lib

链接器” –> “输入”,“附加依赖项”中添加 C:\Program Files\OpenCV\3.2.0\build\x86\vc12\lib 中数字后带 d 的库文件,即编译篇中 Shaun 最后生成的 41 个库文件。

  配置完之后不要忘了右键该属性表进行保存处理,以便下个项目直接使用,不需要再重复进行配置。

最后附示例程序:

1
2
3
4
5
6
7
8
9
10
11
#include <opencv2/opencv.hpp>  

int main(int argc, char *argv[])
{
cv::Mat lena = cv::imread("lena.jpg"); //载入图像到Mat,jpg文件和该cpp在同一文件夹
cv::namedWindow("lena"); //创建一个名为 "lean"的窗口
cv::imshow("lena", lena); //显示名为 "lena"的窗口
cv::waitKey(5000); // 只对窗口机制起作用(显示5000ms,随后返回-1,即窗口关闭),若在此期间有按键按下,则马上返回按键的ASCII码。
//system("pause");
return 0;
}

这里必须在 imshow 后加入 waitkey,因为 WaitKey 不止是 Wait Key 而已,它其实还涉及到消息响应,有这个函数 cv 内部的 WndProc 函数才能起作用,才会更新窗口。

  最后程序运行成功并显示 lena 图,则说明编译和配置没问题。

问题篇

1、用 VS2013 编译 OpenCV 在漫长的等待阶段出现的问题。

  问题描述:CVV 模块报错,TS 模块编译不出来,好在这两个模块都不是很重要,可以忽略,Shaun 强迫症也没到这种程度 O(∩_∩)O~。

  解决办法: 在 CVV 模块报错后可在 CMake(不知道具体是 INSTALL 下的 CMake Rules 中的 INSTALL_force.rule,还是 ALL_BUILD 下的 CMakeLists.txt,忘记了 o(╯□╰)o)中添加 -DBUILD_opencv_cvv=OFF 忽略 CVV 模块,从而正常编译其它模块。参考 errors on build opencv with cvv module and qt5 #577。如果实在不行的话就在 CMake 生成的时候取消勾选出错模块,若是用 CMake 重新生成的话不要忘了先把 /opencv-3.2.0_build/build 目录下的文件全部删除干净。

后记

  这是以前写的两篇文档,现在再来整理成一篇。

附录

  既然能看到这里,说明是想在 VS 下使用 OpenCV,这里推荐一款 VS 下 OpenCV 开发调试神器:Image Watch,效果谁用谁知道。Image Watch 是 VS 的一个插件,不过它只支持 VS2012 及以上版本。使用方法为先设置断点( F9 ),随后在调试( F5 )模式下,鼠标指针悬停在 cv::Mat 类型变量上,即可出现 插件调试标签,点击查看图标即可显示相应图像。

参考资料

[1] cmake-gui和vs2013编译opencv和opencv_contrib源码http://livezingy.com/category/opencv/

[2] VS2013_CMake_opencv3.1动态库与静态库的配置与编译http://livezingy.com/category/opencv/

[3] 使用VS2015编译以及静态编译opencv3记录

[4] errors on build opencv with cvv module and qt5 #577

[5] VS2013中Image Watch插件的使用(OpenCV)http://blog.csdn.net/fengbingchun/article/category/721609

解决写上篇文档“Hexo+GitHub搭建个人博客”遇到的问题

超链接网址问题

  问题描述:使用正常的 markdown 超链接格式[]()没问题,然而当直接将一个网址链接放入该文档时,它会将该链接后面的文字也当成是该链接的一部分,直接点击链接时,会将后面的文字也放入浏览器地址栏,从而出现网页 404 错误:404: Page could not be found

  解决办法:在网址链接后输入一个空格以隔开网址链接和后面的文字或用<url>将网址括起来。

超链接网址问题

  问题描述:使用正常的 markdown 超链接格式[]()没问题,然而当直接将一个网址链接放入该文档时,它会将该链接后面的文字也当成是该链接的一部分,直接点击链接时,会将后面的文字也放入浏览器地址栏,从而出现网页 404 错误:404: Page could not be found

  解决办法:在网址链接后输入一个空格以隔开网址链接和后面的文字或用<url>将网址括起来。

超链接样式问题

  问题描述:Shaun 使用的 hexo 主题是基于 spfk 主题稍微修改过的,spfk 主题能自动修改超链接原有的样式,挺好看的 :D,但是当 Shaun 在 markdown 中数字编号列表,即有序列表中添加超链接时,其样式并没有修改,还是普通的超链接样式。

  解决办法:没有解决。最后只是跳过了这个问题,就用中文的序号表示列表。

文本段落问题

  问题描述:为了使文本有段落感,一般都会在段落首字前空两格,但是在 markdown 中空两格,用 hexo 发布后并没有空两格,这使得文档没有段落感,阅读体验有点差。

  解决办法:将中文输入法由半角切换至全角,在段落首字前输入两个空格即可。

显示英文尖括号问题

  问题描述:由于上篇文档需要在文档中显示<youname>,但由于 Hexo 可能将其当做一个 xml 标签处理了,所以发布之后的文档没有显示该文字。

  解决办法:首先 Shaun 尝试了转义字符\,谁曾想它只出现了一个转义字符,该文字还是没显示,Shaun 差点又要跳过这个问题,将其用另一种表示法了。后来 Shaun 想到这最后不是会转为 html 吗,Shaun 就直接用 html 中尖括号的表示法不就行啦 :p,于是参考HTML语言中括号(尖括号)的字符编码,用&lt;代替<,用&gt;代替>,最后该文字终于出来了。

给文字添加颜色问题

  问题描述:Shaun 想给注意事项上的需要注意的问题添加醒目的颜色,但 markdown 本身不支持给文字添加颜色。

  解决办法:由于 Hexo 最后会将 markdown 文档转换为 html 文档发布,所以直接将 html 标签写进 markdown 文档,最后自然会出现 html 样式,Shaun 这里参考CSDN-markdown编辑器语法——字体、字号与颜色,给想要变色的文字添加<font color=#FA8072></font>标签。

参考资料

[1] HTML语言中括号(尖括号)的字符编码http://liuxufei.com/weblog/jishu

[2] CSDN-markdown编辑器语法——字体、字号与颜色http://blog.csdn.net/testcs_dn

Hexo+GitHub搭建个人博客

Shaun 的系统环境:Win10_x64。

前言

  本来是想在国内某网站上继续写的,毕竟完全不需要自己管理,只需要负责写好文档就可以了,但某一天,该网站由于响应国家的号召,要实名验证,本来实名验证也没什么,就输入手机号,并填写验证码即可,但该网站实名验证的方式给人的感觉特别不爽,于是就决定自己搭建博客,这样虽然有点麻烦,但由于完全是自己管理,自己完全拥有该文档的所有权,也不用担心哪天别的网站突然出现的各种破问题,相比这种完全自由支配、无比爽快的感觉,管理这种麻烦就是小事了。

Shaun 的系统环境:Win10_x64。

前言

  本来是想在国内某网站上继续写的,毕竟完全不需要自己管理,只需要负责写好文档就可以了,但某一天,该网站由于响应国家的号召,要实名验证,本来实名验证也没什么,就输入手机号,并填写验证码即可,但该网站实名验证的方式给人的感觉特别不爽,于是就决定自己搭建博客,这样虽然有点麻烦,但由于完全是自己管理,自己完全拥有该文档的所有权,也不用担心哪天别的网站突然出现的各种破问题,相比这种完全自由支配、无比爽快的感觉,管理这种麻烦就是小事了。

GitHub + Hexo 个人博客搭建

准备篇

在 GitHub 上搭建博客的要求:

  1、要有 GitHub 账号。(没有怎么办,没有就去注册啊)

使用 Hexo 框架的要求:

  1、需要安装 node.js。(电脑上没有安装怎么办,没有安装就去下载https://nodejs.org/en/download/)安装啊)

  2、需要安装 git。(没有安装就去下载安装,附 git学习教程

GitHub 篇

  满足上文的要求之后,就可以开始搭建了,首先在 GitHub 中新建一个仓库( New repository ),在 Repository name 下填写 <yourname>.github.io ,其它可默认,点击 Create repository。

  新建仓库完成后,点击 Create new file 新建一个 README.md 文件,随便写点什么,比如 “It's my blog website”。

  点击上方横条选项中的 Settings ,查看 GitHub Pages 里的设置,上方应该有绿色框,框中“Your site is published at https://<yourname>.github.io”,该网址即为博客主页,Source 应该是 master branch,自此 GitHub 上的设置可以算是完成了,但为了方便和防止误删,一般把 Hexo 文件也放入 GitHub 中,为方便管理,可以新建另一分支专门放 Hexo 文件。

  在仓库 code 界面中点击 Branch:master,在出现的框中输入 hexo 新建 hexo 分支,在 branchesChange default branch 设置 hexo 为默认分支。

Hexo 篇

  将刚才新建的仓库克隆到本地:git clone https://github.com/<yourname>/<yourname>.github.io.git当前在 hexo 分支。

在 <yourname>.github.io 文件夹下执行

1
2
3
4
5
npm install hexo-cli -g
hexo init blog
cd blog
npm install
npm install hexo-deployer-git --save

  按这样一连串执行,如果没出问题的话就会在 <yourname>.github.io 文件夹里生成一个 blog 文件夹,该文件夹有一大堆 Hexo 有关的文件。

配置 Hexo

  Hexo 的配置文件为 blog 文件夹中的 _config.yml 文件。

  修改配置文件不要使用 windows 自带的记事本,Shaun 使用的 VS Code,或者 Notepad++ 和 Sublime Text 2 等编辑器都可以,以防文件编码改变,具体修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Site
title: <你的blog名>
author: <作者名称>
language: zh-CN<网站所用语言,中国大陆选择zh-CN即可>

# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: http://<yourname>.github.io

# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repo: https://github.com/<yourname>/<yourname>.github.io.git
branch: master

其它的默认即可,具体参数信息详见 Hexo官方文档

配置 git 用户信息

1
2
git config --global user.name "<yourname>"
git config --global user.email "<yourname>@xxxxxx.com"

  如果是个人电脑的话推荐加上 --global 全局参数,因为这样更加方便,如果不加的话,还要在 \<yourname>.github.io\.deploy_git\.git 中 config 里加入 git 用户信息,不然可能提交会出问题,稍显麻烦。

部署 Hexo

在 blog 文件夹下执行:

1
2
3
hexo g         #generate 生成静态文件
hexo d #deploy 部署网站.部署网站前,需要预先生成静态文件
hexo s #server 启动服务器

或者执行:

1
hexo g -d

快速部署个人 blog。

  在浏览器中输入http://localhost:4000/,将会出现 Hexo 的 Hello World 界面,更多 Hexo 命令详见 Hexo官方文档

最后将 Hexo 文件提交到 GitHub 远程仓库,具体提交命令为:

1
2
3
git add .
git commit
git push origin hexo

  在浏览器中输入https://<yourname>.github.io同样会出现 Hexo 的 Hello World 界面,自此整个个人 blog 的框架已经完全搭好了。

其它篇

主题选择

  主题可以去官网上的主题界面去找,目前比较受欢迎主题有 nextyilia,去别人 GitHub 上的主题仓库上去下载或 clone 均可,Shaun 目前用的主题为black-blue,这个主题 Shaun 在用的时候还有些问题,或许会换,或许会自己魔改。最后由于术业有专攻,实在不知道该改哪里,所以决定换 black-blue 的原版主题 SPFK ,对照着 black-blue 对 spfk 进行修改。具体换主题的方法为:

  先将下载好的主题整个放在 \blog\themes 文件夹中,再修改 blog 文件夹中的配置文件 _config.yml

1
2
# theme: landscape
theme: black-blue

  black-blue 为打包主题文件并放入 \blog\themes 文件夹中的文件夹名,并不是原主题名,只是 Shaun 恰好将其重命名为主题名。

文章发布

发布文章需要在 blog 文件夹中执行:

1
hexo new "test"

  将会在 _posts 文件夹中生成 test.md 文件,随后编辑 test.md 文件即可,Shaun 使用的 Markdown 编辑器为 Typora

至于给文章打标签和分类什么的,请参考 Hexo官方文档

写完文章之后推送到 GitHub 中,需要执行:

1
2
3
git add .
git commit -m "add test.md"
git push origin hexo

Hexo 文件配置同样需要同步一下:

1
2
3
hexo g
hexo clean
hexo d

插件添加

以 RSS 订阅插件为例。首先安装 hexo-generator-feed,在 blog 文件夹下执行:

1
2
## rss插件
npm install hexo-generator-feed --save

安装成功后,修改 blog 文件夹中的配置文件 _config.yml

1
2
3
4
# Extensions
## Plugins: https://hexo.io/plugins/
plugin:
- hexo-generator-feed #RSS订阅

最后,修改当前主题文件夹中的配置文件 _config.yml,添加 RSS 订阅链接即可:

1
2
subnav:
rss: "/atom.xml"

修改完成后,执行

1
2
3
hexo clean
hexo g
hexo d

将会在页面中看到 RSS 图标。

注意事项

1、提交至远程仓库时可能会出现错误

  原因可能是因为没有将 SSH Key 添加到 GitHub 中。

  查看当前用户主目录下的 .ssh 文件夹中( windows 是 C:\Users\<username>\.ssh)是否有id_rsa(私钥)和id_rsa.pub(公钥)这两个文件,若没有,则执行

1
ssh-keygen -t rsa -C "youremail@example.com"

  在 GitHub 中添加 SSH Key 的具体方法为:点击 GitHub 用户头像下的 Settings,选中 SSH and GPG keys,点击 New SSH key,将id_rsa.pub中的内容复制粘贴到 Key文本框中。

2、Hexo 生成和部署命令都执行失败

  原因可能是修改配置文件 _config.yml 出错。

  将修改的配置文件 _config.yml 复原试试。

3、Hexo 部署之后网页没变化

可能需要执行

1
hexo clean

  清除缓存文件 ( db.json ) 和已生成的静态文件 ( public )。在某些情况(尤其是更换主题后),如果发现对站点的更改无论如何也不生效,可能需要运行该命令。

后记

  以后就在这上面写 blog 了,顺便把以前写的一些文档也放上来。

参考资料

[1] 利用github+hexo搭建自己的博客http://blog.csdn.net/u012150360/article/category/6765461

[2] Hexo官方文档https://hexo.io/zh-cn/

[3] GITHUB+HEXO博客轻松更换主题外观http://www.jianshu.com/nb/10649566

[4] Hexo—正确添加RSS订阅http://hanhailong.com/tags/Hexo%E4%B8%BB%E9%A2%98/