亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

JavaScript實現(xiàn)簽名板功能

 更新時間:2024年10月23日 08:27:22   作者:周尛先森  
簽名板在網(wǎng)頁應用中扮演著重要角色,它們能夠記錄用戶的手寫簽名或者繪圖,下面就跟隨小編一起來學習一下如何使用JavaScript實現(xiàn)簽名板功能

簽名板在網(wǎng)頁應用中扮演著重要角色,它們能夠記錄用戶的手寫簽名或者繪圖,從而提升了用戶體驗。

在接下來的內容中,我將指導你如何利用 JavaScript 來開發(fā)一個功能豐富的簽名板。這個簽名板不僅支持自定義和響應式設計,還具備對觸摸設備的兼容、多樣的筆觸樣式選擇,以及將簽名導出為不同格式圖片的能力。此外,我們還將探索如何整合像 signature_pad 這樣的先進工具來增強簽名板的功能。

開始

讓我們使用純 HTML、CSS 和 JavaScript 創(chuàng)建一個簡單的簽名板。

首先,HTML 文件——在你的工作目錄中創(chuàng)建一個 index.html 文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScript簽名板</title>
    <link rel="stylesheet" href="styles.css" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >
  </head>
  <body>
    <div class="signature-container">
      <canvas id="signature-pad" width="400" height="200"></canvas>
      <button id="clear">清除</button>
    </div>
    <script src="script.js"></script>
  </body>
</html>

我們將采用 <canvas> 標簽來構建簽名板。選擇畫布作為工具是因為它為我們提供了以下功能:

  • 利用 JavaScript 實現(xiàn)自由手寫,這對于獲取簽名是必不可少的。
  • 對畫布的外觀和行為進行個性化定制,包括線條的顏色、粗細以及風格。
  • 兼容多樣的鼠標和觸摸事件,捕捉用戶在繪圖、移動以及提筆或松手時的互動。
  • 利用 toDataURL 方法將簽名以圖像形式導出(如 PNG 或 JPEG),這在保存簽名或將其上傳至服務器時非常有用。

接下來,我們將通過 styles.css 為這個頁面添加一些樣式,以提升其視覺效果。

body {
  display: flex;
  justify - content: center;
  align - items: center;
  height: 100vh;
  background - color: #f0f0f0;
  margin: 0;
}

.signature - container {
  display: flex;
  flex - direction: column;
  align - items: center;
}

canvas {
  border: 1px solid#000;
  background - color: #fff;
}

button {
  margin - top: 10px;
  padding: 5px 10px;
  cursor: pointer;
}

然后向目錄中添加一個 script.js 文件:

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var ctx = canvas.getContext('2d');
  var drawing = false;
  canvas.addEventListener('mousedown',
  function(e) {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX, e.offsetY);
  });
  canvas.addEventListener('mousemove',
  function(e) {
    if (drawing) {
      ctx.lineTo(e.offsetX, e.offsetY);
      ctx.stroke();
    }
  });
  canvas.addEventListener('mouseup',
  function() {
    drawing = false;
  });
  canvas.addEventListener('mouseout',
  function() {
    drawing = false;
  });
  document.getElementById('clear').addEventListener('click',
  function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  });
});

讓我們詳細解釋一下這段代碼的工作原理:

  • 我們首先通過 canvas 變量來綁定到頁面上的 <canvas> 元素。
  • 接著,ctx 變量用于獲取該畫布的 2D 渲染上下文,它包含了繪制圖形所需的各種方法和屬性。
  • 當用戶按下鼠標按鈕時,我們通過一個 mousedown 事件監(jiān)聽器來觸發(fā)繪圖動作。此時,ctx.beginPath() 用于開啟新的繪圖路徑,而 ctx.moveTo(e.offsetX, e.offsetY) 則將畫筆定位到鼠標點擊的準確位置。
  • 用戶移動鼠標時,mousemove 事件監(jiān)聽器會根據(jù)鼠標的當前位置繪制線條。ctx.lineTo(e.offsetX, e.offsetY) 命令畫筆繪制一條直線到新位置,隨后 ctx.stroke() 將這條線實際畫到畫布上。
  • 為了結束繪圖,我們設置了 mouseup 和 mouseout 兩個事件監(jiān)聽器,分別在鼠標按鈕釋放和鼠標光標移出畫布時停止繪圖。此外,當用戶點擊清除按鈕時,ctx.clearRect(0, 0, canvas.width, canvas.height); 用于清除整個畫布,為新的繪圖做準備。

