日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

前端實(shí)現(xiàn)電子簽名(web、移動(dòng)端)通用

作者:zhangyizuishuai 更新時(shí)間: 2023-07-24 編程語(yǔ)言

開啟生長(zhǎng)之旅!這是我參加「日新方案 12 月更文挑戰(zhàn)」的第15天,點(diǎn)擊檢查活動(dòng)概況

前語(yǔ)
在現(xiàn)在的年代發(fā)展中,從以前的手寫簽名,逐步衍生出了電子簽名。電子簽名和紙質(zhì)手寫簽名一樣具有法令效應(yīng)。電子簽名現(xiàn)在主要還是在需求個(gè)人確認(rèn)的產(chǎn)品環(huán)節(jié)和司法類相關(guān)的產(chǎn)品上較多。

舉個(gè)常用的例子,咱們都用過(guò)釘釘,釘釘上面就有電子簽名,信任咱們這肯定是知道的。

那作為前端的咱們?cè)趺赐瓿呻娮雍灻兀科鋵?shí)在html5中現(xiàn)已呈現(xiàn)了一個(gè)重要級(jí)別的輔佐標(biāo)簽,是啥呢?那就是canvas。

什么是canvas
Canvas(畫布)是在HTML5中新增的標(biāo)簽用于在網(wǎng)頁(yè)實(shí)時(shí)生成圖畫,并且能夠操作圖畫內(nèi)容,基本上它是一個(gè)能夠用JavaScript操作的位圖(bitmap)。Canvas 目標(biāo)表明一個(gè) HTML 畫布元素 -。它沒(méi)有自己的行為,但是界說(shuō)了一個(gè) API 支撐腳本化客戶端繪圖操作。

大白話就是canvas是一個(gè)能夠在上面經(jīng)過(guò)javaScript畫圖的標(biāo)簽,經(jīng)過(guò)其供給的context(上下文)及Api進(jìn)行制作,在這個(gè)過(guò)程中canvas充任畫布的角色。


怎么運(yùn)用
canvas給咱們供給了許多的Api,供咱們運(yùn)用,咱們只需求在body標(biāo)簽中創(chuàng)立一個(gè)canvas標(biāo)簽,在script標(biāo)簽中拿到canvas這個(gè)標(biāo)簽的節(jié)點(diǎn),并創(chuàng)立context(上下文)就能夠運(yùn)用了。

... 步入正題。

完成電子簽名
知道幾許的朋友都很清楚,線有點(diǎn)繪成,面由線繪成。

多點(diǎn)成線,多線成面。

所以咱們實(shí)踐只需求拿到當(dāng)時(shí)接觸的坐標(biāo)點(diǎn),進(jìn)行成線處理就能夠了。

在body中增加canvas標(biāo)簽
在這兒咱們不僅需求在在body中增加canvas標(biāo)簽,咱們還需求增加兩個(gè)按鈕,分別是撤銷和保存(后面咱們會(huì)用到)。

撤銷 保存
增加文件 我這兒全程運(yùn)用js進(jìn)行款式設(shè)置及增加。

// 裝備內(nèi)容
const config = {
width: 400, // 寬度
height: 200, // 高度
lineWidth: 5, // 線寬
strokeStyle: ‘red’, // 線條色彩
lineCap: ‘round’, // 設(shè)置線條兩頭圓角
lineJoin: ‘round’, // 線條交匯處圓角
}
獲取canvas實(shí)例
這兒咱們運(yùn)用querySelector獲取canvas的dom實(shí)例,并設(shè)置款式和創(chuàng)立上下文。

// 獲取canvas 實(shí)例
const canvas = document.querySelector('canvas')
// 設(shè)置寬高
canvas.width = config.width
canvas.height = config.height
// 設(shè)置一個(gè)邊框,方便咱們檢查及運(yùn)用
canvas.style.border = '1px solid #000'
// 創(chuàng)立上下文
const ctx = canvas.getContext('2d')

基礎(chǔ)設(shè)置
咱們將canvas的填充色為透明,并制作填充一個(gè)矩形,作為咱們的畫布,假如不設(shè)置這個(gè)填充背景色,在咱們初識(shí)渲染的時(shí)候是一個(gè)黑色背景,這也是它的一個(gè)默認(rèn)色。

// 設(shè)置填充背景色
ctx.fillStyle = 'transparent'
// 制作填充矩形
ctx.fillRect(
    0, // x 軸開端制作方位
    0, // y 軸開端制作方位
    config.width, // 寬度
    config.height // 高度
);

前次制作途徑保存
這兒咱們需求聲明一個(gè)目標(biāo),用來(lái)記錄咱們上一次制作的途徑完畢坐標(biāo)點(diǎn)及偏移量。

