整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          HTML5 的JavaScript 客戶端PDF解決方案-jsPDF

          和往常一樣,jsPDF是一個開源的客戶端的PDF解決方案,在之前的文章中已經介紹過幾個Web端和PDF相關的庫,jsPDF同樣是一個不錯的客戶端PDF引 SDK,你可以通過jsPDF在客戶端完成相關操作,它包含了非常豐富的API,幫助你完成一系列的復雜操作!可以說它是相當領先的HTML5客戶端解決方案了!



          Github

          https://github.com/MrRio/jsPDF

          Github star數17k+,可以說相當受歡迎了!


          安裝使用

          一般情況下我們會考慮使用包管理,常見的就是npm了,因此安裝非常簡單

          npm install jspdf --save
          

          或者也可以使用yarn

          yarn add jspdf
          

          接下來就是制作你的文件的時候了

          默認導出為a4紙張,縱向,使用毫米表示單位


          var doc = new jsPDF()
          doc.text('Hello world!', 10, 10)
          doc.save('a4.pdf')
          

          如果要更改紙張尺寸,方向或單位,可以執行以下操作:


          var doc = new jsPDF({
           orientation: 'landscape',
           unit: 'in',
           format: [4, 2]
          })
          doc.text('Hello world!', 1, 1)
          doc.save('two-by-four.pdf')
          

          使用UTF-8 / TTF

          PDF中的14種標準字體僅限于ASCII代碼頁。如果要使用UTF-8,則必須集成自定義字體,該字體提供所需的字形。jsPDF支持.ttf文件。因此,如果你希望在pdf中使用中文文本,則您的字體必須具有必要的中文字形。因此,請檢查您的字體是否支持所需的字形,否則它將顯示空白而不是文本。



          要將字體添加到jsPDF,在/fontconverter/fontconverter.html中使用官網提供的fontconverter。fontconverter將創建一個js文件,其中包含提供的ttf文件的內容作為base64編碼的字符串和jsPDF的附加代碼。你只需將生成的js-File添加到項目中即可。然后,就可以在代碼中使用setFont-method并編寫UTF-8編碼文本。



          Angular/Webpack/React等配置

          常規操作

          import * as jsPDF from 'jspdf'
          

          有些框架,必須像下面這樣

          import jsPDF from 'jspdf';
          


          API

          jsPDF的api非常豐富,在這里就不提供相關地址了,在Github必然找的到,本文重點不在于介紹jsPDF的用法,將部分API截圖展示,通過名稱大致能猜到一些意思,具體用法需要參考官網文檔:













          從截圖來看,其文檔特別的詳細,具體到每一個API在js文件的行數,便于閱讀源代碼,包括參數以及返回值都非常明確:



          在線DEMO

          官方提供了一個在線demo,可以直接運行代碼,感興趣的可以先嘗試一下:



          總結

          jsPDF是筆者見過類似產品中較為突出的,幾乎涵蓋了所有PDF相關操作,非常詳細的文檔也讓開發者,輕松上手,在線demo還能快速學習,如果你的項目對PDF的操作比較多,不妨嘗試下jsPDF,唯一需要注意的就是解決字體問題,但是上文也提到過解決方案,感興趣的可以進行體驗!

          javascript 是一門單線程的語言,在同一個時間只能做完成一件任務,如果有多個任務,就必須排隊,前面一個任務完成,再去執行后面的任務。作為瀏覽器端的腳本語言,javascript 的主要功能是用來和用戶交互以及操作 dom。假設 javascript 不是單線程語言,在一個線程里我們給某個 dom 節點增加內容的時候,另一個線程同時正在刪除這個 dom 節點的內容,則會造成混亂。

          由于 js 單線程的設計,假設 js 程序的執行都是同步。如果執行一些耗時較長的程序,例如 ajax 請求,在請求開始至請求響應的這段時間內,當前的工作線程一直是空閑狀態, ajax 請求后面的 js 代碼只能等待請求結束后執行,因此會導致 js 阻塞的問題。

          javascript 單線程指的是瀏覽器中負責解釋和執行 javascript 代碼的只有一個線程,即為 js 引擎線程,但是瀏覽器的渲染進程是提供多個線程的,如下:

          1. js 引擎線程
          2. 事件觸發線程
          3. 定時器觸發線程
          4. 異步 http 請求線程
          5. GUI 渲染線程

          一、異步 & 同步

          為解決上述類似上述 js 阻塞的問題,js 引入了同步和異步的概念。

          1、什么是同步?

          “同步”就是后一個任務等待前一個任務結束后再去執行。

          2、什么是異步?

          “異步”與同步不同,每一個異步任務都有一個或多個回調函數。webapi 會在其相應的時機里將回調函數添加進入消息隊列中,不直接執行,然后再去執行后面的任務。直至當前同步任務執行完畢后,再把消息隊列中的消息添加進入執行棧進行執行。

          異步任務在瀏覽器中一般是以下:

          1. 網絡請求
          2. 計時器
          3. DOM 監聽事件
          4. ...

          二、什么是執行棧(stack)、堆(heap)、事件隊列(task queue)?

          1、執行棧

          “棧”是一種數據結構,是一種線性表。特點為 LIFO,即先進后出 (last in, first out)。

          利用數組的 push 和 shift 可以實現壓棧和出棧的操作。

          在代碼運行的過程中,函數的調用會形成一個由若干幀組成的棧。

          function foo(b) {
            let a = 10;
            return a + b + 11;
          }
          
          function bar(x) {
            let y = 3;
            return foo(x * y);
          }
          
          console.log(bar(7))

          上面代碼最終會在控制臺打印42,下面梳理一下它的執行順序。

          1. console.log 函數作為第一幀壓入棧中。
          2. 調用 bar,第二幀被壓入棧中。幀中包含著 bar 的變量對象。
          3. bar 調用 foo,foo 做一位第三幀被壓入棧中,幀中包含著 foo 的變量對象。
          4. foo 執行完畢然后返回。被彈出棧。
          5. bar 執行完畢然后返回,被彈出棧。
          6. log 函數接收到 bar 的返回值。執行完畢后,出棧。此時棧已空。

          2、堆

          對象被分配在堆中,堆是一個用來表示一大塊(通常是非結構化的)內存區域的計算機術語。

          堆和棧的區別

          首先,stack 是有結構的,每個區塊按照一定次序存放,可以明確知道每個區塊的大小;heap 是沒有結構的,數據可以任意存放。因此,

          stack 的尋址速度要快于 heap。

          其次,每個線程分配一個 stack,每個進程分配一個 heap,也就是說,stack 是線程獨占的,heap 是線程共用的。

          此外,stack 創建的時候,大小是確定的,數據從超過這個大小,就發生 stack overflow 錯誤,而 heap 的大小是不確定的,

          需要的話可以不斷增加。

          public void Method1()
          {
              int i=4;
          
              int y=2;
          
              class1 cls1 = new class1();
          }

          上面代碼這三個變量和一個對象實例在內存中的存放方式如下。

          從上圖可以看到,i、y和cls1都存放在stack,因為它們占用內存空間都是確定的,而且本身也屬于局部變量。但是,cls1指向的對象實例存放在heap,因為它的大小不確定。作為一條規則可以記住,所有的對象都存放在heap。

          接下來的問題是,當Method1方法運行結束,會發生什么事?

          回答是整個stack被清空,i、y和cls1這三個變量消失,因為它們是局部變量,區塊一旦運行結束,就沒必要再存在了。而heap之中的那個對象實例繼續存在,直到系統的垃圾清理機制(garbage collector)將這塊內存回收。因此,一般來說,內存泄漏都發生在heap,即某些內存空間不再被使用了,卻因為種種原因,沒有被系統回收。

          3、事件隊列和事件循環

          隊列是一種數據結構,也是一種特殊的線性表。特點為 FIFO,即先進先出(first in, first out)

          利用數組的 push 和 pop 可實現入隊和出隊的操作。

          事件循環和事件隊列的維護是由事件觸發線程控制的。

          事件觸發線程線程同樣是由瀏覽器渲染引擎提供的,它會維護一個事件隊列。

          js 引擎遇到上文所列的異步任務后,會交個相應的線程去維護異步任務,等待某個時機,然后由事件觸發線程將異步任務對應的回調函數加入到事件隊列中,事件隊列中的函數等待被執行。

          js 引擎在執行過程中,遇到同步任務,會將任務直接壓入執行棧中執行,當執行棧為空(即 js 引擎線程空閑), 事件觸發線程 會從事件隊列中取出一個任務(即異步任務的回調函數)放入執行在棧中執行。

          執行完了之后,執行棧再次為空,事件觸發線程會重復上一步的操作,再從事件隊列中取出一個消息,這種機制就被稱為 事件循環 (Event Loop)機制。

          為了更好地理解Event Loop,請看下圖(轉引自Philip Roberts的演講《Help, I'm stuck in an event-loop》)。

          例子代碼:

          console.log('script start')
          
          setTimeout(() => {
            console.log('timer 1 over')
          }, 1000)
          
          setTimeout(() => {
            console.log('timer 2 over')
          }, 0)
          
          console.log('script end')
          
          // script start
          // script end
          // timer 2 over
          // timer 1 over

          模擬 js 引擎對其執行過程:

          第一輪事件循環:

          1. console.log 為同步任務,入棧,打印“script start”。出棧。
          2. setTimeout 為異步任務,入棧,交給定時器觸發線程處理(在1秒后加入將回調加入事件隊列)。出棧。
          3. setTimeout 為異步任務,入棧,交給定時器觸發線程處理(在4ms之內將回調加入事件隊列)。出棧。
          4. console.log 為同步任務,入棧,打印"script end"。出棧。

          此時,執行棧為空,js 引擎線程空閑。便從事件隊列中讀取任務,此時隊列如下:

          第二輪事件循環

          1. js 引擎線程從事件隊列中讀取 cb2 加入執行棧并執行,打印”time 2 over“。出棧。

          第三輪事件循環

          1. js 引擎從事件隊列中讀取 cb1 加入執行棧中并執行,打印”time 1 over“ 。出棧。

          注意點:

          上面,timer 2 的延時為 0ms,HTML5標準規定 setTimeout 第二個參數不得小于4(不同瀏覽器最小值會不一樣),不足會自動增加,所以 "timer 2 over" 還是會在 "script end" 之后。

          就算延時為0ms,只是 time 2 的回調函數會立即加入事件隊列而已,回調的執行還是得等到執行棧為空時執行。

          四、宏任務 & 微任務

          在 ES6 新增 Promise 處理異步后,js 執行引擎的處理過程又發生了新的變化。

          看代碼:

          console.log('script start')
          
          setTimeout(function() {
              console.log('timer over')
          }, 0)
          
          Promise.resolve().then(function() {
              console.log('promise1')
          }).then(function() {
              console.log('promise2')
          })
          
          console.log('script end')
          
          // script start
          // script end
          // promise1
          // promise2
          // timer over

          這里又新增了兩個新的概念, macrotask (宏任務)和 microtask (微任務)。

          所有的任務都劃分到宏任務和微任務下:

          • macrotask : script 主代碼塊、setTimeout、setInterval、requestAnimationFrame、node 中的setimmediate 等。
          • microtask : Promise.then catch finally、MutationObserver、node 中的process.nextTick 等。

          js 引擎首先執行主代碼塊。

          執行棧每次執行的代碼就是一個宏任務,包括任務隊列(宏任務隊列)中的。執行棧中的任務執行完畢后,js 引擎會從宏任務隊列中去添加任務到執行棧中,即同樣是事件循環的機制。

          當在執行宏任務遇到微任務 Promise.then 時,會創建一個微任務,并加入到微任務隊列中的隊尾。

          微任務是在宏任務執行的時候創建的,而在下一個宏任務執行之前,瀏覽器會對頁面重新渲染(task >> render >> task(任務隊列中讀取))。 同時,在上一個宏任務執行完成后,頁面渲染之前,會執行當前微任務隊列中的所有微任務。

          所以上述代碼的執行過程就可以解釋了。

          js 引擎執行 promise.then 時,promise1、promise2 被認為是兩個微任務按照代碼的先后順序被加入到微任務隊列中,script end執行后,空。

          此時當前宏任務(script 主代碼塊)執行完畢,并不從當前宏任務隊列中讀取任務。而是立馬清空當前宏任務所產生的微任務隊列。將兩個微任務依次放入執行棧中執行。執行完畢,打印 promise1、promise2。棧空。 此時,第一輪事件循環結束。

          緊接著,再去讀取宏任務隊列中的任務,time over 被打印。棧空。

          因此,宏任務和微任務的執行機制如下:

          1. 執行一個宏任務(棧中沒有就從宏任務隊列中獲取)
          2. 執行過程中遇到微任務,就將它添加到微任務的任務隊列中
          3. 宏任務執行完畢,立即執行當前微任務隊列中的所有微任務(依次執行)
          4. 當前所有微任務執行完畢后,開始檢查渲染,GUI 線程接管渲染
          5. 渲染完畢后,JS 引擎繼續開始下一個宏任務,從宏任務隊列中獲取

          async & await

          因為,async 和 await 本質上還是基于 Promise 的封裝,而 Promise 是屬于微任務的一種。所以使用 await 關鍵字與 Promise.then 效果類似:

          setTimeout(_ => console.log(4))
          
          async function main() {
            console.log(1)
            await Promise.resolve()
            console.log(3)
          }
          
          main()
          
          console.log(2)
          // 1
          // 2
          // 3
          // 4

          async 函數在 await 之前的代碼都是同步執行的, 可以理解為 await 之前的代碼都屬于 new Promise 時傳入的代碼,await 之后的所有代碼都是 Promise.then 中的回調,即在微任務隊列中。

          五、總結

          1. js 單線程實際上解釋執行 js 代碼的只有一個線程,但是瀏覽器的渲染是多線程的。
          2. 異步和同步的概念與區別,異步任務有哪些。
          3. 棧、堆、隊列的特點和使用場景。
          4. 事件隊列以及事件循環機制。
          5. es6 下,宏任務與微任務的執行過程。

          參考:

          • JavaScript 異步與事件循環
          • 并發模型與事件循環
          • 微任務、宏任務與Event-Loop
          • JavaScript 運行機制詳解:再談Event Loop
          • JS事件循環
          • [譯] 深入理解 JavaScript 事件循環(二)— task and microtask
          • Help, I'm stuck in an event-loop

          原文作者:大芒果哇

          原文地址:https://www.cnblogs.com/shenggao/p/13799566.html

          Fabric.js是一個簡單但功能強大的Javascript HTML5 canvas庫,Fabric在canvas元素之上提供交互式對象模型,而且Fabric還內置SVG-to-canvas(和canvas-to-SVG)解析器,在Github上star數超過13k+,可見其受歡迎程度!



          特性簡介

          1、使用Fabric.js,您可以在畫布上創建和填充對象;對象就像簡單的幾何形狀



          2、或由數百或數千條簡單路徑組成的復雜形狀



          3、或者舊風格的圖像



          4、任何形狀的漸變



          5、您可以添加文本并動態操作其大小,對齊方式,字體系列和其他屬性



          6、將圖像過濾器應用于圖像



          7、有內置的動畫支持



          8、拖動圖像,可以將對象組合在一起,并同時對其進行操作



          9、拖拽方法和方向旋轉



          10、Canvas可以序列化為JSON或SVG,并可以隨時恢復





          12、使用免費繪圖來創建任何你喜歡的東西



          其他特性

          • Subclassing
          • 觸摸設備支持
          • Node.js支持(和npm包)

          如何獲取?

          既然是開源項目,那么當然可以到Github上獲取相關代碼,其一直保持更新維護并繼續增強其功能,同時官網還提供了非常詳細的文檔,以及非常豐富的Demo,下面我們將進行截圖預覽!



          Demo

          • 免費繪圖


          • 文本填入

          相信用過截圖工具或者windows繪圖工具的都知道什么效果



          • 旋轉天體


          • 圖像過濾器


          • HTML5 <video>元素


          • 矩陣變換


          以上是選取一些案例進行演示,可能效果不佳,感興趣的小伙伴可以去官網看看Demo



          兼容性

          其兼容性相當的不錯

          • Firefox 2+
          • Safari 3+
          • Opera 9.64+
          • Chrome (all versions)
          • IE10, IE11, Edge

          安裝

          npm install fabric --save
          

          文檔一覽

          這里就大致看下文檔具備哪些內容,由于文檔很詳細,就不在細說,而且借助瀏覽器翻譯,看懂是完全沒問題的



          最簡單的示例

          <!DOCTYPE html>
          <html>
          <head>
          </head>
          <body>
           <canvas id="canvas" width="300" height="300"></canvas>
           <script src="lib/fabric.js"></script>
           <script>
           var canvas = new fabric.Canvas('canvas');
           var rect = new fabric.Rect({
           top : 100,
           left : 100,
           width : 60,
           height : 70,
           fill : 'red'
           });
           canvas.add(rect);
           </script>
          </body>
          </html>
          

          自定義構建

          官方文檔提供了非常人性化的一個地方就是你可以選擇你需要的部分進行構建




          總結

          總體來說Fabric.js是一個非常值得使用的JavaScript庫,不管是功能還是兼容性都是非常優秀的,而且你可以使用它來構建非常強大的BS端應用。如在線繪圖等,如果你對它感興趣,不放嘗試一下,不會讓你失望!


          主站蜘蛛池模板: 国产一区二区三区露脸| 中文字幕AV无码一区二区三区| 九九久久99综合一区二区| 男人免费视频一区二区在线观看| 亚洲AV噜噜一区二区三区| 欧洲亚洲综合一区二区三区| 国内精品一区二区三区最新| 日韩一区二区在线观看| 中文字幕一区二区人妻性色| 中文人妻无码一区二区三区| AV鲁丝一区鲁丝二区鲁丝三区| 成人区人妻精品一区二区不卡| 无码av不卡一区二区三区| 精品少妇一区二区三区视频 | 国产精品亚洲专一区二区三区| 性色av无码免费一区二区三区| 乱人伦一区二区三区| 国产激情无码一区二区| 中文字幕日韩欧美一区二区三区| 色系一区二区三区四区五区| 亚洲国产精品一区第二页| 精产国品一区二区三产区| 不卡一区二区在线| AV无码精品一区二区三区| 国产成人精品无码一区二区老年人| 一区二区三区视频在线播放| 精品国产免费一区二区| 国产精品一区二区av| 国产免费一区二区三区| 午夜视频一区二区| 韩国福利一区二区三区高清视频| 免费无码一区二区三区| 精品久久久中文字幕一区| 丰满人妻一区二区三区视频53| 性色av一区二区三区夜夜嗨 | 91福利视频一区| 毛片无码一区二区三区a片视频| 精品一区二区三区水蜜桃| 国产av一区二区三区日韩| 无码国产精品一区二区免费I6| 精品中文字幕一区二区三区四区|