国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

雖然寫的字有點丑,但這個手搓的簽字板代碼還是很酷的......

開發(fā) 前端
簽字板的功能實現(xiàn)其實并不復(fù)雜,核心是?基于 canvas 的?2d?繪制能力,監(jiān)聽用戶?鼠標(biāo)?或者?手指?的移動行為,完成對應(yīng)的?線繪制。

Hello,大家好,我是 Sunday。

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

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

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

沒辦法!只能幫他實現(xiàn)一個了.

簽字板實現(xiàn)邏輯

簽字板的功能實現(xiàn)其實并不復(fù)雜,核心是 基于 canvas 的 2d 繪制能力,監(jiān)聽用戶 鼠標(biāo) 或者 手指 的移動行為,完成對應(yīng)的 線繪制

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

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 布局,核心是兩個內(nèi)容:

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

css

css 相對比較簡單,大家可以根據(jù)自己的需求進(jìn)行調(diào)整就可以了,以下是 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 部分是整個簽字板的核心,我們需要在這里考慮較多的內(nèi)容,比如:

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

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

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

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

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

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

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

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

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

 // 停止繪制的函數(shù)
 function stopDrawing(e) {
  e.preventDefault() // 阻止默認(rèn)行為
  drawing = false // 結(jié)束繪制狀態(tài)
 }

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

 // 鼠標(biāo)事件綁定
 canvas.addEventListener('mousedown', startDrawing) // 鼠標(biāo)按下開始繪制
 canvas.addEventListener('mousemove', draw) // 鼠標(biāo)移動時繪制
 canvas.addEventListener('mouseup', stopDrawing) // 鼠標(biāo)抬起停止繪制
 canvas.addEventListener('mouseout', stopDrawing) // 鼠標(biāo)移出畫布停止繪制

 // 觸摸事件綁定
 canvas.addEventListener('touchstart', startDrawing) // 觸摸開始繪制
 canvas.addEventListener('touchmove', draw) // 觸摸移動時繪制
 canvas.addEventListener('touchend', stopDrawing) // 觸摸結(jié)束時停止繪制
 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() // 更新樣式
  })

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

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

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

圖片圖片

責(zé)任編輯:武曉燕 來源: 程序員Sunday
相關(guān)推薦

2022-01-31 13:48:52

低代碼開發(fā)軟件

2023-04-10 15:37:18

AI代碼

2025-04-14 11:00:00

2024-05-16 12:23:45

C語言指針代碼

2021-09-06 18:54:58

Java代碼表達(dá)式

2025-02-06 07:30:32

2023-12-21 08:02:31

React DnD拖拽庫組件

2022-12-07 10:02:17

ChatGPTAI免費試用

2017-05-29 21:46:06

數(shù)博會馬化騰驚喜

2025-06-27 03:10:00

2024-07-10 10:15:43

2020-12-14 05:57:01

clipboard.Selection execCommand

2015-02-26 10:46:13

iPhone 6Android

2016-12-28 17:59:28

MongoDBNoSQL數(shù)據(jù)

2025-08-25 09:05:00

芯片AI訓(xùn)練

2018-02-06 08:42:10

永久內(nèi)存XPoint閃存

2012-07-03 09:59:03

程序員

2025-06-30 08:43:50

網(wǎng)關(guān)代碼

2024-07-09 09:36:17

2022-01-10 06:52:59

拖拽庫項目搜索
點贊
收藏

51CTO技術(shù)棧公眾號