添加觸摸支持

這個示例主要是為鼠標事件設置的,但它也可以很容易地擴展到支持觸摸設備。以下是 JavaScript 處理觸摸事件:

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var ctx = canvas.getContext('2d');
  var drawing = false;

  function startDrawing(e) {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
      ctx.stroke();
    }
  }

  function stopDrawing() {
    drawing = false;
  }

  // 鼠標事件
  canvas.addEventListener('mousedown', startDrawing);
  canvas.addEventListener('mousemove', draw);
  canvas.addEventListener('mouseup', stopDrawing);
  canvas.addEventListener('mouseout', stopDrawing);

  // 觸摸事件
  canvas.addEventListener('touchstart', startDrawing);
  canvas.addEventListener('touchmove', draw);
  canvas.addEventListener('touchend', stopDrawing);
  canvas.addEventListener('touchcancel', stopDrawing);

  document.getElementById('clear').addEventListener('click',
  function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  });
});

對于觸摸事件,使用 e.touches[0].clientXe.touches[0].clientY 來獲取觸摸坐標。為了考慮畫布的位置,使用 canvas.offsetLeftcanvas.offsetTop 進行調整:

自定義

讓我們給簽名板增添一些新功能,比如讓用戶能夠挑選不同的筆觸效果。為此,我們將執(zhí)行以下關鍵步驟:

  • 在 HTML 代碼中嵌入一個 <select> 標簽,它將包含兩個選項:Pen 和 Brush,從而讓用戶可以挑選他們喜歡的筆觸風格。
  • 為這些新增的控件編寫相應的 CSS 樣式,確保它們在頁面上正確地顯示。
  • 為下拉選擇菜單設置一個事件監(jiān)聽器,以便在用戶選擇不同的選項時,動態(tài)地改變筆觸樣式。
  • 根據(jù)用戶所選擇的筆觸樣式,調整 ctx.lineWidth(線寬)和 ctx.lineCap(線帽形狀)的值,以反映不同的視覺效果。

以下是需要添加到 HTML 文件中的代碼片段:

<div class="controls">
  <select id="stroke-style">
    <option value="pen">
      鋼筆
    </option>
    <option value="brush">
      刷子
    </option>
  </select>
  <button id="clear">
    JavaScript簽名板
  </button>
</div>

然后我們更新我們的 CSS:

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    margin: 0;
}

.signature-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

canvas {
    border: 1px solid #000;
    background-color: #fff;
}

.controls {
    margin-top: 10px;
    display: flex;
    gap: 10px;
}

button, select {
    padding: 5px 10px;
    cursor: pointer;
}

最后,更新 script.js

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var ctx = canvas.getContext('2d');
  var drawing = false;
  var strokeStyle = 'pen';

  function startDrawing(e) {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
      ctx.stroke();
    }
  }

  function stopDrawing() {
    drawing = false;
  }

  // 鼠標事件
  canvas.addEventListener('mousedown', startDrawing);
  canvas.addEventListener('mousemove', draw);
  canvas.addEventListener('mouseup', stopDrawing);
  canvas.addEventListener('mouseout', stopDrawing);

  // 觸摸事件
  canvas.addEventListener('touchstart', startDrawing);
  canvas.addEventListener('touchmove', draw);
  canvas.addEventListener('touchend', stopDrawing);
  canvas.addEventListener('touchcancel', stopDrawing);

  document.getElementById('clear').addEventListener('click',
  function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  });

  document.getElementById('stroke-style').addEventListener('change',
  function(e) {
    strokeStyle = e.target.value;
    if (strokeStyle === 'pen') {
      ctx.lineWidth = 2;
      ctx.lineCap = 'round';
    } else if (strokeStyle === 'brush') {
      ctx.lineWidth = 5;
      ctx.lineCap = 'round';
    }
  });

  // 設置初始筆畫樣式
  ctx.lineWidth = 2;
  ctx.lineCap = 'round';
});

處理響應性

當屏幕縮小時,簽名板可能因為缺少響應式設計而無法正常工作。為了改善這一點,我們可以增強應用的響應性,使其在小屏幕設備上也能輕松進行簽名操作。

關鍵在于確保畫布及其容器能夠靈活適應不同的屏幕尺寸。這需要我們根據(jù)瀏覽器窗口的大小來動態(tài)調整畫布的尺寸。

