實戰專案之自動簡歷

李不遠發表於2018-09-15

專案介紹

一個可以自動播放書寫過程簡歷,主要運用原生JS和CSS3的知識點。

用到的庫:

  1. prism
  2. marked

相關連結

  1. 預覽點我
  2. 原始碼點我
    實戰專案之自動簡歷

設計過程

基本思想—動起來

  1. 想辦法讓文字逐個出現在頁面中

    setTimeout(()=>{
        document.body.innerHTML='1'
    },1000)
    setTimeout(()=>{
        document.body.innerHTML='2'
    },2000)
    setTimeout(()=>{
        document.body.innerHTML='3'
    },3000)
    複製程式碼
  2. 成功了,但是有點傻,為何我們不試一試setInterval加上slice()或者substring()

    var result = '1234567890'
    var n = 0
    setInterval(()=>{
        n += 1
        document.body.innerHTML = result.substring(0,n)
    },500)
    複製程式碼

    slice()substring()的區別是,substring()不接受負的引數

  3. 既要開始,也要結束。想辦法取消鬧鐘

    var result = '1234567890'
    var n = 0
    var clock = setInterval(()=>{
        n += 1
        document.body.innerHTML = result.substring(0,n)
       if(n>=result.length){
           window.clearInterval(clock)
       }
    },500)
    複製程式碼

換成CSS

  1. 將內容換成CSS

    var result = `
    body{
       background:green;
    }
    `
    var n = 0
    var clock = setInterval(()=>{
       n += 1
       document.body.innerHTML = result.substring(0,n)
      if(n>=result.length){
          window.clearInterval(clock)
      }
    },500)
    複製程式碼

    執行一下。黑人問號臉——我的換行沒啦???

    這是因為在HTML裡面,連續出現多個看不見的字元,瀏覽器會認為它是一個空格

  2. 利用<pre>標籤

    HTML<pre>元素表示預定義格式文字。在該元素中的文字通常按照原檔案中的編排,以等寬字型的形式展現出來,文字中的空白符(比如空格和換行符)都會顯示出來。

    HTML中加入<pre>標籤,將內容寫到<pre>

    <body>
    <pre id="code"></pre>
    </body>
    複製程式碼
    var result = `
    body{
        background:green;
    }
    `
    var n = 0
    var clock = setInterval(()=>{
        n += 1
        code.innerHTML = result.substring(0,n)
       if(n>=result.length){
           window.clearInterval(clock)
       }
    },100)
    複製程式碼
  3. 應用程式碼

    現在我們只是將程式碼展示了出來,但是看到效果,所以我們要將程式碼寫入到<style>

    <head>
      <style id="myStyle"></style>
    </head>
    <body>
    <pre id="code"></pre>
    </body>
    複製程式碼
    var result = `
    body{
        background:green;
    }
    `
    var n = 0
    var clock = setInterval(()=>{
        n += 1
        code.innerHTML = result.substring(0,n)
        myStyle.innerHTML = result.substring(0,n)
       if(n>=result.length){
           window.clearInterval(clock)
       }
    },500)
    複製程式碼

完善細節

  1. 沒效果?因為文字也寫了進去

    解決辦法-將除去CSS內容進行註釋

    /*你好,我是不遠,一名前端工程師。
    請允許我做一個簡單的自我介紹,但是文字太單調,所以我想來點特別的。
    首先我準備一下樣式。
    */
    *{
    	transition: all 1s;
    }
    html{
    	background:#363636
    	color:#fff;
    	font-size:16px;
    }
    複製程式碼
  2. 程式碼高亮? 首先會想到這樣去解決,

    <span style="color":red;>html</span>
    複製程式碼

    但是在CSS中這樣的語法是不允許的。

    • 方法一:偷樑換柱
         var n = 0
         var clock = setInterval(()=>{
             n += 1
             code.innerHTML = result.substring(0,n)
             code.innerHTML = code.innerHTML.replace('html','<span style="color:red;">html</span>')
             myStyle.innerHTML = result.substring(0,n)
            if(n>=result.length){
                window.clearInterval(clock)
            }
         },500)
    複製程式碼

    但是,很傻,很累,好的程式設計師要學會偷懶

    • 方法二:prism.js 引入prism官網的JS和CSS檔案後

      var n = 0
      var clock = setInterval(() => {
          n += 1
          code.innerHTML = result.substring(0, n)
          code.innerHTML = Prism.highlight(code.innerHTML, Prism.languages.css)
          //修改code為prism提供的樣式
          myStyle.innerHTML = result.substring(0, n)
          if (n >= result.length) {
              window.clearInterval(clock)
          }
      }, 50)
      複製程式碼
  3. 程式碼高亮變化 我們需要讓程式碼預設是平平無奇的樣子,然後再增加高亮效果。這樣活增加視覺的觀賞性。

    • 設定預設樣式 我們需要在html中引入一個預設樣式的css檔案,內容是對程式碼的預設樣式設定。

      .token.selector{
          color: black;
      }
      .token.property{
          color: black;
      }
      .token.punctuation{
          color: black;
      }
      複製程式碼
    • 設定高亮樣式

      .token.selector{
        color: #a6e22e;
      }
      .token.property{
        color: #f92672;
      }
      .token.punctuation{
        color: #f8f8f2;
      }
      複製程式碼
    • 注意一:上面類的名稱是根據prism提供的來的,審查元素可以看到名稱

    • 注意二:CSS檔案應放在引入的prism樣式的下面,以免被覆蓋

