(點擊上方公眾號,可快速關注)
作者:伯樂在線專欄作者 - 十年蹤跡
連結:http://web.jobbole.com/86353/
點擊 → 了解如何加入專欄作者
最近,我通過眾成翻譯學習和翻譯了一系列優秀的文章,許多文章都值得向大家推薦。但是,好的技術文章通常都有大段的代碼。一般情況下,這並沒有什麼問題,因為不論是眾成翻譯、我的博客或者是其他轉載技術類文章的平臺,一般都支持代碼的語法高亮展示和閱讀。
但是,也有一些公共的平臺對代碼的支持並不理想,比如微博的長微博:
長微博裡編輯正常的代碼
到了預覽的時候被「自動壓縮」了
再比如微信公眾號,粘貼文章的時候,如果有代碼,會丟失掉代碼裡面的一些換行。如果代碼較短還好,可以手工編輯下,但是如果是長代碼的話,效果簡直是慘不忍睹,也很難編輯:
博客裡正常的代碼
貼到微信公眾號編輯文章裡慘不忍睹
如果一一把代碼格式調整好會是一個非常巨大的工作量,偶爾做一下還好,如果天天要把時間花費在編輯和調整代碼的格式上,那也太悲催了。
為了更好地在各種非主流(對程式設計師來說)的平臺上愉快地貼代碼,我們只能幹脆將代碼轉為圖片。最簡單的轉換方式,當然是——截屏。
截屏的問題
利用作業系統自帶的截屏或者其他工具的截屏功能來截取代碼當然是可行的。只是,不管是系統默認截屏還是截屏工具,都不是特別好用,尤其當代碼超過一屏的時候,還得分屏截取,而當你決定修改代碼的一部分的時候,有可能又要調整和重新截屏,這對於一大段一大段代碼的文章編輯來說是個噩夢一樣的體驗,而且截成一段段的代碼,對讀者也不友好。
另外一個截屏的問題是,截屏效果依賴於我們使用的 IDE,有可能寫不同的代碼使用不同的 IDE,比如我喜歡用 vim 寫 json 配置和 nginx 配置,但我用 Sublime Text 3 編輯 HTML、CSS 和 JS,如果要寫 Android Native 代碼,我用 Android Studio,寫其他一些程式語言,我可能會使用 XCode。不同的 IDE 界面截出來的代碼風格看起來不同,這樣就會造成文章之間風格不統一或者甚至一篇文章中的代碼風格也五花八門,這對於希望自己的文章被完美呈現的作者來說,簡直不能忍。
用工具將代碼轉圖片
為了解決截屏的這些問題,我寫了一個在線代碼轉圖片的工具(github 代碼倉庫),將代碼粘貼進輸入框,點擊左上角的相機圖標或者用鍵盤快捷鍵 Ctrl+D,就可以自動將代碼轉成語法高亮的圖片。
代碼段即使很長,超過屏幕高度,也能輕鬆截取下來:
語法高亮基於 Code Prettify,支持超過 40 種程式語言的語法高亮。主流程式語言自動識別,不需要選擇語言類型就可以自動識別「Java、JS、HTML、C、C++、Python、PHP」等主流程式語言。
轉換代碼到圖片使用 html2canvas,這是一個非常著名的從瀏覽器網頁截圖的開源庫,使用很方便,功能也很強大。
使用 html2canvas
html2canvas 的使用非常簡單,簡單到只需要傳入一個 DOM 元素,然後通過回調拿到 canvas:
html2canvas(element, {
onrendered: function(canvas) {
// canvas is the final rendered element
}
});
在實際使用的時候,有兩個注意點:
html2canvas 通過解析元素實際的樣式來生成 canvas 圖片內容,因此它對元素實際的布局和視覺顯示有要求。如果要完整截圖,最好將元素從文檔流中獨立出來(例如 position:absolute)
默認生成的 canvas 圖片在 retina 設備上顯示很模糊,處理成 2 倍圖能解決這個問題:
var w = $("#code").width();
var h = $("#code").height();
//要將 canvas 的寬高設置成容器寬高的 2 倍
var canvas = document.createElement("canvas");
canvas.width = w * 2;
canvas.height = h * 2;
canvas.style.width = w + "px";
canvas.style.height = h + "px";
var context = canvas.getContext("2d");
//然後將畫布縮放,將圖像放大兩倍畫到畫布上
context.scale(2,2);
html2canvas(document.querySelector("#code"), {
canvas: canvas,
onrendered: function(canvas) {
...
}
});
對多語言的支持
Code Prettify 默認支持多種語言,所以一開始的時候,沒有設計成讓用戶能夠手動切換語言,但是發現這樣做,在展示 CSS 的時候效果不好:
上面的代碼裡,CSS 的 ID 選擇器被識別成代碼注釋了,查看 Code Prettify 的官方文檔發現,它默認支持的語言中不包括 CSS,CSS 和其他一些語言的語法高亮需要通過擴展來實現。
使用擴展
我使用 URL 的 hash 來標記擴展,例如要使用 CSS 擴展,可以使用 http://code2img.test.h5jun.com/#css。
使用 CSS 語法高亮擴展
使用 hash 來標記擴展的好處是,我在頁面頂部放了一些常用語言的擴展連結,切換這些連結的時候由於是改變 hash,不會刷新頁面。
在第一次切換到某個擴展的語言時,需要加載相應的 js 文件:
var srcMap = {
"apollo": "lang-apollo.js",
"basic": "lang-basic.js",
"clojure": "lang-clj.js",
"css": "lang-css.js",
"dart": "lang-dart.js",
"erlang": "lang-erlang.js",
"go": "lang-go.js",
"haskell": "lang-hs.js",
"lasso": "lang-lasso.js",
"lisp": "lang-lisp.js",
"scheme": "lang-lisp.js",
"llvm": "lang-llvm.js",
"logtalk": "lang-logtalk.js",
"lua": "lang-lua.js",
"matlab": "lang-matlab.js",
"ml": "lang-ml.js",
"mumps": "lang-mumps",
"nemerle": "lang-n.js",
"pascal": "lang-pascal.js",
"protocol": "lang-proto.js",
"r": "lang-r.js",
"rd": "lang-rd.js",
"rust": "lang-rust.js",
"scala": "lang-scala.js",
"sql": "lang-sql.js",
"swift": "lang-swift.js",
"tcl": "lang-tcl.js",
"latek": "lang-tex.js",
"vb": "lang-vb.js",
"vhdl": "lang-vhdl.js",
"wiki": "lang-wiki.js",
"xq": "lang-xq.js",
"yaml": "lang-yaml.js"
};
function loadPlugin(lang){
var js = srcMap[lang.toLowerCase()];
if(typeof js === "string"){
var script = document.createElement("script");
script.src = "/static/js/" + js;
document.body.appendChild(script);
}
//srcMap[lang] 設為 true,表示已經加載過,下次切換就不會再加載
srcMap[lang] = true;
}
許可協議
由於 Code Prettify 採用 Apache License 2.0,而 html2canvas 採用一個非商業授權的協議,因此,本項目採用雙重許可協議,使用、修改和分發本項目代碼需要遵守兩個協議。
總結
由於一些平臺對文本代碼支持不友好,因此我使用 html2canvas 和 Code Prettify 來實現一個將代碼轉為圖片的工具,它的特點如下:
在線轉換代碼為 jpeg base64 圖片
支持 40+ 種不同語言的語法高亮
支持多屏的長代碼轉成一張圖片
如果你有在微信平臺或者微博上發技術文章的需求,你應該可以用到它。
對它感興趣,可以 check out (https://github.com/akira-cn/code-to-image)整個項目的最新版本。
專欄作者簡介 ( 點擊 → 加入專欄作者 )
十年蹤跡:月影,奇舞團團長,熱愛前端開發,JavaScript 程序猿一枚,能寫代碼也能打雜賣萌說段子。
打賞支持作者寫出更多好文章,謝謝!
【今日微信公號推薦↓】
更多推薦請看《值得關注的技術和設計公眾號》
其中推薦了包括技術、設計、極客 和 IT相親相關的熱門公眾號。技術涵蓋:Python、Web前端、Java、安卓、iOS、PHP、C/C++、.NET、Linux、資料庫、運維、大數據、算法、IT職場等。點擊《值得關注的技術和設計公眾號》,發現精彩!