具體來說,我們需要做出以下調整:

  • 為 .signature-container 設置一個靈活的寬度,比如占滿90%的可用空間,并設定一個最大寬度限制,比如600像素。
  • 將畫布元素的寬度設置為 width: 100%,高度設置為 height: auto,以實現(xiàn)響應式效果。

在 JavaScript 代碼中,我們需要執(zhí)行以下操作:

  • 創(chuàng)建一個名為 resizeCanvas 的函數(shù),用以根據(jù)其容器尺寸的變化來調整畫布的大小。
  • 在頁面加載時首先調用 resizeCanvas 函數(shù),并在窗口大小發(fā)生變化時添加一個事件監(jiān)聽器,確保畫布能夠隨著窗口大小的變化而動態(tài)調整尺寸。

按照上述說明,我們需要更新 styles.css 文件,以實現(xiàn)所需的樣式調整。

body {
  display: flex;
  justify - content: center;
  align - items: center;
  height: 100vh;
  background - color: #f0f0f0;
  margin: 0;
}

.signature - container {
  display: flex;
  flex - direction: column;
  align - items: center;
  width: 90 % ;
  max - width: 600px;
}

canvas {
  border: 1px solid#000;
  background - color: #fff;
  width: 100 % ;
  height: auto;
}

.controls {
  margin - top: 10px;
  display: flex;
  gap: 10px;
}

button,
select {
  padding: 5px 10px;
  cursor: pointer;
}

這是在添加之后 script.js 的樣子:

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var ctx = canvas.getContext('2d');
  var drawing = false;
  var strokeStyle = 'pen';

  function resizeCanvas() {
    canvas.width = canvas.offsetWidth;
    canvas.height = canvas.offsetHeight;
    ctx.lineWidth = strokeStyle === 'pen' ? 2 : 5;
    ctx.lineCap = 'round';
  }

  function startDrawing(e) {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
      ctx.stroke();
    }
  }

  function stopDrawing() {
    drawing = false;
  }

  // 鼠標事件
  canvas.addEventListener('mousedown', startDrawing);
  canvas.addEventListener('mousemove', draw);
  canvas.addEventListener('mouseup', stopDrawing);
  canvas.addEventListener('mouseout', stopDrawing);

  // 觸摸事件
  canvas.addEventListener('touchstart', startDrawing);
  canvas.addEventListener('touchmove', draw);
  canvas.addEventListener('touchend', stopDrawing);
  canvas.addEventListener('touchcancel', stopDrawing);

  document.getElementById('clear').addEventListener('click',
  function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  });

  document.getElementById('stroke-style').addEventListener('change',
  function(e) {
    strokeStyle = e.target.value;
    ctx.lineWidth = strokeStyle === 'pen' ? 2 : 5;
  });

  // 初始畫布設置
  resizeCanvas();
  window.addEventListener('resize', resizeCanvas);
});

你可能會觀察到,當改變?yōu)g覽器窗口大小時,畫布上的簽名會消失,這是因為調整畫布尺寸會自動清除其內容。這是 <canvas> 元素的標準行為。不過,我們可以通過一些技巧來避免這個問題。

為了在縮放畫布時保持簽名的完整性,并且能夠正確地對其進行縮放,我們需要先保存畫布上的簽名,然后在調整畫布尺寸后再重新繪制它。我們可以通過 toDataURL 方法來保存畫布上的簽名。

HTMLCanvasElement.toDataURL() 方法能夠根據(jù)你指定的圖片格式,將畫布上的內容轉換成一個數(shù)據(jù) URL。

現(xiàn)在,讓我們來看一下如何保存簽名,以便在窗口大小調整后可以將其恢復。我們需要做的調整如下:

  • 定義一個 signatureData 變量來存儲簽名的當前狀態(tài),以數(shù)據(jù) URL 的形式。
  • 修改 resizeCanvas 函數(shù),使其能在調整畫布大小時,先保存簽名,再調整尺寸,并最終重新繪制簽名。
  • 創(chuàng)建一個 Image 對象來加載保存的簽名,并在調整尺寸后的畫布上將其恢復。
  • 當完成繪畫時,使用 canvas.toDataURL() 方法更新 signatureData 變量,以便存儲當前的畫布內容。
  • 當用戶點擊清除按鈕時,將 signatureData 變量重置為 null,以清除保存的簽名數(shù)據(jù)。

