欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

前端實現(xiàn)電子簽名(web、移動端)通用的實戰(zhàn)過程

 更新時間:2022年12月12日 10:11:02   作者:桃小瑞  
電子簽名通俗來說就是通過技術手段實現(xiàn)在電子文檔上加載電子形式的簽名,下面這篇文章主要給大家介紹了關于前端實現(xiàn)電子簽名(web、移動端)通用的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下

前言

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

舉個常用的例子,大家都用過釘釘,釘釘上面就有電子簽名,相信大家這肯定是知道的。

那作為前端的我們?nèi)绾螌崿F(xiàn)電子簽名呢?其實在html5中已經(jīng)出現(xiàn)了一個重要級別的輔助標簽,是啥呢?那就是canvas。

什么是canvas

Canvas(畫布)是在HTML5中新增的標簽用于在網(wǎng)頁實時生成圖像,并且可以操作圖像內(nèi)容,基本上它是一個可以用JavaScript操作的位圖(bitmap)Canvas 對象表示一個 HTML 畫布元素 -。它沒有自己的行為,但是定義了一個 API 支持腳本化客戶端繪圖操作。

大白話就是canvas是一個可以在上面通過javaScript畫圖的標簽,通過其提供的context(上下文)Api進行繪制,在這個過程中canvas充當畫布的角色。

<canvas></canvas>

如何使用

canvas給我們提供了很多的Api,供我們使用,我們只需要在body標簽中創(chuàng)建一個canvas標簽,在script標簽中拿到canvas這個標簽的節(jié)點,并創(chuàng)建context(上下文)就可以使用了。

...
<body>
    <canvas></canvas>
</body>
<script>
    // 獲取canvas 實例
    const canvas = document.querySelector('canvas')
    canvas.getContext('2d')
</script>
...

步入正題。

實現(xiàn)電子簽名

知道幾何的朋友都很清楚,線有點繪成,面由線繪成。

多點成線,多線成面。

所以我們實際只需要拿到當前觸摸的坐標點,進行成線處理就可以了。

在body中添加canvas標簽

在這里我們不僅需要在在body中添加canvas標簽,我們還需要添加兩個按鈕,分別是取消保存(后面我們會用到)。

<body>
    <canvas></canvas>
    <div>
        <button>取消</button>
        <button>保存</button>
    </div>
</body>

添加文件

我這里全程使用js進行樣式設置及添加。

// 配置內(nèi)容
    const config = {
        width: 400, // 寬度
        height: 200, // 高度
        lineWidth: 5, // 線寬
        strokeStyle: 'red', // 線條顏色
        lineCap: 'round', // 設置線條兩端圓角
        lineJoin: 'round', // 線條交匯處圓角
    }

獲取canvas實例

這里我們使用querySelector獲取canvas的dom實例,并設置樣式和創(chuàng)建上下文。

    // 獲取canvas 實例
    const canvas = document.querySelector('canvas')
    // 設置寬高
    canvas.width = config.width
    canvas.height = config.height
    // 設置一個邊框,方便我們查看及使用
    canvas.style.border = '1px solid #000'
    // 創(chuàng)建上下文
    const ctx = canvas.getContext('2d')

基礎設置

我們將canvas的填充色為透明,并繪制填充一個矩形,作為我們的畫布,如果不設置這個填充背景色,在我們初識渲染的時候是一個黑色背景,這也是它的一個默認色。

    // 設置填充背景色
    ctx.fillStyle = 'transparent'
    // 繪制填充矩形
    ctx.fillRect(
        0, // x 軸起始繪制位置
        0, // y 軸起始繪制位置
        config.width, // 寬度
        config.height // 高度
    );

上次繪制路徑保存

這里我們需要聲明一個對象,用來記錄我們上一次繪制的路徑結束坐標點及偏移量。

  • 保存上次坐標點這個我不用說大家都懂;
  • 為啥需要保存偏移量呢,因為鼠標和畫布上的距離是存在一定的偏移距離,在我們繪制的過程中需要減去這個偏移量,才是我們實際的繪制坐標。
  • 但我發(fā)現(xiàn)chrome中不需要減去這個偏移量,拿到的就是實際的坐標,之前在微信小程序中使用就需要減去偏移量,需要在小程序中使用的朋友需要注意這一點哦。
    // 保存上次繪制的 坐標及偏移量
    const client = {
        offsetX: 0, // 偏移量
        offsetY: 0,
        endX: 0, // 坐標
        endY: 0
    }

