成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

簽字板很難嗎?純 JS 實現一個!

開發 前端
我說:“這種功能很簡單呀,目前市面上有很多開源的庫,比如:signature_pad 就可以直接引入實現”。但是,該同學說自己公司的項目比較特殊,盡量不要使用 第三方的庫,所以想要自己實現,那怎么辦呢?

Hello,大家好,我是 Sunday。

前段時間有位同學問我:“公司項目中需要增加一個簽字板的功能”,問我如何進行實現。

我說:“這種功能很簡單呀,目前市面上有很多開源的庫,比如:signature_pad 就可以直接引入實現”。

但是,該同學說自己公司的項目比較特殊,盡量不要使用 第三方的庫,所以想要自己實現,那怎么辦呢?

沒辦法!只能幫他實現一個了.

簽字板實現邏輯

簽字板的功能實現其實并不復雜,核心是 基于 canvas 的 2d 繪制能力,監聽用戶 鼠標 或者 手指 的移動行為,完成對應的 線繪制。

所以,想要實現簽字板那么必須要有一個 canvas,先看 html 的實現部分:

html

<body>
    <!-- 畫板 -->
    <canvas id="signature-pad" width="400" height="200"></canvas>
    <!-- 控制器 -->
    <div class="controls">
        <select id="stroke-style">
            <option value="pen">鋼筆</option>
            <option value="brush">毛筆</option>
        </select>
        <button id="clear">清空</button>
    </div>
    <script src="script.js"></script>
</body>

我們可以基于以上代碼完成 HTML 布局,核心是兩個內容:

  1. canvas 畫布:它是完成簽字板的關鍵
  2. controls 控制器:通過它可以完成 畫筆切換 以及 清空畫布 的功能

css

css 相對比較簡單,大家可以根據自己的需求進行調整就可以了,以下是 css 大家可以作為參考:

* {
  margin: 0;
  padding: 0;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  height: 100vh;
  width: 100vw;
  background-color: #f0f0f0;
  overflow: hidden;
}

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

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

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

js

js 部分是整個簽字板的核心,我們需要在這里考慮較多的內容,比如:

  1. 為了繪制更加平滑,我們需要使用 ctx.quadraticCurveTo 方法完成平滑過渡
  2. 為了解決移動端手指滑動滾動條的問題,我們需要在 move 事件中通過 e.preventDefault() 取消默認行為
  3. 為了完成畫筆切換,我們需要監聽 select 的 change 事件,從而修改 ctx.lineWidth 畫筆

最終得到的 js 代碼如下所示(代碼中提供的詳細的注釋):