保存前次坐標(biāo)點(diǎn)這個(gè)我不用說(shuō)咱們都懂;
為啥需求保存偏移量呢,由于鼠標(biāo)和畫布上的間隔是存在必定的偏移間隔,在咱們制作的過(guò)程中需求減去這個(gè)偏移量,才是咱們實(shí)踐的制作坐標(biāo)。
但我發(fā)現(xiàn)chrome中不需求減去這個(gè)偏移量,拿到的就是實(shí)踐的坐標(biāo),之前在微信小程序中運(yùn)用就需求減去偏移量,需求在小程序中運(yùn)用的朋友需求注意這一點(diǎn)哦。
// 保存前次制作的 坐標(biāo)及偏移量
const client = {
offsetX: 0, // 偏移量
offsetY: 0,
endX: 0, // 坐標(biāo)
endY: 0
}
設(shè)備兼容
咱們需求它不僅能夠在web端運(yùn)用,還需求在移動(dòng)端運(yùn)用,咱們需求給它做設(shè)備兼容處理。咱們經(jīng)過(guò)調(diào)用navigator.userAgent獲取當(dāng)時(shí)設(shè)備信息,進(jìn)行正則匹配判別。

// 判別是否為移動(dòng)端
const mobileStatus = (/Mobile|Android|iPhone/i.test(navigator.userAgent))

初始化
這兒咱們?cè)诒O(jiān)聽鼠標(biāo)按下(mousedown)(web端)/接觸開端(touchstart)的時(shí)候進(jìn)行初始化,事情監(jiān)聽采用addEventListener。

// 創(chuàng)立鼠標(biāo)/手勢(shì)按下監(jiān)聽器
window.addEventListener(mobileStatus ? "touchstart" : "mousedown", init)

三元判別闡明: 這兒當(dāng)mobileStatus為true時(shí)則表明為移動(dòng)端,反之則為web端,后續(xù)運(yùn)用到的三元依舊是這個(gè)意思。

聲明初始化辦法

咱們?cè)黾右粋€(gè)init辦法作為監(jiān)聽鼠標(biāo)按下/接觸開端的回調(diào)辦法。

這兒咱們需求獲取到當(dāng)時(shí)鼠標(biāo)按下/接觸開端的偏移量和坐標(biāo),進(jìn)行開端點(diǎn)制作。

Tips:web端能夠直接經(jīng)過(guò)event中取到,而移動(dòng)端則需求在event.changedTouches[0]中取到。

這兒咱們?cè)诔跏蓟笤俦O(jiān)聽鼠標(biāo)的移動(dòng)。

// 初始化
const init = event => {
    // 獲取偏移量及坐標(biāo)
    const { offsetX, offsetY, pageX, pageY } = mobileStatus ? event.changedTouches[0] : event 
    // 修正前次的偏移量及坐標(biāo)
    client.offsetX = offsetX
    client.offsetY = offsetY
    client.endX = pageX
    client.endY = pageY
    // 鏟除以上一次 beginPath 之后的一切途徑,進(jìn)行制作
    ctx.beginPath()
    // 依據(jù)裝備文件設(shè)置進(jìn)行相應(yīng)裝備
    ctx.lineWidth = config.lineWidth
    ctx.strokeStyle = config.strokeStyle
    ctx.lineCap = config.lineCap
    ctx.lineJoin = config.lineJoin
    // 設(shè)置畫線開端點(diǎn)位
    ctx.moveTo(client.endX, client.endY)
    // 監(jiān)聽 鼠標(biāo)移動(dòng)或手勢(shì)移動(dòng)
    window.addEventListener(mobileStatus ? "touchmove" : "mousemove", draw)
}

制作
這兒咱們?cè)黾又谱鱠raw辦法,作為監(jiān)聽鼠標(biāo)移動(dòng)/接觸移動(dòng)的回調(diào)辦法。

// 制作
const draw = event => {
    // 獲取當(dāng)時(shí)坐標(biāo)點(diǎn)位
    const { pageX, pageY } = mobileStatus ? event.changedTouches[0] : event
    // 修正最終一次制作的坐標(biāo)點(diǎn)
    client.endX = pageX
    client.endY = pageY
    // 依據(jù)坐標(biāo)點(diǎn)位移動(dòng)增加線條
    ctx.lineTo(pageX , pageY )
    // 制作
    ctx.stroke()
}

完畢制作
增加了監(jiān)聽鼠標(biāo)移動(dòng)/接觸移動(dòng)咱們必定要記住撤銷監(jiān)聽并完畢制作,不然的話它會(huì)一直監(jiān)聽并制作的。