實施了上述更改后,我們的 JavaScript 文件將如下所示:

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var ctx = canvas.getContext('2d');
  var drawing = false;
  var strokeStyle = 'pen';
  var signatureData = null;

  function resizeCanvas() {
    if (signatureData) {
      var img = new Image();
      img.src = signatureData;
      img.onload = function() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        canvas.width = canvas.offsetWidth;
        canvas.height = canvas.offsetHeight;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        setStrokeStyle();
      };
    } else {
      canvas.width = canvas.offsetWidth;
      canvas.height = canvas.offsetHeight;
      setStrokeStyle();
    }
  }

  function setStrokeStyle() {
    if (strokeStyle === 'pen') {
      ctx.lineWidth = 2;
      ctx.lineCap = 'round';
    } else if (strokeStyle === 'brush') {
      ctx.lineWidth = 5;
      ctx.lineCap = 'round';
    }
  }

  function startDrawing(e) {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
      ctx.stroke();
    }
  }

  function stopDrawing() {
    drawing = false;
    signatureData = canvas.toDataURL();
  }

  // 鼠標事件
  canvas.addEventListener('mousedown', startDrawing);
  canvas.addEventListener('mousemove', draw);
  canvas.addEventListener('mouseup', stopDrawing);
  canvas.addEventListener('mouseout', stopDrawing);

  // 觸摸事件
  canvas.addEventListener('touchstart', startDrawing);
  canvas.addEventListener('touchmove', draw);
  canvas.addEventListener('touchend', stopDrawing);
  canvas.addEventListener('touchcancel', stopDrawing);

  document.getElementById('clear').addEventListener('click',
  function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    signatureData = null;
  });

  document.getElementById('stroke-style').addEventListener('change',
  function(e) {
    strokeStyle = e.target.value;
    setStrokeStyle();
  });

  // 初始畫布設置
  resizeCanvas();
  window.addEventListener('resize', resizeCanvas);
});

保存和導出

我們將進一步增強功能,允許用戶將他們的簽名以 PNG 或 JPEG 格式導出,且這些圖片將擁有白色背景。為此,我們將執(zhí)行以下步驟:

  • 在 HTML 代碼中增加兩個按鈕,分別用于將簽名導出為 PNG 和 JPEG 文件。
  • 開發(fā)一個名為 exportCanvas 的函數(shù),該函數(shù)負責將畫布內容(包括白色背景)導出。這一過程涉及到創(chuàng)建一個新畫布,將白色填充為背景色,然后將當前簽名繪制上去,最后將其保存為 PNG 或 JPEG 文件。

以下是經(jīng)過這些更改后的 HTML 代碼示例:

<!DOCTYPE html>
<html lang="en">
  
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
      JavaScript簽名板
    </title>
    <link rel="stylesheet" href="styles.css" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >
  </head>
  
  <body>
    <div class="signature-container">
      <canvas id="signature-pad" width="400" height="200">
      </canvas>
      <div class="controls">
        <button id="clear">
          清除
        </button>
        <button id="export-png">
          導出png格式
        </button>
        <button id="export-jpeg">
          導出jpeg格式
        </button>
      </div>
    </div>
    <script src="script.js">
    </script>
  </body>

</html>

