如何用canvas完成在線(xiàn)簽名的示例代碼
發(fā)表時(shí)間:2023-09-06 來(lái)源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]在我們?cè)谌粘I钪,已?jīng)有很多場(chǎng)景使用在線(xiàn)簽名技術(shù),這篇文章主要介紹了如何用canvas實(shí)現(xiàn)在線(xiàn)簽名的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧隨著計(jì)算機(jī)和網(wǎng)絡(luò)技術(shù)的飛速發(fā)展,在線(xiàn)簽名技術(shù)越來(lái)越多的被應(yīng)用在無(wú)紙化辦公中,這種直觀(guān)便利的操作不僅可以大幅提升辦...
在我們?cè)谌粘I钪,已?jīng)有很多場(chǎng)景使用在線(xiàn)簽名技術(shù),這篇文章主要介紹了如何用canvas實(shí)現(xiàn)在線(xiàn)簽名的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
隨著計(jì)算機(jī)和網(wǎng)絡(luò)技術(shù)的飛速發(fā)展,在線(xiàn)簽名技術(shù)越來(lái)越多的被應(yīng)用在無(wú)紙化辦公中,這種直觀(guān)便利的操作不僅可以大幅提升辦公效率,而且使用數(shù)字化存儲(chǔ)方式,避開(kāi)了傳統(tǒng)的紙質(zhì)簽字存儲(chǔ)查閱困難等問(wèn)題。在我們?cè)谌粘I钪,已?jīng)有很多場(chǎng)景使用在線(xiàn)簽名技術(shù),例如:pos機(jī)刷卡簽字、快遞簽收簽字、銀行或機(jī)關(guān)單位業(yè)務(wù)辦理簽字等。最近在做公司的業(yè)務(wù)辦理需求,里面也涉及到在線(xiàn)簽名,我們采用的 Canvas 技術(shù)實(shí)現(xiàn),接下來(lái),讓我們來(lái)聊聊如何使用 Canvas 實(shí)現(xiàn)在線(xiàn)簽名吧!
什么是 Canvas?
Canvas 是 HTML5 新增的元素,用于在網(wǎng)頁(yè)上繪制圖形,它由 Apple 在 Safari 1.3 Web 瀏覽器中引入,之所以對(duì) HTML 擴(kuò)展的原因在于, HTML 在 Safari 中的繪圖能力能為 Mac OS X 桌面的 Dashboard 組件所使用,并且 Apple 也希望有一種方式可以在 Dashboard 中支持腳本化的圖形。Firefox 1.5 和 Opera 9 這兩個(gè)瀏覽器也緊隨 Safari 的引領(lǐng),開(kāi)始支持 Canvas 。
現(xiàn)在,Canvas 標(biāo)簽已經(jīng)是 HTML5 最偉大的改進(jìn)之一,因?yàn)樗梢宰屛覀冊(cè)诓皇褂脠D片的情況下實(shí)現(xiàn)網(wǎng)頁(yè)的圖形設(shè)計(jì)。它就像一塊畫(huà)布,本身沒(méi)有繪制能力,但卻把繪制 API 展現(xiàn)給客戶(hù)端 JavaScript,我們借助 JavaScript 的支持,在畫(huà)布范圍內(nèi)盡情發(fā)揮,達(dá)到想要的效果。
技術(shù)選型
這個(gè)功能無(wú)論是 Canvas、SVG 或是 Flash,都可以實(shí)現(xiàn),但是我們?yōu)槭裁催x擇了 Canvas 呢?
首先,由于功能上我們需要支持移動(dòng)平臺(tái),所以 Flash 我們就可以直接棄掉,它在移動(dòng)端方面并沒(méi)有得到友好的支持,但 Canvas 和 SVG 都具有很好的跨平臺(tái)能力,我們?nèi)绾尉駬,下面我們?lái)對(duì)比一下。
Canvas 基于像素,提供 2D 繪制函數(shù),提供的功能更原始,適合像素處理、動(dòng)態(tài)渲染和大數(shù)據(jù)量繪制,可控性高,繪制完了基本不記錄過(guò)程,繪圖性能會(huì)更好一點(diǎn),各大廠(chǎng)商也早都實(shí)現(xiàn)了canvas的硬件加速機(jī)制。
SVG 為矢量,提供一系列圖形元素,功能更完善,建立了一大堆可交互對(duì)象,本性長(zhǎng)于交互,但性能會(huì)弱些,更適合靜態(tài)圖片展示,高保真文檔查看和打印的應(yīng)用場(chǎng)景。
兩者各有自己的擅長(zhǎng)領(lǐng)域, 基于以上,我們選擇了 Canvas 來(lái)實(shí)現(xiàn)簽字功能。
下面,我們來(lái)看一下實(shí)現(xiàn)效果。
了解了 Canvas 來(lái)源、技術(shù)選型和最終呈現(xiàn)效果,接下來(lái)、我們會(huì)從創(chuàng)建、繪制、監(jiān)聽(tīng)、重繪、圖片處理等五部分進(jìn)行撰寫(xiě),讓我們一起走進(jìn) Canvas 繪制的世界。
創(chuàng)建畫(huà)布
首先,我們需要判斷瀏覽器是否支持 Canvas :
isCanvasSupported = (): boolean => {
let elem = document.createElement('canvas');
return !!(elem.getContext && elem.getContext('2d'));
}
然后根據(jù)判斷結(jié)果選擇創(chuàng)建 Canvas 畫(huà)布還是展示提示
{isCanvasSupported ?
<canvas ref={canvas => (this.canvas = canvas)} height={canvasHeight} width={canvasWidth}>
:對(duì)不起,當(dāng)前瀏覽器暫不支持此功能!
}
我們知道,每個(gè) Canvas 節(jié)點(diǎn)都有一個(gè)對(duì)應(yīng)的 context 對(duì)象, 我們可以通過(guò) Canvas 對(duì)象的 getContext() 方法,直接把量字符串 “2d” 作為唯一的參數(shù)傳遞給它來(lái)獲取。接下來(lái),我們通過(guò) ref 獲取 Canvas 元素,再通過(guò) getContext() 方法得到一個(gè)畫(huà)布上繪圖的環(huán)境。
let cxt = this.canvas.getContext('2d');
this.setState({cxt: cxt});
環(huán)境已經(jīng)準(zhǔn)備妥當(dāng),接下來(lái)我們就開(kāi)始進(jìn)行繪制工作吧!
繪制
首先繪制開(kāi)始路徑:
cxt.beginPath();
然后設(shè)置當(dāng)前線(xiàn)條的寬度:
cxt.lineWidth = 5;
設(shè)置線(xiàn)條的顏色:
cxt.strokeStyle = '#000';
通過(guò) moveTo 和 lineTo ,我們來(lái)繪制一條線(xiàn)
cxt.moveTo(0,0);
cxt.lineTo(150,0);
// 繪制已定義的路徑
cxt.stroke()
但是,我們發(fā)現(xiàn)繪制的線(xiàn)條比較生硬
這時(shí),我們可以通過(guò) lineCap 改變線(xiàn)條末端線(xiàn)帽的樣式,為每個(gè)末端添加圓形線(xiàn)帽,減少線(xiàn)條的生硬感
cxt.lineCap = 'round';
同時(shí),我們還可以通過(guò)設(shè)置 lineJoin,指定條線(xiàn)交匯時(shí)為圓形邊角
cxt.lineJoin = 'round';
但我們又發(fā)現(xiàn),繪制的線(xiàn)條有明顯的鋸齒,此時(shí)我們就需要借助 Canvas 為我們提供的繪制元素陰影的功能來(lái)模糊邊緣出現(xiàn)的鋸齒,因?yàn)橛嘘幱,所以我們可以適當(dāng)改變 lineWidth 值
cxt.shadowBlur = 1;
cxt.shadowColor = '#000';
是不是變得圓潤(rùn)很多,到這里,我們繪制線(xiàn)路的方法已經(jīng)準(zhǔn)備完事,接下來(lái)我們來(lái)看一下怎么監(jiān)聽(tīng)畫(huà)布事件來(lái)實(shí)現(xiàn)連貫執(zhí)行繪制吧!
監(jiān)聽(tīng)畫(huà)布事件
因?yàn)槲覀冃枰瑫r(shí)兼容 PC 端和移動(dòng)端,所以我們需要事先需要判斷一下對(duì)應(yīng)執(zhí)行的事件
this.state = {
events: ('ontouchstart' in window) ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup']
}
在畫(huà)布初始化之后,我們開(kāi)始監(jiān)聽(tīng) events[0] 事件
this.canvas.addEventListener(this.events[0], startEventHandler, false);
在startEventHandler函數(shù)中監(jiān)聽(tīng) events[1] 和 events[2] 事件
this.canvas.addEventListener(events[1], moveEventHandler, false);
this.canvas.addEventListener(events[2], endEventHandler, false);
重點(diǎn)來(lái)了,我們核心的內(nèi)容就是計(jì)算、描繪劃過(guò)的路徑
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 畫(huà)布為我們提供了一個(gè)用來(lái)作圖的平面空間,該空間的每個(gè)點(diǎn)都有自己的坐標(biāo),x 表示橫坐標(biāo),y 表示豎坐標(biāo)。原點(diǎn) (0, 0) 位于圖像左上角,x 軸的正向是原點(diǎn)向右,y 軸的正向是原點(diǎn)向下。
于是我們通過(guò) getBoundingClientRect() 方法獲得頁(yè)面 Canvas 元素相對(duì)瀏覽器視窗的位置左邊和頂部的像素距離,再利用 clientX,clientY 事件屬性返回當(dāng)事件被觸發(fā)時(shí)鼠標(biāo)指針向?qū)τ跒g覽器頁(yè)面的水平和垂直坐標(biāo),最后通過(guò) lineTo 和 stroke 來(lái)繪制路徑。
同時(shí),我們要記得在 events[2] 事件執(zhí)行之后,移除 events[1]、events[2] 事件,否則會(huì)造成一直繪制。
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);
}
如此反復(fù)循環(huán)上述事件操作,我們的簽字功能就基本實(shí)現(xiàn)了。
重新繪制
簽字過(guò)程中,簽錯(cuò)或是簽的過(guò)于潦草是必不可免的,所以我們需要支持清空簽字的功能,這時(shí),我們利用 Canvas 的 clearRect() 方法就可以幫助我們清除畫(huà)布區(qū)域內(nèi)容。
cxt.clearRect(0, 0, canvasWidth, canvasHeight);
圖片處理
繪制之后我們還沒(méi)完事,我們還需要把繪制的簽名上傳保存。這時(shí),我們可以利用 toDataURL() 方法將 Canvas 轉(zhuǎn)化成一般的圖像文件形式。
通常我們直接執(zhí)行以操作就能轉(zhuǎn)化成 data URI,然后再利用 ajax 請(qǐng)求上傳就完事了。
dataurl = this.canvas.toDataURL('image/png');
//or
dataurl = this.canvas.toDataURL('image/jpeg', 0.8);
但是,由于各種業(yè)務(wù)需求,我們有時(shí)需要攜帶頁(yè)面其他內(nèi)容,這時(shí),我們可以借助 html2canvas 來(lái)實(shí)現(xiàn)。html2canvas 可以幫助我們對(duì)瀏覽器端整個(gè)或部分頁(yè)面進(jìn)行截屏,并渲染成一個(gè) Canvas ,然后我們?cè)诶?toDataURL() 方法進(jìn)行處理。
說(shuō)道 html2canvas,順便給大家一個(gè)繞坑提示,它在一些低版本瀏覽器截出來(lái)的圖片是空白的,原因是使用了flex 布局,而html2canvas并不支持 -webkit-flex 或 -webkit-box,所以無(wú)法將 HTML 生成 Canvas,從而導(dǎo)致了截出一張白屏。
解決辦法:
通過(guò)以上幾步,我們就基本實(shí)現(xiàn)了在線(xiàn)簽名的功能。值得注意的是,這個(gè)項(xiàng)目我們使用的 React+TypeScript 環(huán)境構(gòu)建,上述代碼的實(shí)際使用需要結(jié)合自己環(huán)境進(jìn)行適當(dāng)修改。
文中使用的是 Canvas 比較淺層的繪制知識(shí),如果想利用Canvas進(jìn)動(dòng)畫(huà)制作、物理效果模擬、碰撞檢測(cè)、游戲開(kāi)發(fā)、移動(dòng)應(yīng)用開(kāi)發(fā)、大數(shù)據(jù)可視化開(kāi)發(fā),還需要我們復(fù)習(xí)一下之前學(xué)過(guò)的數(shù)學(xué)幾何、物理方面的知識(shí),然后在慢慢摸索。現(xiàn)在很多成熟的圖表插件都是用 Canvas 實(shí)現(xiàn)的,例如 Chart.js、ECharts等,里面很多好看炫酷的圖表,幾乎覆蓋了所有圖表的實(shí)現(xiàn)。Canvas還有很多開(kāi)源類(lèi)庫(kù),例如 ZRender、createJS、Pixi.js等,ECharts底層也是依賴(lài)輕量級(jí)的 Canvas 類(lèi)庫(kù) ZRender 進(jìn)行封裝的。
以上就是如何用canvas實(shí)現(xiàn)在線(xiàn)簽名的示例代碼的詳細(xì)內(nèi)容,更多請(qǐng)關(guān)注php中文網(wǎng)其它相關(guān)文章!
網(wǎng)站建設(shè)是一個(gè)廣義的術(shù)語(yǔ),涵蓋了許多不同的技能和學(xué)科中所使用的生產(chǎn)和維護(hù)的網(wǎng)站。