亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > HTML > 正文

如何用canvas實現在線簽名的示例代碼

2024-08-26 00:20:50
字體:
來源:轉載
供稿:網友

隨著計算機和網絡技術的飛速發展,在線簽名技術越來越多的被應用在無紙化辦公中,這種直觀便利的操作不僅可以大幅提升辦公效率,而且使用數字化存儲方式,避開了傳統的紙質簽字存儲查閱困難等問題。在我們在日常生活中,已經有很多場景使用在線簽名技術,例如:pos機刷卡簽字、快遞簽收簽字、銀行或機關單位業務辦理簽字等。最近在做公司的業務辦理需求,里面也涉及到在線簽名,我們采用的 Canvas 技術實現,接下來,讓我們來聊聊如何使用 Canvas 實現在線簽名吧!

什么是 Canvas?

Canvas 是 HTML5 新增的元素,用于在網頁上繪制圖形,它由 Apple 在 Safari 1.3 Web 瀏覽器中引入,之所以對 HTML 擴展的原因在于, HTML 在 Safari 中的繪圖能力能為 Mac OS X 桌面的 Dashboard 組件所使用,并且 Apple 也希望有一種方式可以在 Dashboard 中支持腳本化的圖形。Firefox 1.5 和 Opera 9 這兩個瀏覽器也緊隨 Safari 的引領,開始支持 Canvas 。

現在,Canvas 標簽已經是 HTML5 最偉大的改進之一,因為它可以讓我們在不使用圖片的情況下實現網頁的圖形設計。它就像一塊畫布,本身沒有繪制能力,但卻把繪制 API 展現給客戶端 JavaScript,我們借助 JavaScript 的支持,在畫布范圍內盡情發揮,達到想要的效果。

技術選型

這個功能無論是 Canvas、SVG 或是 Flash,都可以實現,但是我們為什么選擇了 Canvas 呢?

首先,由于功能上我們需要支持移動平臺,所以 Flash 我們就可以直接棄掉,它在移動端方面并沒有得到友好的支持,但 Canvas 和 SVG 都具有很好的跨平臺能力,我們如何抉擇,下面我們來對比一下。

  •  Canvas 基于像素,提供 2D 繪制函數,提供的功能更原始,適合像素處理、動態渲染和大數據量繪制,可控性高,繪制完了基本不記錄過程,繪圖性能會更好一點,各大廠商也早都實現了canvas的硬件加速機制。  
  • SVG 為矢量,提供一系列圖形元素,功能更完善,建立了一大堆可交互對象,本性長于交互,但性能會弱些,更適合靜態圖片展示,高保真文檔查看和打印的應用場景。

兩者各有自己的擅長領域, 基于以上,我們選擇了 Canvas 來實現簽字功能。

下面,我們來看一下實現效果。

canvas,在線簽名,代碼

了解了 Canvas 來源、技術選型和最終呈現效果,接下來、我們會從創建、繪制、監聽、重繪、圖片處理等五部分進行撰寫,讓我們一起走進 Canvas 繪制的世界。

創建畫布

首先,我們需要判斷瀏覽器是否支持 Canvas :

isCanvasSupported = (): boolean => {    let elem = document.createElement('canvas');    return !!(elem.getContext && elem.getContext('2d'));}

然后根據判斷結果選擇創建 Canvas 畫布還是展示提示

{isCanvasSupported ?     <canvas ref={canvas => (this.canvas = canvas)} height={canvasHeight} width={canvasWidth}>    :對不起,當前瀏覽器暫不支持此功能!}

我們知道,每個 Canvas 節點都有一個對應的 context 對象, 我們可以通過 Canvas 對象的 getContext() 方法,直接把量字符串 “2d” 作為唯一的參數傳遞給它來獲取。接下來,我們通過 ref 獲取 Canvas 元素,再通過 getContext() 方法得到一個畫布上繪圖的環境。

let cxt = this.canvas.getContext('2d');this.setState({cxt: cxt});