設備兼容

我們需要它不僅可以在web端使用,還需要在移動端使用,我們需要給它做設備兼容處理。我們通過調(diào)用navigator.userAgent獲取當前設備信息,進行正則匹配判斷。

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

初始化

這里我們在監(jiān)聽鼠標按下(mousedown)(web端)/觸摸開始(touchstart)的時候進行初始化,事件監(jiān)聽采用addEventListener。

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

三元判斷說明: 這里當mobileStatustrue時則表示為移動端,反之則為web端,后續(xù)使用到的三元依舊是這個意思。

聲明初始化方法

我們添加一個init方法作為監(jiān)聽鼠標按下/觸摸開始的回調(diào)方法。

這里我們需要獲取到當前鼠標按下/觸摸開始的偏移量和坐標,進行起始點繪制。

Tips:web端可以直接通過event中取到,而移動端則需要在event.changedTouches[0]中取到。

這里我們在初始化后再監(jiān)聽鼠標的移動。

    // 初始化
    const init = event => {
        // 獲取偏移量及坐標
        const { offsetX, offsetY, pageX, pageY } = mobileStatus ? event.changedTouches[0] : event 

        // 修改上次的偏移量及坐標
        client.offsetX = offsetX
        client.offsetY = offsetY
        client.endX = pageX
        client.endY = pageY

        // 清除以上一次 beginPath 之后的所有路徑,進行繪制
        ctx.beginPath()

        // 根據(jù)配置文件設置進行相應配置
        ctx.lineWidth = config.lineWidth
        ctx.strokeStyle = config.strokeStyle
        ctx.lineCap = config.lineCap
        ctx.lineJoin = config.lineJoin

        // 設置畫線起始點位
        ctx.moveTo(client.endX, client.endY)

        // 監(jiān)聽 鼠標移動或手勢移動
        window.addEventListener(mobileStatus ? "touchmove" : "mousemove", draw)
    }

繪制

這里我們添加繪制draw方法,作為監(jiān)聽鼠標移動/觸摸移動的回調(diào)方法。

    // 繪制
    const draw = event => {
        // 獲取當前坐標點位
        const { pageX, pageY } = mobileStatus ? event.changedTouches[0] : event
        // 修改最后一次繪制的坐標點
        client.endX = pageX
        client.endY = pageY

        // 根據(jù)坐標點位移動添加線條
        ctx.lineTo(pageX , pageY )

        // 繪制
        ctx.stroke()
    }

結束繪制

添加了監(jiān)聽鼠標移動/觸摸移動我們一定要記得取消監(jiān)聽并結束繪制,不然的話它會一直監(jiān)聽并繪制的。

這里我們創(chuàng)建一個cloaseDraw方法作為鼠標彈起/結束觸摸的回調(diào)方法來結束繪制并移除鼠標移動/觸摸移動的監(jiān)聽。

canvas結束繪制則需要調(diào)用closePath()讓其結束繪制

    // 結束繪制
    const cloaseDraw = () => {
        // 結束繪制
        ctx.closePath()
        // 移除鼠標移動或手勢移動監(jiān)聽器
        window.removeEventListener("mousemove", draw)
    }

添加結束回調(diào)監(jiān)聽器

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

ok,現(xiàn)在我們的電子簽名功能還差一丟丟可以實現(xiàn)完了,現(xiàn)在已經(jīng)可以正常的簽名了。

我們來看一下效果:

取消功能/清空畫布

我們在剛開始創(chuàng)建的那兩個按鈕開始排上用場了。

這里我們創(chuàng)建一個cancel的方法作為取消并清空畫布使用

    // 取消-清空畫布
    const cancel = () => {
        // 清空當前畫布上的所有繪制內(nèi)容
        ctx.clearRect(0, 0, config.width, config.height)
    }

然后我們將這個方法和取消按鈕進行綁定

     <button onclick="cancel()">取消</button>

保存功能

這里我們創(chuàng)建一個save的方法作為保存畫布上的內(nèi)容使用。