国产乱码精品一区二区三区四区| 狠狠狠综合7777久夜色撩人| 欧美日韩导航| 精品爽片免费看久久| 超碰在线公开免费| 国产精品乱码妇女bbbb| www国产精品内射老熟女| 国产老女人精品毛片久久| 欧洲一区二区在线观看| 国产一区日韩一区| 国产精品mp4| 中文字幕一区日韩精品| 久久精品国产99国产精品澳门| 性国裸体高清亚洲| 精品国内二区三区| 成人ww免费完整版在线观看| 欧美揉bbbbb揉bbbbb| 手机福利在线| 五月天中文字幕一区二区| 伦理电影国产精品| 亚洲视频在线一区二区| 成人免费淫片在线费观看| 国产精品午夜免费| 一插菊花综合| 国产精品日日摸夜夜摸av| 午夜免费福利在线| 亚洲欧洲日韩综合一区二区| 性一爱一乱一交一视频| 精品久久久久久久久久久久久久 | 亚洲砖区区免费| 日本成人在线一区| 欧美少妇一区二区三区| 成人一级视频在线观看| 欧美aⅴ在线观看| 中文字幕欧美三区| 西瓜成人精品人成网站| 欧美一二三视频| 日韩精品中文字幕吗一区二区| 久久久午夜电影| 欧美精品videosex牲欧美| sm性调教片在线观看| 日韩一区二区福利| 午夜精品福利影院| 成人性免费视频| 五月综合激情日本mⅴ| 亚洲欧美日韩精品在线| 有码一区二区三区| 亚洲免费一区三区| 久久99精品久久久久久青青日本| 高潮白浆女日韩av免费看| 北岛玲heyzo一区二区| 亚洲欧美福利视频| 国产一区二区三区四区五区| 一级性生活视频| 一区二区三区在线不卡| 黄色大片在线免费看| 精品国产乱码久久久久久婷婷 | 国内不卡的二区三区中文字幕| www.欧美日本韩国| 精品国产网站地址| 蜜臀久久99精品久久久久宅男| 免费网站www在线观看| 网址你懂得在线观看| 亚洲午夜在线电影| 无遮挡的视频在线观看 | 欧美在线小视频| 天堂网在线最新版www中文网| 久久国产精品久久精品| 99久久久国产精品美女| 中文字幕一区二区三区精彩视频| 国产日韩欧美精品在线| 岛国视频免费在线观看| 综合网日日天干夜夜久久| 日韩欧美国产精品综合嫩v| 丝袜足脚交91精品| 亚洲免费在线播放| 黑人巨大精品| 91系列在线观看| 99国产精品久久久久| 在线观看黄色av| 午夜精品久久17c| 老鸭窝一区二区久久精品| 国产精品㊣新片速递bt| 亚洲人成网站在线播| 伊人情人综合网| 分分操这里只有精品| 色悠悠亚洲一区二区| 国产精品66| 高清国产在线一区| 中文字幕av一区二区三区| 久草免费在线色站| 国产精品一区二区女厕厕| 成人听书哪个软件好| 岛国成人毛片| 国产日韩欧美另类| 国产丝袜在线精品| 深夜福利视频一区二区| 电影午夜精品一区二区三区| 亚洲欧美在线另类| 成人毛片免费| 日韩欧美亚洲在线| 欧美系列一区二区| 成人情趣视频网站| 欧美精品久久久久久久久25p| 欧美tickling网站挠脚心| 999久久久国产精品| 9l视频白拍9色9l视频| 色av中文字幕一区| 极品美女销魂一区二区三区| 美女隐私在线观看| 亚洲一区二区三区xxx视频| 国产精品网站在线| crdy在线观看欧美| www.在线观看av| 亚洲精品在线视频| 视频在线观看91| аⅴ资源新版在线天堂| 91夜夜揉人人捏人人添红杏| 亚洲精品欧美激情| 日韩有码一区| eeuss在线播放| 51久久精品夜色国产麻豆| 国产亚洲1区2区3区| 国产一区二区三区视频在线| 黄网站欧美内射| 最新亚洲国产精品| 成人黄色大片在线观看| 婷婷综合六月| 青青草综合在线| 中文字幕日韩av电影| 丁香一区二区三区| 成人在线视频观看| 成人免费在线小视频| 美女性感视频久久久| 91麻豆文化传媒在线观看| 国产精选久久| 久久久久久久久久久久91| 欧美激情国产精品| 国产精品系列在线| 一区二区小说| 亚洲国产资源| 99re热精品| 欧美理论电影在线| 久久婷婷丁香| 性欧美gay| 日韩免费毛片视频| 奇米影视亚洲狠狠色| 午夜精品福利一区二区三区蜜桃| 亚洲欧美在线专区| 亚洲夜夜综合| 欧美国产综合在线| 97国产一区二区精品久久呦| 五月婷婷综合激情| 老妇喷水一区二区三区| 成人看片在线观看| 欧美大尺度做爰床戏| 成人黄色激情网| 91麻豆精品国产91| 丁香网亚洲国际| 神马香蕉久久| 成人精品福利| 国产精品99久久久久久大便| 欧美大码xxxx| 一本久道中文字幕精品亚洲嫩| 久久精选视频| 136福利精品导航| 中文在线有码| a级黄色片网站| 青草热久免费精品视频| 欧美亚洲动漫精品| 国产精品自拍一区| 日韩美女国产精品| 欧美激情午夜| 久久精品免费一区二区| 91精品综合视频| 亚洲天堂影视av| 亚洲精品少妇30p| 天堂蜜桃91精品| 成人三级av在线| 91大神在线网站| www.亚洲天堂网| 国产视频不卡| 欧美第一页在线| 欧美精品日韩精品| 久久精品综合网| 国产美女一区| 老司机aⅴ在线精品导航| 麻豆传媒在线观看| www亚洲成人| 亚洲精品人成| 国产精品亚洲第一区| 亚洲精品资源在线| 精品久久久一区二区| 99久久综合精品| 日韩午夜av在线| 国产精品qvod| a国产在线视频| 中文在线а√在线| 正在播放亚洲| 成人久久精品视频|