環境已經準備妥當,接下來我們就開始進行繪制工作吧!

繪制

首先繪制開始路徑:

cxt.beginPath();

然后設置當前線條的寬度:

cxt.lineWidth = 5;

設置線條的顏色:

cxt.strokeStyle = '#000';

通過 moveTo 和 lineTo ,我們來繪制一條線

cxt.moveTo(0,0);cxt.lineTo(150,0);// 繪制已定義的路徑cxt.stroke()

canvas,在線簽名,代碼

但是,我們發現繪制的線條比較生硬

這時,我們可以通過 lineCap 改變線條末端線帽的樣式,為每個末端添加圓形線帽,減少線條的生硬感

cxt.lineCap = 'round';

canvas,在線簽名,代碼

同時,我們還可以通過設置 lineJoin,指定條線交匯時為圓形邊角

cxt.lineJoin = 'round';

canvas,在線簽名,代碼 canvas,在線簽名,代碼

但我們又發現,繪制的線條有明顯的鋸齒,此時我們就需要借助 Canvas 為我們提供的繪制元素陰影的功能來模糊邊緣出現的鋸齒,因為有陰影,所以我們可以適當改變 lineWidth 值

cxt.shadowBlur = 1;cxt.shadowColor = '#000';

canvas,在線簽名,代碼

是不是變得圓潤很多,到這里,我們繪制線路的方法已經準備完事,接下來我們來看一下怎么監聽畫布事件來實現連貫執行繪制吧!

監聽畫布事件

因為我們需要同時兼容 PC 端和移動端,所以我們需要事先需要判斷一下對應執行的事件

