這期內容當中小編將會給大家?guī)碛嘘P使用canvas怎么實現(xiàn)一個在線簽名功能,文章內容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務領域包括:成都網站建設、網站建設、企業(yè)官網、英文網站、手機端網站、網站推廣等服務,滿足客戶于互聯(lián)網時代的佳木斯網站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網解決方案。努力成為您成熟可靠的網絡建設合作伙伴!
什么是 Canvas?
Canvas 是 HTML5 新增的元素,用于在網頁上繪制圖形,它由 Apple 在 Safari 1.3 Web 瀏覽器中引入,之所以對 HTML 擴展的原因在于, HTML 在 Safari 中的繪圖能力能為 Mac OS X 桌面的 Dashboard 組件所使用,并且 Apple 也希望有一種方式可以在 Dashboard 中支持腳本化的圖形。Firefox 1.5 和 Opera 9 這兩個瀏覽器也緊隨 Safari 的引領,開始支持 Canvas 。
現(xiàn)在,Canvas 標簽已經是 HTML5 最偉大的改進之一,因為它可以讓我們在不使用圖片的情況下實現(xiàn)網頁的圖形設計。它就像一塊畫布,本身沒有繪制能力,但卻把繪制 API 展現(xiàn)給客戶端 JavaScript,我們借助 JavaScript 的支持,在畫布范圍內盡情發(fā)揮,達到想要的效果。
技術選型
這個功能無論是 Canvas、SVG 或是 Flash,都可以實現(xiàn),但是我們?yōu)槭裁催x擇了 Canvas 呢?
首先,由于功能上我們需要支持移動平臺,所以 Flash 我們就可以直接棄掉,它在移動端方面并沒有得到友好的支持,但 Canvas 和 SVG 都具有很好的跨平臺能力,我們如何抉擇,下面我們來對比一下。
Canvas 基于像素,提供 2D 繪制函數,提供的功能更原始,適合像素處理、動態(tài)渲染和大數據量繪制,可控性高,繪制完了基本不記錄過程,繪圖性能會更好一點,各大廠商也早都實現(xiàn)了canvas的硬件加速機制。
SVG 為矢量,提供一系列圖形元素,功能更完善,建立了一大堆可交互對象,本性長于交互,但性能會弱些,更適合靜態(tài)圖片展示,高保真文檔查看和打印的應用場景。
兩者各有自己的擅長領域, 基于以上,我們選擇了 Canvas 來實現(xiàn)簽字功能。
下面,我們來看一下實現(xiàn)效果。
了解了 Canvas 來源、技術選型和最終呈現(xiàn)效果,接下來、我們會從創(chuàng)建、繪制、監(jiān)聽、重繪、圖片處理等五部分進行撰寫,讓我們一起走進 Canvas 繪制的世界。
創(chuàng)建畫布
首先,我們需要判斷瀏覽器是否支持 Canvas :
isCanvasSupported = (): boolean => { let elem = document.createElement('canvas'); return !!(elem.getContext && elem.getContext('2d')); }
然后根據判斷結果選擇創(chuàng)建 Canvas 畫布還是展示提示
{isCanvasSupported ?
我們知道,每個 Canvas 節(jié)點都有一個對應的 context 對象, 我們可以通過 Canvas 對象的 getContext() 方法,直接把量字符串 “2d” 作為唯一的參數傳遞給它來獲取。接下來,我們通過 ref 獲取 Canvas 元素,再通過 getContext() 方法得到一個畫布上繪圖的環(huán)境。
let cxt = this.canvas.getContext('2d'); this.setState({cxt: cxt});
環(huán)境已經準備妥當,接下來我們就開始進行繪制工作吧!
繪制
首先繪制開始路徑:
cxt.beginPath();
然后設置當前線條的寬度:
cxt.lineWidth = 5;
設置線條的顏色:
cxt.strokeStyle = '#000';
通過 moveTo 和 lineTo ,我們來繪制一條線
cxt.moveTo(0,0); cxt.lineTo(150,0); // 繪制已定義的路徑 cxt.stroke()
但是,我們發(fā)現(xiàn)繪制的線條比較生硬
這時,我們可以通過 lineCap 改變線條末端線帽的樣式,為每個末端添加圓形線帽,減少線條的生硬感
cxt.lineCap = 'round';
同時,我們還可以通過設置 lineJoin,指定條線交匯時為圓形邊角
cxt.lineJoin = 'round';
但我們又發(fā)現(xiàn),繪制的線條有明顯的鋸齒,此時我們就需要借助 Canvas 為我們提供的繪制元素陰影的功能來模糊邊緣出現(xiàn)的鋸齒,因為有陰影,所以我們可以適當改變 lineWidth 值
cxt.shadowBlur = 1; cxt.shadowColor = '#000';
是不是變得圓潤很多,到這里,我們繪制線路的方法已經準備完事,接下來我們來看一下怎么監(jiān)聽畫布事件來實現(xiàn)連貫執(zhí)行繪制吧!
監(jiān)聽畫布事件
因為我們需要同時兼容 PC 端和移動端,所以我們需要事先需要判斷一下對應執(zhí)行的事件
this.state = { events: ('ontouchstart' in window) ? ['touchstart', 'touchmove', 'touchend'] : ['mousedown', 'mousemove', 'mouseup'] }
在畫布初始化之后,我們開始監(jiān)聽 events[0] 事件
this.canvas.addEventListener(this.events[0], startEventHandler, false);
在startEventHandler函數中監(jiān)聽 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 事件屬性返回當事件被觸發(fā)時鼠標指針向對于瀏覽器頁面的水平和垂直坐標,最后通過 lineTo 和 stroke 來繪制路徑。
同時,我們要記得在 events[2] 事件執(zhí)行之后,移除 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); }
如此反復循環(huán)上述事件操作,我們的簽字功能就基本實現(xiàn)了。
重新繪制
簽字過程中,簽錯或是簽的過于潦草是必不可免的,所以我們需要支持清空簽字的功能,這時,我們利用 Canvas 的 clearRect() 方法就可以幫助我們清除畫布區(qū)域內容。
cxt.clearRect(0, 0, canvasWidth, canvasHeight);
圖片處理
繪制之后我們還沒完事,我們還需要把繪制的簽名上傳保存。這時,我們可以利用 toDataURL() 方法將 Canvas 轉化成一般的圖像文件形式。
通常我們直接執(zhí)行以操作就能轉化成 data URI,然后再利用 ajax 請求上傳就完事了。
dataurl = this.canvas.toDataURL('image/png'); //or dataurl = this.canvas.toDataURL('image/jpeg', 0.8);
但是,由于各種業(yè)務需求,我們有時需要攜帶頁面其他內容,這時,我們可以借助 html2canvas 來實現(xiàn)。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; 小結
上述就是小編為大家分享的使用canvas怎么實現(xiàn)一個在線簽名功能了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。