- 地址 http://makelrc.imjs.work,除了保存 LRC 歌词功能以外,其他纯前端,所以不提供源码了。Ctrl+s 下来应该也能用吧。。。就是不要扒下来改版权然后扔到自己空间上,要是被我发现,必定追究。预览功能用的 http://www.ikk.me 的播放器,版权已留。
终于把这播放器做出来了。。。
**2014.07.10 更新
修复以下两项严重错误:
- add_lrc() 传参错误
- 没有深入了解 lrc 文件标准,感谢 http://www.zhixing123.cn/jsp/js-lrc.html 提供参考文章**
可以像 http://futa.ooo/1648.html 一样,用 playerid.add_lrc() 手动添加歌词,也可以用 add_lrc() 添加 lrc 格式歌词,更可以使用 get_lrc() 获取百度音乐的 lrc 歌词。。。
使用方法
1 | get_lrc(name,singer,playerid); |
1 | add_lrc(lrc_data,playerid); |
手动添加的。。。看前面链接的那篇文章吧
例子:http://lab.imjs.work/getlrc/test.html
附源码
test.html1
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<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"/>
<script src="get_lrc.js"></script>
<style>
/*
* Lyric support by kookxiang(http://ikk.me)
*/
.kk_player { width: 100%; max-height: 40px; }
.kk_lrc { height: 125px; overflow: auto; padding: 0; margin: 0; }
.kk_lrc li { display: block; text-align: center; color: gray; line-height: 20px; margin: 2px 0 3px 0; min-height: 20px; }
.kk_lrc .current { color: black; font-weight: bold; }
.kk_lrc, .kk_lrc * { -webkit-transition-duration: 1s; -moz-transition-duration: 1s; transition-duration: 1s; }
.kk_lrc ::selection { background: transparent; background: rgba(127, 127, 127, 0.1); }
.kk_lrc_box { position: relative; }
.kk_lrc_box:before { content: '.'; overflow: hidden; text-indent: -9999px; width: 100%; height: 30px; z-index: 1; display: block; position: absolute; background: url(cover.png) repeat-x 0 0; top: 0; pointer-events: none; }
.kk_lrc_box:after { content: '.'; overflow: hidden; text-indent: -9999px; width: 100%; height: 30px; z-index: 1; display: block; position: absolute; background: url(cover.png) repeat-x 0 100%; bottom: 0; pointer-events: none; }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { -webkit-border-radius: 10px; border-radius: 10px; }
::-webkit-scrollbar-thumb { -webkit-border-radius: 10px; border-radius: 10px; background: rgba(96, 96, 96, 0.8); -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); }
::-webkit-scrollbar-thumb:window-inactive { background: rgba(96, 96, 96, 0.4); }
</style>
</head>
<body>
<pre>get_lrc() 方法</pre>
<audio class="kk_player" controls="true" id="kk_lrc_hongdou" src="http://lab.imjs.work/getlrc/hongdou.mp3" preload="metadata">您的浏览器不支持HTML5的 audio 标签,无法为您播放!</audio><br />
<div class="kk_lrc_box"><ul id="kk_lrc_hongdou_lrc" class="kk_lrc">
<li></li><li></li><li></li>
</ul></div>
<script>
get_lrc('红豆','王菲','hongdou');
</script>
<pre>add_lrc() 方法</pre>
<audio class="kk_player" controls="true" id="kk_lrc_hongqingting" src="http://lab.imjs.work/getlrc/hongqingting.mp3" preload="metadata">您的浏览器不支持HTML5的 audio 标签,无法为您播放!</audio><br />
<div class="kk_lrc_box"><ul id="kk_lrc_hongqingting_lrc" class="kk_lrc">
<li></li><li></li><li></li>
</ul></div>
<script>
add_lrc("[ti:红蜻蜓]<br />[ar:小虎队]<br />[al:红蜻蜓]<br />[00:00.00]红蜻蜓<br />[00:04.84]词:长郑刚 曲:李子恒<br />[00:08.85]演唱:小虎队<br />[02:09.02][00:32.74]飞呀 飞呀<br />[02:10.22][00:33.82]看那红色蜻蜓飞在蓝色天空<br />[02:13.52][00:37.33]游戏在风中不断追逐他的梦<br />[02:17.90][00:41.59]天空是永恒的家 大地就是他的王国<br />[02:21.88][00:45.56]飞翔是生活<br />[02:26.18][00:49.96]我们的童年也像追逐成长吹来的风<br />[02:30.25][00:53.94]轻轻地吹着梦想 慢慢地升空<br />[02:34.64][00:58.24]红色的蜻蜓是我小时侯的小小英雄<br />[02:38.57][01:02.30]多希望有一天能和他一起飞<br />[02:42.92][01:06.57]当烦恼愈来愈多 玻璃弹珠愈来愈少<br />[02:46.85][01:10.62]我知道我已慢慢地长大了<br />[02:51.33][01:14.93]红色的蜻蜓曾几何时<br />[02:53.94][01:17.38]也在我岁月慢慢不见了<br />[03:33.66][02:59.98][01:23.59]我们都已经长大 好多梦正在飞<br />[03:41.68][03:08.18][01:31.83]就像童年看到地红色的蜻蜓<br />[03:50.09][03:16.59][01:40.38]我们都已经长大 好多梦还要飞<br />[03:58.47][03:24.83][01:48.52]就像现在心目中红色的蜻蜓<br />[04:05.06][01:55.12](music)<br />[04:34.64]End<br />[04:39.23]","hongqingting");
</script>
</body>
</html>
get_lrc.js1
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
168function get_lrc(name,singer,playerid) {
var script = document.createElement('script');
script.setAttribute('src', "http://lab.imjs.work/getlrc/?name="+encodeURIComponent(name)+"&singer="+encodeURIComponent(singer)+"&playerid="+encodeURIComponent(playerid)+"&callback=con_lrc");
//load javascript
document.getElementsByTagName('head')[0].appendChild(script);
return true;
}
function con_lrc(lrc_data,playerid) {
var err_msg={"-1":"服务器没有接收到完整数据","-2":"无法正常获取 xml 文件","-3":"找不到该曲目","-4":"未收录 lrc 歌词","-5":"无法正常获取 lrc 歌词"};
if (lrc_data.status=="error") {
console.error(err_msg[lrc_data.errcode]);
return false;
}
eval("var "+playerid+" = load_kk_lrc(\""+playerid+"\");");
for (i=0;i<lrc_data.result.length;i++) {
var lrcArray=lrc_data.result[i].split("<br />");
var timeKey=new Object();
var strArray=new Array();
for (var i = 0,l = lrcArray.length;i < l;i++) {
//正则匹配 删除[00:00.00]格式或者 [00:00:00]格式
//所有的 lrc 都应该 decode 一下,因为各种语言都可能有
clause = decodeURIComponent(lrcArray[i]).replace(/\[\d*?:\d*?[\.:]\d*?\]/g,'');
timeRegExpArr = decodeURIComponent(lrcArray[i]).match(/\[(\d*?):(\d*?)[\.:](\d*?)\]/g);
if (timeRegExpArr!=null) {
for (var k = 0,h = timeRegExpArr.length;k < h;k++) { //第一遍循环,JSON存储歌词,数组存储时间
_timeRegExpArr = timeRegExpArr[k].match(/^\[(\d*?):(\d*?)[\.:](\d*?)\]$/);
min = parseFloat(_timeRegExpArr[1]);
sec = parseFloat(_timeRegExpArr[2]);
msec = parseFloat(_timeRegExpArr[3]);
time=min * 60 + sec + msec/100;
if (!timeKey[time]) {
strArray.push(time);
timeKey[time] = clause + '<br />';
} else {
timeKey[time] += clause + '<br />';
}
}
}
}
strArray.sort(function(a,b) {
return a - b;
});
for (var i = 0,l = strArray.length;i < l;i++) { //第二遍循环,JSON存储时间,数组存储歌词
var tempIndex = strArray[i],
tempClause = timeKey[tempIndex];
console.log([tempIndex,tempClause]);
eval(playerid+".add_lrc(tempIndex,tempClause);");
}
}
eval(playerid+".init();");
return true;
}
function add_lrc(lrc_data,playerid) {
con_lrc({'status':'success','errcode':'0','result':[lrc_data.replace("\n","<br />")]},playerid);
return true;
}
/*
* Lyric support by kookxiang(http://ikk.me)
*/
function load_kk_lrc(playerid){
var kk_lrc = new Object();
kk_lrc.extra_top = 1;
kk_lrc.current = -1;
kk_lrc.current_obj;
kk_lrc.offset = 0;
kk_lrc.current_start = -1;
kk_lrc.next_update_time = -1;
kk_lrc.showtime = -1;
kk_lrc.lrc_offset = -1;
kk_lrc.lrc_height = -1;
kk_lrc.lrc = [];
kk_lrc.lrcobj = null;
kk_lrc.target = 0;
kk_lrc._target = 0;
kk_lrc.player_obj = document.getElementById('kk_lrc_' + playerid);
kk_lrc.lrc_obj = document.getElementById('kk_lrc_' + playerid + '_lrc');
kk_lrc.scroll_lrc = function () {
if(typeof kk_lrc.lrc[kk_lrc.current+2] != "undefined"){
for(id in kk_lrc.lrcobj) kk_lrc.lrcobj[id].className = '';
kk_lrc.lrcobj[kk_lrc.current+3].className = 'current';
}
kk_lrc.current_start = kk_lrc.lrc[kk_lrc.current];
kk_lrc.current++;
kk_lrc.current_obj = kk_lrc.lrcobj[kk_lrc.current+2];
kk_lrc.next_update_time = kk_lrc.lrc[kk_lrc.current];
kk_lrc.showtime = kk_lrc.next_update_time - kk_lrc.current_start;
kk_lrc.lrc_offset = kk_lrc.current_obj.offsetTop;
kk_lrc.lrc_height = kk_lrc.current_obj.offsetHeight;
};
kk_lrc.check_lrc_update = function () {
var curTime = kk_lrc.player_obj.currentTime;
if(curTime >= kk_lrc.next_update_time - 0.2){
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
}
if(typeof kk_lrc.lrc[kk_lrc.current-1] != "undefined"){
kk_lrc.extra_top = (kk_lrc.next_update_time - curTime) / kk_lrc.showtime;
}
kk_lrc.target = Math.round(kk_lrc.lrc_offset - (125 - kk_lrc.lrc_height) / 2);
if(kk_lrc.target < 0) kk_lrc.target = 0;
};
kk_lrc.init = function () {
kk_lrc.add_lrc('999999', '');
kk_lrc.add_lrc('999999', '');
kk_lrc.add_lrc('999999', '');
kk_lrc.current = -1;
kk_lrc.lrcobj = kk_lrc.lrc_obj.getElementsByTagName('li');
kk_lrc.current_obj = kk_lrc.lrcobj[0];
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
kk_lrc.player_obj.addEventListener("seeked" ,function(){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
});
kk_lrc.player_obj.addEventListener("durationchange" ,function(){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
});
setInterval(function(){
if(kk_lrc.player_obj.paused) return;
if(kk_lrc.current_start > kk_lrc.player_obj.currentTime){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
}else{
kk_lrc.check_lrc_update();
}
}, 100);
setInterval(function(){
if(kk_lrc._target == kk_lrc.target) return;
if(Math.abs(kk_lrc.lrc_obj.scrollTop - kk_lrc._target) > kk_lrc.lrc_height){
kk_lrc._target = kk_lrc.lrc_obj.scrollTop;
}
if(kk_lrc.player_obj.paused){
kk_lrc._target = kk_lrc.fixFloat(kk_lrc._target * 0.8 + kk_lrc.target * 0.2);
}else{
kk_lrc._target = kk_lrc.fixFloat(kk_lrc._target * 0.98 + kk_lrc.target * 0.02);
}
kk_lrc.lrc_obj.scrollTop = kk_lrc._target;
}, 5);
};
kk_lrc.add_lrc = function (time, lrc) {
kk_lrc.lrc.push(parseFloat(time) + kk_lrc.offset);
var lrc_line = document.createElement("li");
lrc_line.innerHTML = lrc;
kk_lrc.lrc_obj.appendChild(lrc_line);
};
kk_lrc.get_lrc = function (num) {
if(typeof kk_lrc.lrc[num] != "undefined"){
return kk_lrc.lrc[num][1];
}else{
return '';
}
}
kk_lrc.setoffset = function (num) {
kk_lrc.offset = num / 1000;
}
kk_lrc.fixFloat = function (num) {
return Math.ceil(num * 10) / 10;
}
return kk_lrc;
}
完整 Demo 下载:getlrc
关于百度音乐的 lrc 歌词 api
前段时间转了一个别人的 HTML5 音乐播放器,一个挺有意思的 html5 播放器,想着应该怎么改进一下,结果发现 lrc 歌词可以自动获取,例如可以使用百度音乐提供的 api,虽然度娘没公开,虽然收录的歌词有点少。。。
百度了一下,发现了篇文章,没想到还能用,百度MP3音乐API接口及应用,暑假正好闲着无聊,于是写了一个 lrc 歌词获取工具咳咳,返回 json 字符串或者 jsonp,具体可以看注释。
附测试链接 http://lab.imjs.work/getlrc/?name=%E7%AC%A8%E5%B0%8F%E5%AD%A9&singer;=%E5%88%98%E5%BE%B7%E5%8D%8E&callback;=test
P.S.
callback 参数非必需,若是同站可以不使用;playerid 同样可选
源码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
/**************************************************************************************/
/* 百度音乐 lrc 歌词获取工具 api */
/* 作者 admin@imjs.work */
/* 博客 http://futa.ooo */
/* 返回格式: json 或 jsonp 字符串 */
/* 包含参数: */
/* status,值为 success 或 error */
/* errcode, 值为 0,-1,-2,-3,-4,-5 */
/* 0 无错误 */
/* -1 为服务器没有接收到完整数据 */
/* -2 为无法正常获取 xml 文件 */
/* -3 为找不到该曲目 */
/* -4 为未收录 lrc 歌词 */
/* -5 为无法正常获取 lrc 歌词 */
/* result, 当 status=success 时返回 lrc 歌词数组 */
/* 请求参数: name 歌曲名, singer 歌手名, callback 回调函数(可选), playerid 可选 */
/**************************************************************************************/
header("Content-type: text/javascript; charset=utf-8");
function curl_get_contents($url) { //封装 curl
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 5); //超时五秒
$output = curl_exec($ch);
curl_close($ch);
if ($output===false) {
return false;
}
return $output;
}
function url_encode_array($val) { //递归处理数组
if (is_array($val)) {
foreach ($val as $k=>$v) {
$val[$k]=url_encode_array($v);
}
return $val;
} else {
return urlencode($val);
}
}
function output($result_array) { //输出函数
if ($_GET['playerid'] && $result_array['status']=='success') {
$playerid=htmlspecialchars($_GET['playerid']);
}
echo ($_GET['callback']?htmlspecialchars($_GET['callback']).'(':'').urldecode(json_encode(url_encode_array($result_array))).($_GET['callback']?(($playerid?(',\''.(get_magic_quotes_gpc()?$playerid:addslashes($playerid)).'\''):'').');'):'');
exit();
}
//function 部分到此结束
$name=rawurldecode($_GET['name']);
$singer=rawurldecode($_GET['singer']);
/*
$name='笨小孩';
$singer='刘德华';
*/
if ($name=='' || $singer=='') {
output(array('status'=>'error','errcode'=>-1));
}
$xml_data=curl_get_contents('http://box.zhangmen.baidu.com/x?op=12&count=1&title='.rawurlencode($name).'$$'.rawurlencode($singer).'$$$$');
if (!$xml_data) {
output(array('status'=>'error','errcode'=>-2));
}
if (preg_match("/<count>(\d*?)<\/count>/",$xml_data,$_count)) {
if ($_count[1]) {
preg_match_all("/<lrcid>(\d*?)<\/lrcid>/",$xml_data,$_lrcids);
$lrcid=array_unique($_lrcids[1]);
$lrc_data=array();
foreach ($lrcid as $id) {
if ($lrcid!='0') {
$_lrc=str_replace("\n","<br />",iconv('GBK','UTF-8',curl_get_contents('http://box.zhangmen.baidu.com/bdlrc/'.floor($id/100).'/'.$id.'.lrc')));
if (!$_lrc) {
output(array('status'=>'error','errcode'=>-5));
} else {
$lrc_data[]=$_lrc;
}
}
}
if (empty($lrc_data)) {
output(array('status'=>'error','errcode'=>-4));
} else {
output(array('status'=>'success','errcode'=>0,'result'=>$lrc_data),$_GET['callback']);
}
} else {
output(array('status'=>'error','errcode'=>-3));
}
} else {
output(array('status'=>'error','errcode'=>-2));
}
无聊帮童鞋做的 vb 作业
一个挺有意思的 html5 播放器
在 http://www.ikk.me 上看到的,lrc 歌词功能是亮点,于是把关键代码提出来放在这里,日后慢慢研究。
JavaScript: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/*
* Lyric support by kookxiang(http://ikk.me)
*/
function load_kk_lrc(playerid){
var kk_lrc = new Object();
kk_lrc.extra_top = 1;
kk_lrc.current = -1;
kk_lrc.current_obj;
kk_lrc.offset = 0;
kk_lrc.current_start = -1;
kk_lrc.next_update_time = -1;
kk_lrc.showtime = -1;
kk_lrc.lrc_offset = -1;
kk_lrc.lrc_height = -1;
kk_lrc.lrc = [];
kk_lrc.lrcobj = null;
kk_lrc.target = 0;
kk_lrc._target = 0;
kk_lrc.player_obj = document.getElementById('kk_lrc_' + playerid);
kk_lrc.lrc_obj = document.getElementById('kk_lrc_' + playerid + '_lrc');
kk_lrc.scroll_lrc = function () {
if(typeof kk_lrc.lrc[kk_lrc.current+2] != "undefined"){
for(id in kk_lrc.lrcobj) kk_lrc.lrcobj[id].className = '';
kk_lrc.lrcobj[kk_lrc.current+3].className = 'current';
}
kk_lrc.current_start = kk_lrc.lrc[kk_lrc.current];
kk_lrc.current++;
kk_lrc.current_obj = kk_lrc.lrcobj[kk_lrc.current+2];
kk_lrc.next_update_time = kk_lrc.lrc[kk_lrc.current];
kk_lrc.showtime = kk_lrc.next_update_time - kk_lrc.current_start;
kk_lrc.lrc_offset = kk_lrc.current_obj.offsetTop;
kk_lrc.lrc_height = kk_lrc.current_obj.offsetHeight;
};
kk_lrc.check_lrc_update = function () {
var curTime = kk_lrc.player_obj.currentTime;
if(curTime >= kk_lrc.next_update_time - 0.2){
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
}
if(typeof kk_lrc.lrc[kk_lrc.current-1] != "undefined"){
kk_lrc.extra_top = (kk_lrc.next_update_time - curTime) / kk_lrc.showtime;
}
kk_lrc.target = Math.round(kk_lrc.lrc_offset - (125 - kk_lrc.lrc_height) / 2);
if(kk_lrc.target < 0) kk_lrc.target = 0;
};
kk_lrc.init = function () {
kk_lrc.add_lrc('999999', '');
kk_lrc.add_lrc('999999', '');
kk_lrc.add_lrc('999999', '');
kk_lrc.current = -1;
kk_lrc.lrcobj = kk_lrc.lrc_obj.getElementsByTagName('li');
kk_lrc.current_obj = kk_lrc.lrcobj[0];
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
kk_lrc.player_obj.addEventListener("seeked" ,function(){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
});
kk_lrc.player_obj.addEventListener("durationchange" ,function(){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
});
setInterval(function(){
if(kk_lrc.player_obj.paused) return;
if(kk_lrc.current_start > kk_lrc.player_obj.currentTime){
kk_lrc.current = -1;
kk_lrc.scroll_lrc();
kk_lrc.check_lrc_update();
}else{
kk_lrc.check_lrc_update();
}
}, 100);
setInterval(function(){
if(kk_lrc._target == kk_lrc.target) return;
if(Math.abs(kk_lrc.lrc_obj.scrollTop - kk_lrc._target) > kk_lrc.lrc_height){
kk_lrc._target = kk_lrc.lrc_obj.scrollTop;
}
if(kk_lrc.player_obj.paused){
kk_lrc._target = kk_lrc.fixFloat(kk_lrc._target * 0.8 + kk_lrc.target * 0.2);
}else{
kk_lrc._target = kk_lrc.fixFloat(kk_lrc._target * 0.98 + kk_lrc.target * 0.02);
}
kk_lrc.lrc_obj.scrollTop = kk_lrc._target;
}, 5);
};
kk_lrc.add_lrc = function (time, lrc) {
kk_lrc.lrc.push(parseFloat(time) + kk_lrc.offset);
var lrc_line = document.createElement("li");
lrc_line.innerHTML = lrc;
kk_lrc.lrc_obj.appendChild(lrc_line);
};
kk_lrc.get_lrc = function (num) {
if(typeof kk_lrc.lrc[num] != "undefined"){
return kk_lrc.lrc[num][1];
}else{
return '';
}
}
kk_lrc.setoffset = function (num) {
kk_lrc.offset = num / 1000;
}
kk_lrc.fixFloat = function (num) {
return Math.ceil(num * 10) / 10;
}
return kk_lrc;
}
CSS:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/*
* Lyric support by kookxiang(http://ikk.me)
*/
.kk_player { width: 100%; max-height: 40px; }
.kk_lrc { height: 125px; overflow: auto; padding: 0; margin: 0; }
.kk_lrc li { display: block; text-align: center; color: gray; line-height: 20px; margin: 2px 0 3px 0; min-height: 20px; }
.kk_lrc .current { color: black; font-weight: bold; }
.kk_lrc, .kk_lrc * { -webkit-transition-duration: 1s; -moz-transition-duration: 1s; transition-duration: 1s; }
.kk_lrc ::selection { background: transparent; background: rgba(127, 127, 127, 0.1); }
.kk_lrc_box { position: relative; }
.kk_lrc_box:before { content: '.'; overflow: hidden; text-indent: -9999px; width: 100%; height: 30px; z-index: 1; display: block; position: absolute; background: url(cover.png) repeat-x 0 0; top: 0; pointer-events: none; }
.kk_lrc_box:after { content: '.'; overflow: hidden; text-indent: -9999px; width: 100%; height: 30px; z-index: 1; display: block; position: absolute; background: url(cover.png) repeat-x 0 100%; bottom: 0; pointer-events: none; }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { -webkit-border-radius: 10px; border-radius: 10px; }
::-webkit-scrollbar-thumb { -webkit-border-radius: 10px; border-radius: 10px; background: rgba(96, 96, 96, 0.8); -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.5); }
::-webkit-scrollbar-thumb:window-inactive { background: rgba(96, 96, 96, 0.4); }
调用: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<audio class="kk_player" controls="true" id="kk_lrc_bestFriend" src="http://www.ikk.me/usr/uploads/2014/06/1587625061.mp3" preload="metadata">您的浏览器不支持HTML5的 audio 标签,无法为您播放!</audio><br />
<div class="kk_lrc_box"><ul id="kk_lrc_bestFriend_lrc" class="kk_lrc">
<li></li><li></li><li></li>
</ul></div>
<script>
var bestFriend = load_kk_lrc('bestFriend');
bestFriend.add_lrc('0.00', 'ありがとう 君がいてくれて本当よかったよ<br />');
bestFriend.add_lrc('9.19', 'どんな時だっていつも<br />');
bestFriend.add_lrc('13.54', '笑っていられる<br />');
bestFriend.add_lrc('17.43', '例えば、離れていても 何年経っても<br />');
bestFriend.add_lrc('25.79', 'ずっと変わらないでしょ<br />');
bestFriend.add_lrc('29.84', '私たちBest Friend<br />');
bestFriend.add_lrc('33.37', '好きだよ、大好きだよ<br />');
bestFriend.add_lrc('46.24', '<br />');
bestFriend.add_lrc('51.19', 'こんな遅い時間にゴメンね<br />');
bestFriend.add_lrc('55.14', '一人じゃせっぱつまってきたの<br />');
bestFriend.add_lrc('59.44', '君の声少し聞けたら がんばれる<br />');
bestFriend.add_lrc('66.21', '何でも打ち明けられる<br />');
bestFriend.add_lrc('70.81', 'ママにも言えないことも全部<br />');
bestFriend.add_lrc('75.77', '誰よりも分かってくれる<br />');
bestFriend.add_lrc('83.28', '嬉しい時は自分の事みたいに喜んでくれて<br />');
bestFriend.add_lrc('91.21', 'ダメな時はちゃんと叱ってくれる存在<br />');
bestFriend.add_lrc('99.41', 'ありがとう 君がいてくれて本当よかったよ<br />');
bestFriend.add_lrc('107.75', 'どんな時だっていつも 笑っていられる<br />');
bestFriend.add_lrc('115.88', '例えば、離れていても 何年経っても<br />');
bestFriend.add_lrc('124.00', 'ずっと変わらないでしょ<br />');
bestFriend.add_lrc('128.36', '私たちBest Friend<br />');
bestFriend.add_lrc('131.78', '好きだよ、大好きだよ<br />');
bestFriend.add_lrc('144.67', '<br />');
bestFriend.add_lrc('149.49', '強がってもすぐにバレてる<br />');
bestFriend.add_lrc('153.63', 'へこんでる時は<br />');
bestFriend.add_lrc('155.40', '真っ先にメールくれる優しさに<br />');
bestFriend.add_lrc('159.81', 'もう何度も救われて<br />');
bestFriend.add_lrc('164.58', '泣きたい時はおもいっきり泣けばいい<br />');
bestFriend.add_lrc('170.72', '側にいるからって<br />');
bestFriend.add_lrc('174.26', '誰よりも強い味方<br />');
bestFriend.add_lrc('181.46', 'そんな君に私は何かしてあげられてるかな?<br />');
bestFriend.add_lrc('189.77', '何かあったらすぐに飛んでくから、絶対<br />');
bestFriend.add_lrc('197.90', 'ありがとう 君がいてくれて本当よかったよ<br />');
bestFriend.add_lrc('206.27', 'どんな時だっていつも<br />');
bestFriend.add_lrc('210.33', '笑っていられる<br />');
bestFriend.add_lrc('214.27', '例えば、離れていても 何年経っても<br />');
bestFriend.add_lrc('222.66', 'ずっと変わらないでしょ<br />');
bestFriend.add_lrc('226.75', '私たちBest Friend<br />');
bestFriend.add_lrc('230.29', '好きだよ、大好きだよ<br />');
bestFriend.add_lrc('243.15', '<br />');
bestFriend.add_lrc('247.12', 'どんな時も祈っているよ<br />');
bestFriend.add_lrc('255.12', '世界で一番に幸せになってほしい<br />');
bestFriend.add_lrc('263.50', 'ありがとう 君がいてくれて本当よかったよ<br />');
bestFriend.add_lrc('272.03', 'どんな時だっていつも<br />');
bestFriend.add_lrc('275.89', '笑っていられる<br />');
bestFriend.add_lrc('279.90', '例えば、離れていても 何年経っても<br />');
bestFriend.add_lrc('288.33', 'ずっと変わらないでしょ<br />');
bestFriend.add_lrc('292.38', '私たちBest Friend<br />');
bestFriend.add_lrc('296.48', '好きだよ、大好きだよ<br />');
bestFriend.init();
</script>
解决 wordpress 调用 Google 在线字体加载速度变慢的问题(续)
1 | sed -i s/fonts\.googleapis\.com/fonts.useso.com/g `grep fonts\.googleapis\.com -rl ./` |
解决问题
前几天码了篇文章,解决 wordpress 调用 Google 在线字体加载速度变慢的问题,发现依旧还是有点慢,正好手边有电脑,用 Google 的开发者工具看了下,坑爹啊,Google Apis 调用的 themes.googleusercontent.com 也被。。。你懂的,简直不能忍!