將畫布上的內(nèi)容保存為圖片/文件的方法有很多,比較常見的是blobtoDataURL這兩種方案,但toDataURL這哥們沒blob強,適配也不咋滴。所以我們這里采用a標簽 ? blob方案實現(xiàn)圖片的保存下載。

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

然后我們將這個方法和保存按鈕進行綁定

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

我們將剛剛繪制的內(nèi)容進行保存,點擊保存按鈕,就會進行下載保存

完整代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
    </style>
</head>
<body>
    <canvas></canvas>
    <div>
        <button onclick="cancel()">取消</button>
        <button onclick="save()">保存</button>
    </div>
</body>
<script>
    // 配置內(nèi)容
    const config = {
        width: 400, // 寬度
        height: 200, // 高度
        lineWidth: 5, // 線寬
        strokeStyle: 'red', // 線條顏色
        lineCap: 'round', // 設置線條兩端圓角
        lineJoin: 'round', // 線條交匯處圓角
    }

    // 獲取canvas 實例
    const canvas = document.querySelector('canvas')
    // 設置寬高
    canvas.width = config.width
    canvas.height = config.height
    // 設置一個邊框
    canvas.style.border = '1px solid #000'
    // 創(chuàng)建上下文
    const ctx = canvas.getContext('2d')

    // 設置填充背景色
    ctx.fillStyle = 'transparent'
    // 繪制填充矩形
    ctx.fillRect(
        0, // x 軸起始繪制位置
        0, // y 軸起始繪制位置
        config.width, // 寬度
        config.height // 高度
    );

    // 保存上次繪制的 坐標及偏移量
    const client = {
        offsetX: 0, // 偏移量
        offsetY: 0,
        endX: 0, // 坐標
        endY: 0
    }

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

    // 初始化
    const init = event => {
        // 獲取偏移量及坐標
        const { offsetX, offsetY, pageX, pageY } = mobileStatus ? event.changedTouches[0] : event 

        // 修改上次的偏移量及坐標
        client.offsetX = offsetX
        client.offsetY = offsetY
        client.endX = pageX
        client.endY = pageY

        // 清除以上一次 beginPath 之后的所有路徑,進行繪制
        ctx.beginPath()
        // 根據(jù)配置文件設置相應配置
        ctx.lineWidth = config.lineWidth
        ctx.strokeStyle = config.strokeStyle
        ctx.lineCap = config.lineCap
        ctx.lineJoin = config.lineJoin
        // 設置畫線起始點位
        ctx.moveTo(client.endX, client.endY)
        // 監(jiān)聽 鼠標移動或手勢移動
        window.addEventListener(mobileStatus ? "touchmove" : "mousemove", draw)
    }
    // 繪制
    const draw = event => {
        // 獲取當前坐標點位
        const { pageX, pageY } = mobileStatus ? event.changedTouches[0] : event
        // 修改最后一次繪制的坐標點
        client.endX = pageX
        client.endY = pageY

        // 根據(jù)坐標點位移動添加線條
        ctx.lineTo(pageX , pageY )

        // 繪制
        ctx.stroke()
    }
    // 結束繪制
    const cloaseDraw = () => {
        // 結束繪制
        ctx.closePath()
        // 移除鼠標移動或手勢移動監(jiān)聽器
        window.removeEventListener("mousemove", draw)
    }
    // 創(chuàng)建鼠標/手勢按下監(jiān)聽器
    window.addEventListener(mobileStatus ? "touchstart" : "mousedown", init)
    // 創(chuàng)建鼠標/手勢 彈起/離開 監(jiān)聽器
    window.addEventListener(mobileStatus ? "touchend" :"mouseup", cloaseDraw)
    
    // 取消-清空畫布
    const cancel = () => {
        // 清空當前畫布上的所有繪制內(nèi)容
        ctx.clearRect(0, 0, config.width, config.height)
    }
    // 保存-將畫布內(nèi)容保存為圖片
    const save = () => {
        // 將canvas上的內(nèi)容轉成blob流
        canvas.toBlob(blob => {
            // 獲取當前時間并轉成字符串,用來當做文件名
            const date = Date.now().toString()
            // 創(chuàng)建一個 a 標簽
            const a = document.createElement('a')
            // 設置 a 標簽的下載文件名
            a.download = `${date}.png`
            // 設置 a 標簽的跳轉路徑為 文件流地址
            a.href = URL.createObjectURL(blob)
            // 手動觸發(fā) a 標簽的點擊事件
            a.click()
            // 移除 a 標簽
            a.remove()
        })
    }
