我的個人網站:拓跋的前端客棧瞭解一哈,這裡是原文地址,這裡是專案地址,歡迎star&fork。如果您發現我文章中存在錯誤,請盡情向我吐槽,大家一起學習一起進步φ(>ω<*)
DEMO
最終效果請點選 這裡 ,是不是有點意思?
原始碼分析
code-printer的最基本的原理是首先搭起一個骨架,然後通過遍歷的方式,一點一點地往骨架裡塞東西。
骨架主要有三塊:
- <pre id="my-code">: 主要用來展示的HTML程式碼的,帶標籤
- <style id="style-elem">: 主要填CSS程式碼的,用於把<pre>裡特定的標籤轉換成特定的樣式
- <div id="script-area">: 主要是填JS程式碼的。但是由於一個字元一個字元往裡面填程式碼會出現大量報錯,因此這部分需要一個段落的JS程式碼全部書寫完畢以後,通過一個命令符'~'來一次性填入。
printCodes
let printCodes = function (message, index, interval) {
if (index < message.length) {
$code_pre.scrollTop = $code_pre.scrollHeight;
printChar(message[index++]);
return setTimeout((function () {
return printCodes(message, index, interval);
}), speed);
}
};
複製程式碼
這段程式碼的主要作用就是遍歷列印字元,同時每次列印的時候都將滾動條拖到最底下,保證使用者能看到最新的變化。
printChar
let printChar = function (which) {
let char, formatted_code, prior_block_match, prior_comment_match, script_tag;
if (which === "`") {
// 重置為空字串,防止列印出來
which = "";
isJs = !isJs;
}
if (isJs) {
if (which === "~" && !openComment) {
script_tag = createElement("script");
// two matches based on prior scenario
prior_comment_match = /(?:\*\/([^\~]*))$/;
prior_block_match = /([^~]*)$/;
if (unformatted_code.match(prior_comment_match)) {
script_tag.innerHTML = unformatted_code.match(prior_comment_match)[0].replace("*/", "") + "\n\n";
} else {
script_tag.innerHTML = unformatted_code.match(prior_block_match)[0] + "\n\n";
}
$script_area.innerHTML = "";
$script_area.appendChild(script_tag);
}
char = which;
formatted_code = jsHighlight($code_pre.innerHTML, char);
} else {
char = which === "~" ? "" : which;
$style_elem.innerHTML += char;
formatted_code = cssHighlight($code_pre.innerHTML, char);
}
prevAsterisk = which === "*";
prevSlash = (which === "/") && !openComment;
openInteger = which.match(/[0-9]/) || (openInteger && which.match(/[\.\%pxems]/)) ? true : false;
if (which === '"') {
openString = !openString;
}
unformatted_code += which;
return $code_pre.innerHTML = formatted_code;
};
複製程式碼
printChar函式是code-printer的核心函式,這個函式會根據當前的程式碼是JS還是CSS,來進行不同的處理。
如何判斷是JS還是CSS程式碼呢?預設設定
let isJs = false;
複製程式碼
也就是預設是CSS,然後以 ` 作為切換符號,每次遇到 ` 就切換一次語言。
當前字元屬於JS時,在沒遇到執行符號 ~ 之前,printChar只是單純的列印格式化後的字元。遇到 ~ 以後,printChar進行了如下操作:
- 函式首先通過正則匹配,匹配出之前的JS整段程式碼。
- 再呼叫**createElement()**來創造一對<script></script>標籤,用來存放JS程式碼。
- 然後將處理過的JS程式碼存入<script></script>標籤內。
- 最後通過$script_area.appendChild()的方式將<script></script>及其內部的JS程式碼存入<div id="script-area">中。注意,每次呼叫**$script_area.appendChild()**之前,都要將之前<div id="script-area">清空一遍,防止之前的JS程式碼再執行一次。
當前字元屬於CSS時,每次列印過程,一方面會將未格式化的字串傳入<style id="style-elem">中,用以生成樣式。另一方面會將格式化的程式碼輸出到<pre id="my-code">中,用以展示程式碼。
cssHighlight和jsHighlight
這兩個函式十分類似,主要作用就是通過正則匹配,給不同型別的字元兩端封上不同的標籤,用以高亮程式碼。舉個例子:
if (openInteger && !which.match(/[0-9\.]/) && !openString && !openComment) {
s = string.replace(/([0-9\.]*)$/, "<em class=\"int\">$1</em>" + which);
}
複製程式碼
這就是一處典型的匹配+替換標籤組合拳。作用是程式碼在以數字結尾時,給數字兩端封上<em class="int"></em>的標籤。
程式碼中還有很多用作標誌位的引數,比如說openInteger,表示這段輸入都是數字。通過對這些控制位進行操作,可以將零散的字元分成一段一段的,方便進行處理。
其他部分就不談了,自己可以看原始碼,我已經加了備註。
使用方法
您可以fork過去直接修改,也可以按照如下步驟操作
git clone https://github.com/tuobaye0711/code-printer.git
複製程式碼
安裝依賴檔案
npm install
複製程式碼
打包檔案
npm start
複製程式碼
起服務
npm run server
複製程式碼
修改配置說明:
resume 檔案存放簡歷或者其他靜態資源
source/code.js 存放需要列印並展示樣式的程式碼(CSS/JS)
source/app.js 是主程式碼,可以修改一些比如說列印速度、高亮色等配置
小結
能在自己網站掛一份帶列印特效的簡歷,想必能讓人眼前一亮吧。這篇文章主要安利了一下我這個名為code-printer的小專案,希望能幫到各位~