這兒咱們創(chuàng)立一個(gè)cloaseDraw辦法作為鼠標(biāo)彈起/完畢接觸的回調(diào)辦法來(lái)完畢制作并移除鼠標(biāo)移動(dòng)/接觸移動(dòng)的監(jiān)聽。

canvas完畢制作則需求調(diào)用closePath()讓其完畢制作

// 完畢制作
const cloaseDraw = () => {
    // 完畢制作
    ctx.closePath()
    // 移除鼠標(biāo)移動(dòng)或手勢(shì)移動(dòng)監(jiān)聽器
    window.removeEventListener("mousemove", draw)
}

增加完畢回調(diào)監(jiān)聽器

// 創(chuàng)立鼠標(biāo)/手勢(shì) 彈起/離開 監(jiān)聽器
window.addEventListener(mobileStatus ? "touchend" :"mouseup", cloaseDraw)

ok,現(xiàn)在咱們的電子簽名功能還差一丟丟能夠完成完了,現(xiàn)在現(xiàn)已能夠正常的簽名了。

咱們來(lái)看一下作用:

撤銷功能/清空畫布
咱們?cè)趧傞_端創(chuàng)立的那兩個(gè)按鈕開端排上用場(chǎng)了。

這兒咱們創(chuàng)立一個(gè)cancel的辦法作為撤銷并清空畫布運(yùn)用

// 撤銷-清空畫布
const cancel = () => {
    // 清空當(dāng)時(shí)畫布上的一切制作內(nèi)容
    ctx.clearRect(0, 0, config.width, config.height)
}

然后咱們將這個(gè)辦法和撤銷按鈕進(jìn)行綁定

 <button onclick="cancel()">撤銷</button>

保存功能
這兒咱們創(chuàng)立一個(gè)save的辦法作為保存畫布上的內(nèi)容運(yùn)用。

將畫布上的內(nèi)容保存為圖片/文件的辦法有許多,比較常見的是blob和toDataURL這兩種方案,但toDataURL這哥們沒(méi)blob強(qiáng),適配也不咋滴。所以咱們這兒采用a標(biāo)簽 ? blob方案完成圖片的保存下載。

// 保存-將畫布內(nèi)容保存為圖片
const save = () => {
    // 將canvas上的內(nèi)容轉(zhuǎn)成blob流
    canvas.toBlob(blob => {
        // 獲取當(dāng)時(shí)時(shí)間并轉(zhuǎn)成字符串,用來(lái)作為文件名
        const date = Date.now().toString()
        // 創(chuàng)立一個(gè) a 標(biāo)簽
        const a = document.createElement('a')
        // 設(shè)置 a 標(biāo)簽的下載文件名
        a.download = `${date}.png`
        // 設(shè)置 a 標(biāo)簽的跳轉(zhuǎn)途徑為 文件流地址
        a.href = URL.createObjectURL(blob)
        // 手動(dòng)觸發(fā) a 標(biāo)簽的點(diǎn)擊事情
        a.click()
        // 移除 a 標(biāo)簽
        a.remove()
    })
}

然后咱們將這個(gè)辦法和保存按鈕進(jìn)行綁定

<button onclick="save()">保存</button>

咱們將剛剛制作的內(nèi)容進(jìn)行保存,點(diǎn)擊保存按鈕,就會(huì)進(jìn)行下載保存

前端完成電子簽名(web、移動(dòng)端)通用
完整代碼

Document
撤銷 保存
各內(nèi)核和瀏覽器支撐情況 Mozilla 程序從 Gecko 1.8 (Firefox 1.5(en-US)) 開端支撐。它首先是由 Apple 引進(jìn)的,用于 OS X Dashboard 和 Safari。Internet Explorer 從 IE9 開端支撐,更舊版本的 IE 中,頁(yè)面能夠經(jīng)過(guò)引進(jìn) Google 的Explorer Canvas項(xiàng)目中的腳本來(lái)獲得支撐。Google Chrome 和 Opera 9+ 也支撐。

小程序中提示
在小程序中咱們假如需呀完成的話,也是同樣的原理哦,只是咱們需求將創(chuàng)立實(shí)例和上下文的Api進(jìn)行修正,由于小程序中是沒(méi)有dom,既然沒(méi)有dom,哪來(lái)的操作dom這個(gè)操作呢。

假如是uni-app則需求運(yùn)用uni.createCanvasContext進(jìn)行上下文創(chuàng)立

假如是原生微信小程序則運(yùn)用wx.createCanvasContext進(jìn)行創(chuàng)立(2.9.0)之后的庫(kù)不支撐

原文鏈接:https://blog.csdn.net/zhangyizuishuai/article/details/131742145

  • 上一篇:沒(méi)有了
  • 下一篇:沒(méi)有了
欄目分類
最近更新