this.state = {events: ('ontouchstart' in window) ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup']}

在畫布初始化之后,我們開始監聽 events[0] 事件

this.canvas.addEventListener(this.events[0], startEventHandler, false);

在startEventHandler函數中監聽 events[1] 和 events[2] 事件

this.canvas.addEventListener(events[1], moveEventHandler, false);this.canvas.addEventListener(events[2], endEventHandler, false);

重點來了,我們核心的內容就是計算、描繪劃過的路徑

moveEventHandler(event: any): void {    event.preventDefault();    const {ctx, isSupportTouch} = this.state;    const evt = isSupportTouch ? event.touches[0] : event;    const coverPos = this.canvas.getBoundingClientRect();    const mouseX = evt.clientX - coverPos.left;    const mouseY = evt.clientY - coverPos.top;    cxt.lineTo(       mouseX,       mouseY    );    cxt.stroke();}

了解 Canvas 的知道, Canvas 畫布為我們提供了一個用來作圖的平面空間,該空間的每個點都有自己的坐標,x 表示橫坐標,y 表示豎坐標。原點 (0, 0) 位于圖像左上角,x 軸的正向是原點向右,y 軸的正向是原點向下。

于是我們通過 getBoundingClientRect() 方法獲得頁面 Canvas 元素相對瀏覽器視窗的位置左邊和頂部的像素距離,再利用 clientX,clientY 事件屬性返回當事件被觸發時鼠標指針向對于瀏覽器頁面的水平和垂直坐標,最后通過 lineTo 和 stroke 來繪制路徑。

同時,我們要記得在 events[2] 事件執行之后,移除 events[1]、events[2] 事件,否則會造成一直繪制。

endEventHandler(event: any): void {    event.preventDefault();    const {events, moveEventHandler, endEventHandler} = this.state;    this.canvas.removeEventListener(events[1], moveEventHandler, false);    this.canvas.removeEventListener(events[2], endEventHandler, false);}

如此反復循環上述事件操作,我們的簽字功能就基本實現了。

重新繪制

簽字過程中,簽錯或是簽的過于潦草是必不可免的,所以我們需要支持清空簽字的功能,這時,我們利用 Canvas 的 clearRect() 方法就可以幫助我們清除畫布區域內容。

cxt.clearRect(0, 0, canvasWidth, canvasHeight);

圖片處理

繪制之后我們還沒完事,我們還需要把繪制的簽名上傳保存。這時,我們可以利用 toDataURL() 方法將 Canvas 轉化成一般的圖像文件形式。

通常我們直接執行以操作就能轉化成 data URI,然后再利用 ajax 請求上傳就完事了。

dataurl = this.canvas.toDataURL('image/png');//ordataurl = this.canvas.toDataURL('image/jpeg', 0.8);

但是,由于各種業務需求,我們有時需要攜帶頁面其他內容,這時,我們可以借助 html2canvas 來實現。html2canvas 可以幫助我們對瀏覽器端整個或部分頁面進行截屏,并渲染成一個 Canvas ,然后我們在利用 toDataURL() 方法進行處理。

說道 html2canvas,順便給大家一個繞坑提示,它在一些低版本瀏覽器截出來的圖片是空白的,原因是使用了flex 布局,而html2canvas并不支持 -webkit-flex 或 -webkit-box,所以無法將 HTML 生成 Canvas,從而導致了截出一張白屏。

解決辦法:

  • 不使用flex布局
  • 修改 html2canvas 源碼,在html2canvas/dist/npm/parsing/display.js 文件中增加 -webkit-flex 和 -webkit-box 也返回 DISPLAY.FLEX; 小結

通過以上幾步,我們就基本實現了在線簽名的功能。值得注意的是,這個項目我們使用的 React+TypeScript 環境構建,上述代碼的實際使用需要結合自己環境進行適當修改。

文中使用的是 Canvas 比較淺層的繪制知識,如果想利用Canvas進動畫制作、物理效果模擬、碰撞檢測、游戲開發、移動應用開發、大數據可視化開發,還需要我們復習一下之前學過的數學幾何、物理方面的知識,然后在慢慢摸索?,F在很多成熟的圖表插件都是用 Canvas 實現的,例如 Chart.js、ECharts等,里面很多好看炫酷的圖表,幾乎覆蓋了所有圖表的實現。Canvas還有很多開源類庫,例如 ZRender、createJS、Pixi.js等,ECharts底層也是依賴輕量級的 Canvas 類庫 ZRender 進行封裝的。

好了,我們今天就先聊到這里,如有任何疑問,還請留言。以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。 


注:相關教程知識閱讀請移步到HTML教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久一本一区二区青青蜜月| 亚洲欧洲午夜一线一品| 77777少妇光屁股久久一区| 亚洲国产日韩欧美综合久久| 欧美壮男野外gaytube| 欧美成人sm免费视频| 欧美中文在线观看| 精品亚洲夜色av98在线观看| 成人精品久久av网站| 青草青草久热精品视频在线网站| 精品毛片网大全| 欧美刺激性大交免费视频| 国产精品色视频| 欧美视频在线视频| 欧美激情一区二区三区高清视频| 国内精品久久久久久| 粉嫩老牛aⅴ一区二区三区| 欧美日韩亚洲网| 日韩电影在线观看中文字幕| 国产成人精品一区二区| 欧美成人四级hd版| 日韩视频永久免费观看| 欧美性猛xxx| 亚洲成色777777女色窝| 久久香蕉国产线看观看av| 国产精品精品久久久久久| www.日本久久久久com.| 亚洲xxxx3d| 国产精品成av人在线视午夜片| 欧美午夜片在线免费观看| 欧美刺激性大交免费视频| 亚洲激情视频在线播放| 中文字幕亚洲综合久久筱田步美| 最近2019年日本中文免费字幕| 欧美午夜视频在线观看| 正在播放欧美视频| 欧美一级淫片丝袜脚交| 日日骚av一区| 国产精品吊钟奶在线| 亚洲在线免费视频| 国产欧美一区二区三区在线看| 韩国精品美女www爽爽爽视频| 国产在线精品成人一区二区三区| 亚洲女同精品视频| 成人网在线视频| 亚洲成人精品视频在线观看| 国产视频福利一区| 国产91成人在在线播放| 波霸ol色综合久久| 日韩网站在线观看| 色播久久人人爽人人爽人人片视av| 丝袜一区二区三区| 欧美激情一区二区三区在线视频观看| 欧美精品福利在线| 日韩中文字幕视频在线观看| 久久精品国产久精国产一老狼| 91黑丝在线观看| 午夜精品一区二区三区在线| 美女精品视频一区| 久久国产精品久久精品| 国产第一区电影| 欧美激情啊啊啊| 日韩精品中文字幕久久臀| 91精品在线观看视频| 亚洲男人的天堂网站| 久久免费少妇高潮久久精品99| 91沈先生作品| 日韩av网站电影| 精品欧美aⅴ在线网站| 亚洲成人精品久久久| 精品国产一区二区三区久久| 精品国产31久久久久久| 久久精品视频导航| 日韩精品在线观看网站| 亚洲欧美在线免费| 国产美女被下药99| 亚洲精品xxx| 国产精品第一区| 国产欧美精品va在线观看| 亚洲二区中文字幕| 亚洲欧美日韩国产精品| 国产精品极品尤物在线观看| 亚洲xxxxx| 国外视频精品毛片| 国产精品免费一区二区三区都可以| 国产婷婷成人久久av免费高清| 美女av一区二区三区| 欧美在线视频导航| 中文字幕精品网| 精品视频在线播放免| 欧美丰满老妇厨房牲生活| 欧美成人在线免费视频| 欧美激情一区二区久久久| 欧美精品激情在线观看| 伊人久久男人天堂| 一区二区三区精品99久久| 亚洲第一在线视频| 欧美性猛交xxxx乱大交极品| 亚洲国产高清高潮精品美女| 亚洲精品久久久久久久久| 中文字幕精品—区二区| 91网站在线看| 欧美成人精品一区二区三区| 国产中文欧美精品| 两个人的视频www国产精品| 日韩毛片在线看| 亚洲精品乱码久久久久久按摩观| 成人亚洲综合色就1024| 国产欧美精品日韩精品| 精品亚洲一区二区| 亚洲欧美日韩区| 久久九九免费视频| 国产91露脸中文字幕在线| 久久久国产精彩视频美女艺术照福利| 亚洲日韩中文字幕在线播放| 欧美又大又粗又长| 2023亚洲男人天堂| 亚洲精品国产精品国产自| 亚洲xxx大片| 国产亚洲视频在线观看| 国产成人精品a视频一区www| 国产成人精品在线播放| 性欧美视频videos6一9| 国产精品久久久久久久久久99| 国产精品爱久久久久久久| 日韩视频免费在线| 北条麻妃99精品青青久久| 日韩美女主播视频| 亚洲欧洲日本专区| 欧美裸身视频免费观看| 久久精品国产亚洲| 国产成人精品一区二区在线| 亚洲欧洲xxxx| 亚洲成人av资源网| 久久6精品影院| 国产精品啪视频| 国产美女精品视频| 国产精品久久久久久久久粉嫩av| 国内精品400部情侣激情| 亚洲精品资源美女情侣酒店| 欧美亚州一区二区三区| 成人免费淫片视频软件| 一区二区三区视频免费在线观看| 日韩欧美成人免费视频| 久久久精品一区| 国产啪精品视频网站| 亚洲美女视频网站| 久久久综合av| 国产精品中文字幕在线| 日韩精品在线免费观看| 成人观看高清在线观看免费| 亚洲成**性毛茸茸| 久久人人爽亚洲精品天堂| 久久偷看各类女兵18女厕嘘嘘| 欧美大秀在线观看| 国产亚洲美女久久| 韩国v欧美v日本v亚洲| 高清欧美性猛交xxxx黑人猛交| 亚洲在线视频观看| 国产欧美精品一区二区三区介绍| 亚洲成人a**站| 亚洲国产精品人人爽夜夜爽| 成人久久精品视频| 欧美又大又粗又长|