這是在添加之后 JavaScript 文件的樣子:

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var ctx = canvas.getContext('2d');
  var drawing = false;
  var strokeStyle = 'pen';
  var signatureData = null;

  function resizeCanvas() {
    if (signatureData) {
      var img = new Image();
      img.src = signatureData;
      img.onload = function() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        canvas.width = canvas.offsetWidth;
        canvas.height = canvas.offsetHeight;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        setStrokeStyle();
      };
    } else {
      canvas.width = canvas.offsetWidth;
      canvas.height = canvas.offsetHeight;
      setStrokeStyle();
    }
  }

  function setStrokeStyle() {
    if (strokeStyle === 'pen') {
      ctx.lineWidth = 2;
      ctx.lineCap = 'round';
    } else if (strokeStyle === 'brush') {
      ctx.lineWidth = 5;
      ctx.lineCap = 'round';
    }
  }

  function startDrawing(e) {
    drawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineTo(e.offsetX || e.touches[0].clientX - canvas.offsetLeft, e.offsetY || e.touches[0].clientY - canvas.offsetTop);
      ctx.stroke();
    }
  }

  function stopDrawing() {
    drawing = false;
    signatureData = canvas.toDataURL();
  }

  function exportCanvas(format) {
    var exportCanvas = document.createElement('canvas');
    exportCanvas.width = canvas.width;
    exportCanvas.height = canvas.height;
    var exportCtx = exportCanvas.getContext('2d');

    // 用白色填充背景
    exportCtx.fillStyle = '#fff';
    exportCtx.fillRect(0, 0, exportCanvas.width, exportCanvas.height);

    // 繪制簽名
    exportCtx.drawImage(canvas, 0, 0);

    // 導出畫布
    var dataURL = exportCanvas.toDataURL(`image / $ {
      format
    }`);
    var link = document.createElement('a');
    link.href = dataURL;
    link.download = `signature.$ {
      format
    }`;
    link.click();
  }

  // 鼠標事件
  canvas.addEventListener('mousedown', startDrawing);
  canvas.addEventListener('mousemove', draw);
  canvas.addEventListener('mouseup', stopDrawing);
  canvas.addEventListener('mouseout', stopDrawing);

  // 觸摸事件
  canvas.addEventListener('touchstart', startDrawing);
  canvas.addEventListener('touchmove', draw);
  canvas.addEventListener('touchend', stopDrawing);
  canvas.addEventListener('touchcancel', stopDrawing);

  document.getElementById('clear').addEventListener('click',
  function() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    signatureData = null;
  });

  document.getElementById('stroke-style').addEventListener('change',
  function(e) {
    strokeStyle = e.target.value;
    setStrokeStyle();
  });

  document.getElementById('export-png').addEventListener('click',
  function() {
    exportCanvas('png');
  });

  document.getElementById('export-jpeg').addEventListener('click',
  function() {
    exportCanvas('jpeg');
  });

  // 初始畫布設置
  resizeCanvas();
  window.addEventListener('resize', resizeCanvas);
});

添加更多功能

通過引入外部庫,我們可以簡化簽名板中一些復雜功能的實現(xiàn)過程。我們將采用 signature_pad 這個庫,它非常出色,能夠幫助我們輕松地實現(xiàn)之前討論過的眾多功能,并且它還能讓我們生成更加流暢的簽名效果。

首先,我們需要在 HTML 文檔中引入 signature_pad 庫:

<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js"></script>

然后添加必要的按鈕。這是最終 HTML 的樣子:

<!DOCTYPE html>
<html lang="en">
  
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
      JavaScript簽名板
    </title>
    <link rel="stylesheet" href="styles.css" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >
    <script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js">
    </script>
  </head>
  
  <body>
    <div class="signature-container">
      <canvas id="signature-pad" width="600" height="400">
      </canvas>
      <div class="controls">
        <button id="undo">
          撤銷
        </button>
        <button id="redo">
          重做
        </button>
        <button id="clear">
          清除
        </button>
        <button id="save-png">
          導出png格式
        </button>
        <button id="save-jpeg">
          導出jpeg格式
        </button>
      </div>
    </div>
    <script src="script.js">
    </script>
  </body>

</html>

更新樣式:

body {
  display: flex;
  justify - content: center;
  align - items: center;
  height: 100vh;
  background - color: #f0f0f0;
  margin: 0;
}

.signature - container {
  display: flex;
  flex - direction: column;
  align - items: center;
  width: 90 % ;
  max - width: 600px;
}

canvas {
  border: 1px solid#000;
  background - color: #fff;
  width: 100 % ;
  height: auto;
}

.controls {
  margin - top: 10px;
  display: flex;
  gap: 10px;
  flex - wrap: wrap;
}

button {
  padding: 5px 10px;
  cursor: pointer;
}

為了進一步完善我們的簽名板功能,script.js 腳本需要進行以下更新:

  • 實現(xiàn)兩個棧,undoStack 和 redoStack,分別用來追蹤撤銷和重做的歷史狀態(tài)。
  • 創(chuàng)建一個 saveState 函數(shù),該函數(shù)負責將簽名板的當前狀態(tài)存儲到撤銷棧中。
  • 定義 undo 和 redo 函數(shù),分別用于執(zhí)行撤銷和重做的操作。

經(jīng)過這些修改,script.js 腳本將具備完整的撤銷和重做功能。以下是更新后的 script.js 腳本:

document.addEventListener('DOMContentLoaded',
function() {
  var canvas = document.getElementById('signature-pad');
  var signaturePad = new SignaturePad(canvas);
  var undoStack = [];
  var redoStack = [];
  function saveState() {
    undoStack.push(deepCopy(signaturePad.toData()));
    redoStack = [];
  }
  function undo() {
    if (undoStack.length > 0) {
      redoStack.push(deepCopy(signaturePad.toData()));
      undoStack.pop();
      signaturePad.clear();
      if (undoStack.length) {
        var lastStroke = undoStack[undoStack.length - 1];
        signaturePad.fromData(lastStroke, {
          clear: false
        });
      }
    }
  }
  function redo() {
    if (redoStack.length > 0) {
      undoStack.push(deepCopy(signaturePad.toData()));
      var nextState = redoStack.pop();
      signaturePad.clear();
      if (nextState.length) {
        signaturePad.fromData(nextState);
      }
    }
  }
  document.getElementById('undo').addEventListener('click', undo);
  document.getElementById('redo').addEventListener('click', redo);
  document.getElementById('clear').addEventListener('click',
  function() {
    signaturePad.clear();
    undoStack = [];
    redoStack = [];
  });
  document.getElementById('save-png').addEventListener('click',
  function() {
    if (!signaturePad.isEmpty()) {
      var dataURL = signaturePad.toDataURL('image/png');
      var link = document.createElement('a');
      link.href = dataURL;
      link.download = 'signature.png';
      link.click();
    }
  });
  document.getElementById('save-jpeg').addEventListener('click',
  function() {
    if (!signaturePad.isEmpty()) {
      var dataURL = signaturePad.toDataURL('image/jpeg');
      var link = document.createElement('a');
      link.href = dataURL;
      link.download = 'signature.jpeg';
      link.click();
    }
  });
  // 繪圖結束時保存狀態(tài)
  signaturePad.addEventListener("endStroke", () = >{
    console.log("Signature end");
    saveState();
  });
  // 初始畫布設置
  function resizeCanvas() {
    var ratio = Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext('2d').scale(ratio, ratio);
    signaturePad.clear(); // 否則 isEmpty() 可能會返回錯誤值
    if (undoStack.length > 0) {
      signaturePad.fromData(undoStack[undoStack.length - 1]);
    }
  }
  function deepCopy(data) {
    return JSON.parse(JSON.stringify(data));
  }
  window.addEventListener('resize', resizeCanvas);
  resizeCanvas();
});

應用場景介紹:JavaScript 簽名板

掌握上述代碼能夠讓我們應對多種實際應用場景。

電子簽名在網(wǎng)頁表單中的應用

通過在網(wǎng)頁表單中集成簽名板,用戶可以輕松地電子簽名文檔,這在處理合同、協(xié)議和同意書時尤為重要。在法律、房地產(chǎn)、醫(yī)療和金融等行業(yè)內,電子簽名的收集成為工作流程中不可或缺的一環(huán),有效減少了紙質文件的使用。

在線繪圖工具的集成

開發(fā)者可以將簽名板整合到需要用戶進行繪圖或注釋的在線應用中。無論是協(xié)作白板、設計軟件還是交互式反饋環(huán)節(jié),簽名板都能發(fā)揮重要作用。例如,在在線教育平臺上,學生可以利用簽名板在直播課程中繪制圖表或解答數(shù)學題目,教師也能即時給予反饋。

網(wǎng)絡文檔和圖像編輯器中的注釋功能

簽名板可作為網(wǎng)絡文檔和圖像編輯器中的注釋工具,讓用戶能夠直接在文檔或圖像上添加手寫注釋、評論或草圖。

訪客登記管理

在訪客登記管理中,簽名板可用于記錄訪客的數(shù)字化簽到和簽出信息,這在企業(yè)管理和活動策劃中非常實用。

總結

在本篇文章中,我們探索了如何使用純 JavaScript 來創(chuàng)建一個功能豐富的簽名板,包括觸摸支持、筆觸樣式選擇、響應式設計以及導出功能。我們學習了如何利用 HTML 的 <canvas> 元素來捕捉用戶的手寫簽名,并通過 JavaScript 為簽名板添加了撤銷、重做等高級功能。此外,我們還通過引入 signature_pad 庫進一步簡化了開發(fā)過程,使得實現(xiàn)平滑的簽名體驗變得更加容易。