</script>
</html>

各內(nèi)核和瀏覽器支持情況

Mozilla 程序從 Gecko 1.8 (Firefox 1.5 (en-US)) 開始支持 <canvas>。它首先是由 Apple 引入的,用于 OS X Dashboard 和 Safari。Internet Explorer 從 IE9 開始支持<canvas> ,更舊版本的 IE 中,頁面可以通過引入 Google 的 Explorer Canvas 項目中的腳本來獲得<canvas>支持。Google Chrome 和 Opera 9+ 也支持 <canvas>。

小程序中提示

在小程序中我們?nèi)绻柩綄崿F(xiàn)的話,也是同樣的原理哦,只是我們需要將創(chuàng)建實例和上下文的Api進行修改,因為小程序中是沒有dom,既然沒有dom,哪來的操作dom這個操作呢。

總結

到此這篇關于前端實現(xiàn)電子簽名(web、移動端)通用的文章就介紹到這了,更多相關前端實現(xiàn)通用電子簽名內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 三劍客:offset、client和scroll還傻傻分不清?

    三劍客:offset、client和scroll還傻傻分不清?

    這篇文章主要給大家介紹了三劍客:offset,client和scroll的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • JavaScript之instanceof方法手寫示例詳解

    JavaScript之instanceof方法手寫示例詳解

    這篇文章主要為大家介紹了JavaScript之instanceof方法手寫示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • JavaScript實現(xiàn)購物車圖片局部放大預覽效果

    JavaScript實現(xiàn)購物車圖片局部放大預覽效果

    這篇文章主要為大家詳細介紹了JavaScript如何通過canvas簡單實現(xiàn)購物車圖片放大預覽效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-03-03
  • showModalDialog在谷歌瀏覽器下會返回Null的解決方法

    showModalDialog在谷歌瀏覽器下會返回Null的解決方法

    showModalDialog的返回值在IE、火狐下面都能夠獲取返回值,但是在谷歌瀏覽器下面會返回Null,下面有個不錯的解決方法,感興趣的朋友可以參考下
    2013-11-11
  • JavaScript的內(nèi)置對象Math和字符串詳解

    JavaScript的內(nèi)置對象Math和字符串詳解

    這篇文章主要為大家介紹了JavaScript的內(nèi)置對象Math和字符串,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • 基于JS實現(xiàn)數(shù)字動態(tài)變化顯示效果附源碼

    基于JS實現(xiàn)數(shù)字動態(tài)變化顯示效果附源碼

    我們經(jīng)常看到液晶電子表樣式,數(shù)字動態(tài)顯示,動態(tài)變化的在指定元素內(nèi)顯示數(shù)字。怎么實現(xiàn)效果呢?下面小編給大家?guī)砹嘶贘S實現(xiàn)數(shù)字動態(tài)變化顯示效果 ,感興趣的朋友一起看看吧
    2019-07-07
  • Javascript頁面跳轉常見實現(xiàn)方式匯總

    Javascript頁面跳轉常見實現(xiàn)方式匯總

    這篇文章主要介紹了Javascript頁面跳轉常見實現(xiàn)方式,結合實例匯總分析了JavaScript常用的七種頁面跳轉實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • cnblogs 代碼高亮顯示后的代碼復制問題解決實現(xiàn)代碼

    cnblogs 代碼高亮顯示后的代碼復制問題解決實現(xiàn)代碼

    cnblogs是比較有名的技術博客基地,很多技術達人都在里面發(fā)布技術文章, 不過由于代碼不利于復制,因為頁面里面有pre標簽等問題
    2011-12-12
  • JS訪問對象兩種方式區(qū)別解析

    JS訪問對象兩種方式區(qū)別解析

    這篇文章主要介紹了JS訪問對象兩種方式區(qū)別解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-08-08
  • JavaScript 跨域之POST實現(xiàn)方法

    JavaScript 跨域之POST實現(xiàn)方法

    本篇文章主要介紹了JavaScript 跨域之POST實現(xiàn)方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-05-05

最新評論