document.addEventListener('DOMContentLoaded', function () {
 // 獲取 canvas 元素和其 2D 上下文
 var canvas = document.getElementById('signature-pad')
 var ctx = canvas.getContext('2d')
 var drawing = false // 標志是否正在繪制
 var lastX = 0,
  lastY = 0 // 保存上一個點的坐標
 var strokeStyle = 'pen' // 初始筆畫樣式

 // 開始繪制的函數
 function startDrawing(e) {
  e.preventDefault() // 阻止默認行為,避免頁面滾動
  drawing = true // 設置為正在繪制
  ctx.beginPath() // 開始新路徑

  // 記錄初始點的位置
  const { offsetX, offsetY } = getEventPosition(e)
  lastX = offsetX
  lastY = offsetY
  ctx.moveTo(offsetX, offsetY) // 移動畫筆到初始位置
 }

 // 繪制過程中的函數
 function draw(e) {
  e.preventDefault() // 阻止默認行為,避免頁面滾動
  if (!drawing) return // 如果不是在繪制,直接返回

  // 獲取當前觸點位置
  const { offsetX, offsetY } = getEventPosition(e)

  // 使用貝塞爾曲線進行平滑過渡繪制
  ctx.quadraticCurveTo(
   lastX,
   lastY,
   (lastX + offsetX) / 2,
   (lastY + offsetY) / 2
  )
  ctx.stroke() // 實際繪制路徑

  // 更新上一個點的位置
  lastX = offsetX
  lastY = offsetY
 }

 // 停止繪制的函數
 function stopDrawing(e) {
  e.preventDefault() // 阻止默認行為
  drawing = false // 結束繪制狀態
 }

 // 獲取事件中觸點的相對位置
 function getEventPosition(e) {
  // 鼠標事件或者觸摸事件中的坐標
  const offsetX = e.offsetX || e.touches[0].clientX - canvas.offsetLeft
  const offsetY = e.offsetY || e.touches[0].clientY - canvas.offsetTop
  return { offsetX, offsetY }
 }

 // 鼠標事件綁定
 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 // 獲取選中的筆畫樣式
   updateStrokeStyle() // 更新樣式
  })

 // 根據 strokeStyle 更新筆畫樣式
 function updateStrokeStyle() {
  if (strokeStyle === 'pen') {
   ctx.lineWidth = 2 // 細線條
   ctx.lineCap = 'round' // 線條末端圓角
  } else if (strokeStyle === 'brush') {
   ctx.lineWidth = 5 // 粗線條
   ctx.lineCap = 'round' // 線條末端圓角
  }
 }

 // 初始化默認的筆畫樣式
 updateStrokeStyle()
})

以上就是 純JS實現簽字板的完整代碼,大家可以直接組合代碼進行使用,最終展示的結果如下:

圖片 圖片

責任編輯:武曉燕 來源: 程序員Sunday
相關推薦

2022-07-13 15:31:29

手繪板canvas鴻蒙

2023-04-17 09:08:27

CSS計時器

2024-03-13 08:21:53

冒泡排序動畫

2011-11-03 09:13:27

JavaScript

2011-10-25 09:28:30

Node.js

2020-08-07 10:40:56

Node.jsexpress前端

2025-03-26 01:35:00

tabs開發組件

2024-09-02 00:03:00

tabs組件CSS

2018-01-29 21:56:28

Bug程序程序員

2017-03-28 21:03:35

代碼React.js

2022-04-06 18:29:58

CSSJS輸入框

2009-07-02 10:02:40

JSP程序

2022-04-14 20:43:24

JavaScript原型鏈

2020-10-16 15:06:59

開發技術方案

2021-05-13 20:20:40

Java架構代碼

2020-04-08 08:35:20

JavaScript模塊函數

2012-07-10 16:09:54

App盈利

2013-03-18 10:31:22

JS異常

2022-03-04 14:17:08

JS工具庫錄音

2023-12-27 14:05:00

關系型數據庫產品
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91久久久久 | 精品视频在线观看 | 欧美成人一区二区 | 可以看黄的视频 | 视频一区二区三区在线观看 | 久久久久九九九九 | 台湾佬久久 | 久久狼人天堂 | 国产免费国产 | 亚洲自拍偷拍免费视频 | 一级片免费视频 | 国产日韩欧美一区 | 亚洲视频免费 | 国产不卡视频 | 欧美一区二区三区免费在线观看 | 欧美午夜一区二区三区免费大片 | 婷婷综合色 | 中文字幕精品一区二区三区精品 | 国产免费一区二区 | 午夜电影合集 | 精品国产一区二区三区久久 | 99re在线视频观看 | 97精品超碰一区二区三区 | 日韩一级| 亚洲欧美视频一区 | 人人九九精 | 久草99| 欧美a在线 | 一区二区三区av夏目彩春 | 欧美成人一级 | 91在线观看网址 | 欧美一区二区三区在线观看视频 | 香蕉视频一区二区 | 91精品久久久久久久久久入口 | 超碰97人人人人人蜜桃 | 亚洲网站在线观看 | 粉嫩国产精品一区二区在线观看 | 人人99| 国产欧美性成人精品午夜 | 天天拍天天操 | 最新高清无码专区 |