于是,我就依葫芦画瓢,给 themes.googleusercontent.com 搭了个反代,不过呢,之前的 fonts.imjs.work 的规则得修改一下,因为需要对获取的 css 里面请求的 url 进行替换,先上处理 css 的 php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://fonts.googleapis.com".$_SERVER['REQUEST_URI']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
$response = curl_exec($ch);
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$output_body = substr($response, $headerSize);
}
curl_close($ch);
preg_match("/Content-Type:.*?\r/",$header,$tmp);
if ($tmp[0]!=="") {
header($tmp[0]);
}
echo str_replace('themes.googleusercontent.com','themes.googleusercontent.imjs.work:20808',$output_body);
//后面的 themes.googleusercontent.imjs.work:20808 就是我自己的 vps
原先的 fonts.imjs.work 的规则修改为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
28server
{
listen 80;
server_name fonts.imjs.work;
index index.html index.htm index.php default.html default.htm default.php;
root /home/wwwroot/fonts.imjs.work;
rewrite ^ /index.php;
location ~ .*\.(php|php5)?$
{
try_files $uri =404;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fcgi.conf;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 12h;
}
access_log off;
}
绑定 themes.googleusercontent.imjs.work 到vps,附规则1
2
3
4
5
6
7
8
9
10
11server {
listen 80;
server_name themes.googleusercontent.imjs.work;
location / {
proxy_pass http://themes.googleusercontent.com/;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
不是别人给你使绊儿,是你自己给自己埋雷
总有人抱怨社会不公平,自己运气不好,我这最近想这个事,有可能很多不顺和不公平是自找的。总结一下,自省一下、自警一下、自勉一下啊!
我实习的时候,有个实习生整天说转正名额是内定的,再怎么表现好也没用,领导知道第一个把他开了。我闲的没事的时候,经常发起线上活动,会拉很多赞助。有人不停的发帖说奖品是内定的,我一想,我不能让你白说呀!我就截图给所有赞助商看,通知他们如果选中这个人就删了。在扎堆里做赠书活动,送了一千多册书呀!难免有丢单,漏发的。有个人没收到书不停留言说没收到,到处留言,很多粉丝看了之后觉得我不靠谱,退了扎堆。可是这个人呢!收到书以后反而不言语了。为了以后不再出现这种事,我设立了黑名单,决定以后都不会发书给他了。
有时候不光这些间接的、不知不觉给自己埋雷的事,让我们悲剧,那么有的人是直接没事找事。有一年夏天领导带我们去山里采摘,有位同事说“通过观察和思考选择的小路,可以摘到更甜美的果实。”大家怎么劝他都不行,无奈我们只好分开走,然后走小路的他被人家看果园的狗追地鞋都丢了。
有些人靠听说活着,人家说什么信什么,也有人是人家说什么都不信,这都容易让自己运气不好。很多话不能听了就做,你得听全了,还得琢磨一下,琢磨明白再做。理财的基础是记账,(记账是为了算账,不是单纯的记账,光记账不算账没用)。吃五谷粥可以养生(得坚持吃,就吃一次不管事)。一场说走就走的旅行(自己上班攒够钱了,没钱就别耽误工夫了)。
比如总有人反应书评群加了十多遍加不进去,我一看没写通过语,你说你阅读个书评群的加群指南都有问题,谁还敢找你写书评呀?!还有人老抱怨自己运气不好,参与线上活动没中奖。我一看根本没参加,大哥你根本没参加中什么奖呀?想中500万不买彩票也中不了!你这都没参加,你可不运气不好。
在为人处世上,注意措辞也很重要,我婆婆管这叫语言艺术。比如今天早上在扎堆收到三个书还没有邮寄到,需要查快递单号的信息:
“土豆姐,我是月日被选中写《》书评,一个月还没收到,方便的话,能不能帮我查一下。”
“我还没有收到书呢土豆姐~”
“《》是不是不发了啊”
这三个措辞上就能看出谁会说话了。平时找人帮忙,“反正你也没事,帮我……”这种话非常让人反感,很容易被拒绝,被拒绝之后不想自己的问题,觉得人家不帮助你就是没人情味,人就容易瞎想。
之前闲着没事接了很多杂志的专栏,快休产假逐渐介绍给别人或者给编辑推荐新的作者。有个豆瓣友邻发豆油给我。
他:你那个**专栏,为什么不推荐我写?!
我:因为你之前骂我!
他:你难道不知道“举贤不避亲仇”!
我:我知道,但是我不是祁黄羊。
大家出来工作,不得罪人成不了事,你要把人都得罪了,运气不好也没什么可抱怨的。你说你没事净给别人添堵,谁没事贱的还帮你呀?!之前还有一次我帮一朋友发招聘信息,另外一位骂过我的友邻跟我说让我推荐他。理由是他看别人骂我,他才骂我的。我说这要是别人杀人,你也杀人,你跟警察说,因为别人杀人,我才杀人的,警察能原谅你吗?
虽说“人无远虑必有近忧”但是真分什么事,有时候真的不用为太远的事焦虑。比如才200多关注,就暂时别担心有几万粉丝怎么处理粉丝问题。比如连男朋友都没有,就先别着急学习如何与婆婆斗志斗勇。比如一个月还不到五千的收入,就先别纠结买北京二环内四合院还是五环外别墅了。友邻@海补充的“比如连书都没读几本的,就别担心什么读书的害处了。”有些人瞎纠结,给自己设置很多障碍,不是别人给你使绊儿,是你自己给自己埋雷。
解决 wordpress 调用 Google 在线字体加载速度变慢的问题
1 | sed -i s/fonts\.googleapis\.com/fonts.useso.com/g `grep fonts\.googleapis\.com -rl ./` |
解决问题
最近有消息称我们伟大的墙又升级了,Google 遭到的封锁更加严重,加了 https 都没法打开。这不是问题关键,关键是,wordpress 调用了 Google 的 Open Sans 在线字体,但域 fonts.googleapis.com 也已无法正常访问,导致站点打开速度变慢,这怎么能忍?简直丧心病狂!表示过会还得去看看 chart.googleapis.com 是不是也被封了。。。如果封掉了还得。。。跑偏了,接下来说说应该怎么解决这个问题了。。。
之前看到有人说直接禁用 wordpress 调用 Open Sans 字体(关闭谷歌的Open Sans字体为WordPress后台加速),但总觉得这样做未免有点太绝,而且我也有点强迫症。。。总觉得原版的才是最好的。。。于是我就给 fonts.googleapis.com 搭了个反代(其实可以把文件下到自己服务器上改调用地址的,但又不想改 wordpress 文件结构,所以就用 vpsme 搭了个反代)。。。
首先,我用 vpsme 搭了个反代,域 fonts.imjs.work,因为是共享 ip,端口 20808,附带个规则1
2
3
4
5
6
7
8
9
10
11server {
listen 80;
server_name fonts.imjs.work;
location / {
proxy_pass http://fonts.googleapis.com/;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
然后,重载一下配置1
service nginx reload
其次,我进自己 vps ssh 搜了下有哪些文件调用了 Google Apis 的字体1
grep -r "fonts.googleapis.com" /home/wwwroot/233.imjs.work
出来了五个结果
其中,三个是需要改的(另外两个是别的主题里的,我用不到)1
2
3
4
5/home/wwwroot/233.imjs.work/themes/twentytwelve/functions.php: $font_url = add_query_arg( $query_args, "$protocol://fonts.googleapis.com/css" );
/home/wwwroot/233.imjs.work/wp-includes/script-loader.php: $open_sans_font_url = "//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,300,400,600&subset=$subsets";
/home/wwwroot/233.imjs.work/wp-includes/js/tinymce/plugins/compat3x/css/dialog.css:@import url(//fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,300,400,600&subset=latin-ext,latin);
将 fonts.googleapis.com 都修改为刚才的我们的域 fonts.imjs.work:20808,保存,立即生效。
现在可以访问测试下啦,不过我的站还是有点慢的。。。azure 流量超了。。。用 bluevm 的 128 撑一会。。。17 号搬回去。。。
关于 js function 传值的问题
最近无聊在做一个解三元一次方程组的网页,用的 javascript,好吧其实大部分是 jquery 框架。现在已经基本完工了,除了判断方程组是否无解或者有无穷解的部分以外。下午碰到一个挺有意思的问题,拿出来分享一下。
先上部分关键代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23function get_swap(arr_a,arr_b,k) { //交换系数
arr_a=$.extend(true, {}, arr_a); //坑啊这句
for (i=0;i<3;++i) {
arr_a[i][k]=arr_b[i];
}
return arr_a;
}
function get_tteleg(arr_a,arr_b) { //主 function,出结果用
var gc=(typeof(arguments[2])=="undefined")?false:arguments[2]; //如果 false 就不要过程。。。
var d=get_array_fj(arr_a);
var x=get_array_fj(get_swap(arr_a,arr_b,0))/d;
var y=get_array_fj(get_swap(arr_a,arr_b,1))/d;
var z=get_array_fj(get_swap(arr_a,arr_b,2))/d;
if (gc) {
var op='<img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('D='+get_array_gc(arr_a))+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('D='+get_array_fj_gc(arr_a)+'='+d)+'" style="border:none;" /><br />';
op+='<img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('x= \\frac{'+get_array_gc(get_swap(arr_a,arr_b,0))+'}{D}')+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('x= \\frac{'+get_array_fj_gc(get_swap(arr_a,arr_b,0))+'}{'+d+'}='+x)+'" style="border:none;" /><br />';
op+='<img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('y= \\frac{'+get_array_gc(get_swap(arr_a,arr_b,1))+'}{D}')+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('y= \\frac{'+get_array_fj_gc(get_swap(arr_a,arr_b,1))+'}{'+d+'}='+y)+'" style="border:none;" /><br />';
op+='<img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('z= \\frac{'+get_array_gc(get_swap(arr_a,arr_b,2))+'}{D}')+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('z= \\frac{'+get_array_fj_gc(get_swap(arr_a,arr_b,2))+'}{'+d+'}='+z)+'" style="border:none;" />';
} else {
var op='<img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('d='+d)+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('x='+x)+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('y='+y)+'" style="border:none;" /><br /><img src="http://chart.googleapis.com/chart?cht=tx&chl='+encodeURIComponent('z='+z)+'" style="border:none;" />';
}
return op;
}
各种各样的 img 标签是调用 Google 的 api 用 TeX 输出,这个就不细说了。看上面代码中有一句 arr_a=$.extend(true, {}, arr_a);
原先并没有这一句,但因为 get_swap() 是用来交换系数用的,每次交换完输出的 arr_a 就不正常,于是就开始找起了 bug,但由于我并不怎么接触 javascript,只以为它和 php 是一样的,找了半天都没找到问题,但直觉告诉我可能是因为全局变量或者传值的问题,可是我没有定义全局变量啊。直至经位高人指点,才发现 javascript 里 function 传对象和数组传的都是地址,而非值。(参考 http://www.cftea.com/c/2010/07/TKE282SFVCKL2RLS.asp)这简直就是天大的坑啊,于是乎就想着把数组拆开,一个一个传值,但这样又显得太麻烦,毕竟 4*3 的增广矩阵呢,这不得写死人。。。罢了罢了,后来想过把数组转成 json 格式字符串,传进 function 再 eval,结果发现 jquery 的 $.toJSON 要另外引插件($.toJSON 我 tm 以前做播放器的时候不是用过嘛。。。居然忘记了),顿时放弃了,然后百度了一两个小时,终于被我找到方法了。我思路是这样的,既然它传地址进来我为何不重新定义一个数组然后 copy 原先那个数组的值呢?嗯。。。其实这个思路也是百度到的。。。。开始是用了 arr.concat() 和 arr.slice(0),发现无效,原因是我的数组是一个二维数组,不支持。卧槽,然后才发现了这个 http://www.cnblogs.com/RascallySnake/archive/2010/05/07/1729563.html,$.extend,jquery 自带,效果甚是满意。放个链接出来给各位测试一下 http://lab.imjs.work/math/tteleg.html
P.S. 关于三元一次方程组是否无解还有是否有无穷解的问题到现在还是没解决,求个方便点的算法研究一下。。。(不是我要做伸手党。。。实在是高一党,啊呸,中专党对线性代数有点力不从心啊)刚刚倒是问了几位大神,说是增广矩阵的秩可以用来判断,但秩却又是什么。。。又有说可以用高斯消元法去做,做下来的行数还是列数来着的是秩。。。。卧槽这什么跟什么呀。。。我解个三元一次方程组我容易么我。。。二元一次方程组的时候用行列式感觉还行,没想到三元一次的这么复杂啊卧槽。。。附张百度百科的截图,完整的内容戳链接 增广矩阵 - 百度百科
诶对还有,一直有个问题想不明白,二元一次方程组可以理解为一个直角平面里两根直线的相交点,三元的则是一个三维的物体,那四元及以上的呢?求解释。。。
TeX、LaTeX、TeXLive 小结
一直纠结:用什么工具来记录学习中的点滴,用什么写软件的文档
在线的(blog、wiki、google doc、google site、…)
离线的(wiki、LaTeX、sphinx、docbook、doxygen…)
…
然后觉得 git + sphinx 应该是个不错的选择,恩,生成网页、qthelp、chm文件等都还不错,可是,当想生成包含中文的pdf时,又回到了让人倍感头痛的 LaTeX中文问题上面来了…
windows下似乎没什么好说的,本文稍偏重ubuntu,总体来说latex中文比前几年好用太多了。本文最初目标,学习最基本的sphinx+latex的中文处理。名词
相关(类似)的名词太多了,想分清真不容易
| 引擎 | (Knuth)TeX | 真正的(原始的)TeX |
| | ε-TeX | 相对于原始的TeX它提供了一种扩展模式 |
| | pdfTeX | 它从tex文件不通过dvi文件直接生成pdf文件(开发者已经转向LuaTeX) |
| | XeTeX | 相对于原始的TeX,主要增加了Unicode和 OpenType 的支持 |
| | LuaTeX | 它使用Lua作为扩展语言,对于LaTeX支持尚不完善? |
| | … | |
| 宏集 | plain TeX | 最古老的TeX宏集,提供了一些最基本的命令 |
| | AMSTeX | 是美国数学会提供的一个TeX宏集,它添加了许多数学符号和数学字体 |
| | LaTeX | 相对于PlainTeX,它使得科技文档的排版更加直观和方便 |
| | ConTeXt | 和LaTeX 相比,它更加灵活和自由 |
| | … | |
| 发行版 | TeX Live | 国际TeX用户组织TUG开发,支持不同的操作系统 |
| | MiKTeX | Windows 下广泛使用的一个TeX发行版 |
| | ConTeXt Minimals | 它包含了最新版本的 ConTeXt |
| | teTeX | 一个Unix下的TeX发行版,现在已经停止更新且并入TeXLive |
| | fpTeX | 一个Windows的TeX发行版,已不再更新 |
| | … | |
真够乱的,还好,我们只关注一部分:
LaTeX
原始的TeX已经有了一组宏集,也就是Knuth所写的著名的Plain TeX(原始的TeX和Plain Tex都是《The TeXbook 》一书中介绍的内容)。
但是这些命令仍然很底层,不够方便、直观,于是Leslie Lamport写了另一组宏,称为LaTeX,主要是它版本配置和文中内容适度分开处理。
LaTeX 2ε是自1993年以来LaTeX的一个稳定版本,是目前大部分LaTeX书籍的主体内容。
ctex
ctex宏包提供了一个统一的中文LaTeX文档框架,底层支持CCT、CJK和xeCJK三种中文LaTeX系统。
CCT 非常不推荐了
CJK 这个?应该在windows下工作还很不错
xeCJK 比较推荐
ctex宏包提供了编写中文LaTeX文档常用的一些宏定义和命令。
主要文件包括ctexart.cls、ctexrep.cls、ctexbook.cls 和 ctex.sty、ctexcap.sty。生成pdf流程
- 原始的方式
| .tex | ==> | .dvi | ==> | .ps | ==> | .pdf |
| | latex | | divps | | ps2pdf | | dvipdfm(x),少一个 .ps 步骤
| .tex | ==> | .dvi | ==> | .pdf |
| | latex | | dvipdfm | |pdflatex或xelatex,直接生成 pdf
| .tex | ==> | .pdf |
| | pdflatex | |配置
TeX Live
种种迹象表明,ubuntu软件仓库中的TeX Live非常非常不好用。于是,只能从官方下载ISO镜像,或者直接网络安装了。
下载 texlive2011-20110705.iso
挂载
1 | sudo mkdir /mnt/texlive |
- 安装
1 | cd /mnt/texlive |
TeXworks
很不错的一个Tex(LaTeX、ConTeXt等)文档的创作环境,一个基于Unicode的可感知TeX的编辑器,集成了PDF浏览功能,干净、简洁的操作界面。
恩,更主要的是Qt4编写的开源软件,跨Windows、Linux、Mac OS环境。
中文配置
主要涉及几个宏包,这些宏包进化太快了,远没有latex稳定,可能了解它们最好的办法就是看其自带的手册了。
当前的推荐配置(?)使用XeLaTeX引擎处理中文
使用xeCJK宏包解决中西文字体选择、标点符号位置、CJK兼容等问题
使用ctex宏包和文档类解决中文版式习惯的问题
不使用这两个宏包(需要设置所用字体,命令fc-list :lang=zh-cn用来查看系统字体)1
2
3
4
5
6\documentclass[11pt,a4paper]{article}
\usepackage{fontspec}
\setmainfont{WenQuanYi Micro Hei}
\begin{document}
TeX Live 2011,XeLaTeX,Texworks,你们好!!
\end{document}
直接使用xeCJK宏包。(属于底层的方案)1
2
3
4
5
6\documentclass{article}
\usepackage{xeCJK}
\setCJKmainfont{WenQuanYi Micro Hei}
\begin{document}
TeX Live 2011,XeLaTeX,Texworks,你们好!!
\end{document}
使用ctex宏包。高层的方案。(默认的字体是为windows准备的,在linux下,可以直接设置字体,但更建议采用后面的方法,修改ctex的字体文件)1
2
3
4
5\documentclass{ctexart}
\setCJKmainfont{WenQuanYi Micro Hei}
\begin{document}
TeX Live 2011,XeLaTeX,Texworks,你们好!!
\end{document}
解决字体问题后,看起来还是很简单的:1
2
3
4\documentclass{ctexart}
\begin{document}
TeX Live 2011,XeLaTeX,Texworks,你们好!!
\end{document}
字体
如果不想用linux下的字体,还可以把 Windows 下的一些字体直接拷贝到~/.fonts目录中
1
cp sim* ~/.fonts
对于xeCJK宏包,使用命令设置字体,比如:
1 | \setCJKmainfont[BoldFont=Droid Sans Fallback, ItalicFont=AR PL UKai CN]{AR PL UMing CN} |
- 使用ctex宏包时,直接修改下面这个文件:
1 | /usr/local/texlive/2011/texmf-dist/tex/latex/ctex/fontset/ctex-xecjk-winfonts.def |
其内容大致如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14% ctex-xecjk-winfonts.def: Windows 的 xeCJK 字体设置,默认为六种中易字体
% vim:ft=tex
\setCJKmainfont[BoldFont={SimHei},ItalicFont={[SIMKAI.TTF]}]{SimSun}
\setCJKsansfont{SimHei}
\setCJKmonofont{[SIMFANG.TTF]}
\setCJKfamilyfont{zhsong}{SimSun}
\setCJKfamilyfont{zhhei}{SimHei}
\setCJKfamilyfont{zhkai}{[SIMKAI.TTF]}
\setCJKfamilyfont{zhfs}{[SIMFANG.TTF]}
\newcommand*{\songti}{\CJKfamily{zhsong}} % 宋体
\newcommand*{\heiti}{\CJKfamily{zhhei}} % 黑体
\newcommand*{\kaishu}{\CJKfamily{zhkai}} % 楷书
\newcommand*{\fangsong}{\CJKfamily{zhfs}} % 仿宋
\endinput
将其中的 [SIMKAI.TTF] 和 [SIMFANG.TTF] 用 KaiTi 和 FangSong 替代。(好奇怪,Windows下怎么会这个奇怪的名字,字体直接拷过来,就不需要这么奇怪的名字)
sphinx
有了前面一堆东西,终于可以回到Pyhton sphinx了
当我们运行 sphinx-build -b latex src target时,它生成
Makefile
XXX.tex
…
等文件
但是,生成的 .tex 中:使用的documentclass是report或article,我们需要的是ctexrep或ctexart
生成的 Makefile 中:使用的latex和pdflatex,我们需要的是 xelatex
这样以来,需要简单修改一下的sphinx的latex生成器了,找到目标(这个位置不定,在python中import sphinx,然后查看sphinx.比较容易定位)1
/usr/lib/pymodules/python2.7/sphinx/writers/latex.py
搜索article和report,改为ctexart和ctexrep
Makefile 是通过哪个文件生成的呢?好隐蔽1
/usr/share/sphinx/texinputs/Makefile
恩,一个静态文件,直接按照自己需要改就行了。不过我们直接将里面所有的pdflatex直接改成xelatex就够了
