加入html元素

  1. CSS執行結束,執行第二個函式,控制html;第三個函式控制html樣式

    var n = 0
    var clock = setInterval(() => {
    //原始碼不變
    	if (n >= result.length) {
    		window.clearInterval(clock)
    		fn2()
            fn3()
        }
    }, 10)
    複製程式碼
  2. 定義fn2()

    function fn2(){
        var paper = document.createElement('div')
        paper.id = 'paper'
        document.body.appendChild(paper)
    }
    複製程式碼
  3. 定義fn3()做一個左右結構,執行fn3(){}

    function fn3(preResult) {
        var result = `
    #paper{
        width:200px;
        height:400px;
        background:#F1E2C3;
    }
        `
        var n = 0
        var clock = setInterval(() => {
            n += 1
            code.innerHTML = preResult + result.substring(0, n)
            code.innerHTML = Prism.highlight(code.innerHTML, Prism.languages.css)
            myStyle.innerHTML = preResult + result.substring(0, n)
            if (n >= result.length) {
                window.clearInterval(clock)
            }
        }, 10)
    }
    複製程式碼

封裝函式

  1. 封裝函式
  /*把code寫到#code和style標籤裡面*/
  function writeCode(code){
      let domCode = document.querySelector('#code')
      let n = 0
      var clock = setInterval(() => {
          n += 1
          domCode.innerHTML = Prism.highlight(code.substring(0, n), Prism.languages.css)
          myStyle.innerHTML = code.substring(0, n)
          if (n >= code.length) {
              window.clearInterval(clock)
          }
      }, 10)
  }
  //封裝
  var result = `......`
  writeCode(cssCode)
  //呼叫(原result內容)
複製程式碼
  1. 回撥函式

    封裝完畢後,當我們想緊接呼叫f2()時,又尷尬了。因為setInterval()是一個鬧鐘(非同步),所以在設定好鬧鐘之後,就會立即執行f2(),可是正確的執行邏輯是在code寫完之後再呼叫f2()

    • 不等結果就是非同步

    • 回撥是拿到非同步結果的一種方式(也可以拿到同步結果)

  2. 防止覆蓋之前的程式碼,我們增加一個引數prefix

    function writeCode(prefix,code,fn){
    //....
            }
        }, 10)
    }
    複製程式碼
  3. 呼叫函式

    第一次呼叫的時候由於之前沒有內容,所以我們prefix''

    function writeCode(prefix, code, fn) {
        let domCode = document.querySelector('#code')
        let n = 0
        var clock = setInterval(() => {
            n += 1
            domCode.innerHTML = Prism.highlight(prefix + code.substring(0, n), Prism.languages.css)
            myStyle.innerHTML = prefix + code.substring(0, n)
            if (n >= code.length) {
                window.clearInterval(clock)
                fn.call()
            }
        }, 10)
    }
    複製程式碼

    呼叫函式

    writeCode('', cssCode, () => {
        createPaper(() => {
            writeCode(cssCode, htmlCode)
        })
    })
    複製程式碼

繼續優化細節

  1. 優化程式碼展示視窗,使其和展示視窗一樣高;在defulf.css裡設定為

    #code{
        height: 100vh;
        overflow: hidden;
    }
    複製程式碼
  2. 自動滾動程式碼至底部,再封裝的函式內增加程式碼

  function writeCode(prefix, code, fn) {
  //...
          domCode.scrollTop=domCode.scrollHeight
  //...        
      }, 10)
  }
複製程式碼

Element.scrollTop 屬性可以獲取或設定一個元素的內容垂直滾動的畫素數。

  1. scrollIntoView()方法:

    如果展示視窗設定的是overflow: auto;或者overflow: scroll;會自動拉到底部

    Element.scrollIntoView(false)
    複製程式碼

    element.scrollIntoView(false)為滾動至底部

    element.scrollIntoView(true)為滾動至頂部

    其他引數:

    • behavior 可選

      定義緩動動畫, "auto", "instant", 或 "smooth" 之一。預設為 "auto"

    • block 可選

      "start", "center", "end", 或 "nearest"之一。預設為 "center"

    • inline 可選

      "start", "center", "end", 或 "nearest"之一。預設為 "nearest"

      element.scrollIntoView({behavior: "instant", block: "end", inline: "nearest"});
      複製程式碼

增加簡歷展示頁

編寫JS增加編寫簡歷內容的展示視窗。與程式碼展示視窗類似

function writeMarkdown(markdown, fn) {
    let domPaper = document.querySelector('#paper')
    let n = 0
    var clock = setInterval(() => {
        n += 1
        domPaper.innerHTML = Prism.highlight(markdown.substring(0, n), Prism.languages.markdown)
        domPaper.scrollIntoView({behavior: "instant", block: "end", inline: "nearest"})
        if (n >= markdown.length) {
            window.clearInterval(clock)
            fn.call()
        }
    }, 10)
複製程式碼

變成markdown語法

利用第三方庫**marked.js**

    document.querySelector('#paper').innerHTML = marked(markdown)
    fn.call()
}
複製程式碼

寫到這裡基本就結束了,剩下的就是非同步函式呼叫的順序了。然後再慢慢的修改CSS樣式。就可以大工完成了

——遠方不遠

相關文章