通過這些技術,我們不僅能夠創(chuàng)建一個基本的簽名板,還能夠為其添加各種實用的功能,使其適應不同的應用場景。無論是在網(wǎng)頁表單中收集電子簽名,還是在在線教育平臺中作為繪圖工具,或是作為網(wǎng)絡文檔編輯器中的注釋工具,JavaScript 簽名板都能提供出色的用戶體驗。

此外,我們還討論了如何將簽名數(shù)據(jù)導出為不同格式的圖片,這對于保存簽名或將其發(fā)送到服務器進行進一步處理非常有用。例如,簽名驗證功能可以提高在線交易的安全性,確保用戶的身份得到確認。

總的來說,JavaScript 簽名板的靈活性和可定制性使其成為現(xiàn)代網(wǎng)絡應用的理想選擇。隨著技術的不斷進步,我們可以預見,JavaScript 簽名板將在未來的網(wǎng)絡應用中扮演越來越重要的角色,為用戶提供更加豐富和便捷的手寫簽名體驗。通過本文的指導,開發(fā)者可以輕松地在自己的項目中實現(xiàn)這些功能,無論是簡單的簽名收集還是復雜的交互式繪圖和注釋,都能輕松應對。這種技術的應用不僅提高了工作效率,也為用戶帶來了更加直觀和個性化的交互方式。

以上就是JavaScript實現(xiàn)簽名板功能的詳細內容,更多關于JavaScript簽名板的資料請關注腳本之家其它相關文章!

相關文章

  • 使用webpack和rollup打包組件庫的方法

    使用webpack和rollup打包組件庫的方法

    這篇文章主要介紹了使用webpack和rollup打包組件庫的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • 淺談JavaScript 聲明提升

    淺談JavaScript 聲明提升

    這篇文章主要介紹了JavaScript 聲明提升的相關資料,幫助大家更好的理解和學習JavaScript,感興趣的朋友可以了解下
    2020-09-09
  • 20個常見的JavaScript數(shù)組操作總結

    20個常見的JavaScript數(shù)組操作總結

    JavaScript中的Array對象與其他編程語言中的數(shù)組一樣,是一組數(shù)據(jù)的集合。在JavaScript中,數(shù)組里面的數(shù)據(jù)可以是不同類型的,并具有用于執(zhí)行數(shù)組常見操作的方法,本文整理了一些常用的,需要的可以參考一下
    2022-09-09
  • 基于vue實現(xiàn)可搜索下拉框定制組件

    基于vue實現(xiàn)可搜索下拉框定制組件

    這篇文章主要為大家詳細介紹了基于vue實現(xiàn)可搜索下拉框定制組件,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • 原生JS實現(xiàn)音樂播放器

    原生JS實現(xiàn)音樂播放器

    這篇文章主要為大家詳細介紹了原生JS音樂播放器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • JavaScript 原型繼承之構造函數(shù)繼承

    JavaScript 原型繼承之構造函數(shù)繼承

    JavaScript 是基于原型的面向對象語言。也就是說,每個實例對象都具有一個原型。對象從該原型中繼承屬性和方法。這一篇將具體說說構造函數(shù)的繼承。
    2011-08-08
  • 基于Bootstrap模態(tài)對話框只加載一次 remote 數(shù)據(jù)的解決方法

    基于Bootstrap模態(tài)對話框只加載一次 remote 數(shù)據(jù)的解決方法

    下面小編就為大家?guī)硪黄贐ootstrap模態(tài)對話框只加載一次 remote 數(shù)據(jù)的解決方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • 用Js實現(xiàn)的動態(tài)增加表格示例自己寫的

    用Js實現(xiàn)的動態(tài)增加表格示例自己寫的

    動態(tài)增加表格的方法有很多,但大多說實現(xiàn)起來比較繁瑣,本文的這個示例是作者自己手寫的,經(jīng)測試效果還不錯,但唯獨不兼容FF,感興趣的朋友可以參考下
    2013-10-10
  • web前端開發(fā)upload上傳頭像js示例代碼

    web前端開發(fā)upload上傳頭像js示例代碼

    這篇文章主要為大家詳細介紹了web前端開發(fā)upload上傳頭像js示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • 微信JSSDK調用微信掃一掃功能的方法

    微信JSSDK調用微信掃一掃功能的方法

    這篇文章主要為大家詳細介紹了微信JSSDK調用微信掃一掃功能的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07

最新評論