vue移動(dòng)端使用canvas簽名的實(shí)現(xiàn)
效果

canvas畫(huà)板移動(dòng)端 .gif
需求
在一些項(xiàng)目業(yè)務(wù)中,經(jīng)常會(huì)使用到畫(huà)板,讓用戶自己去寫(xiě)/畫(huà)一些東西做標(biāo)示,比如說(shuō)在線簽電子合約、簽名等,如果不用插件,那么如何使用h5的canvas畫(huà)布來(lái)實(shí)現(xiàn)這一需求呢? 【本篇只討論移動(dòng)端,PC端請(qǐng)看上篇】
分析
很明顯,我們需要一個(gè)canvas,關(guān)于canvas的一些基本操作可以在w3school或者別的一些平臺(tái)上熟悉一下,其實(shí)本例也是基礎(chǔ)操作。本案例在vue中完成。(脫離vue也一樣。)
- 首先,需要一個(gè)canvas畫(huà)布
- 其次,考慮邏輯
- 把邏輯實(shí)現(xiàn)
1. canvas畫(huà)布
隨意布局的一個(gè)畫(huà)布,此處值得注意的是如果canvas的寬高確定,則在html>canvas中直接寫(xiě)寬高,如果不確定,根據(jù)別的元素變化,那么可以在js中初始化畫(huà)布時(shí)寫(xiě)。
html
<div class="boardBox" ref="boardBox">
<canvas ref="board"
</canvas>
</div>
布局
.boardBox{
margin: 30px auto;
width: 90vw;
height: 25vh;
background: #f9f9f9;
canvas{
border: 1px solid #b3b3b3;
}
}
畫(huà)布初始化
let board = this.$refs.board; // 獲取DOM
board.width = this.$refs.boardBox.offsetWidth; // 設(shè)置畫(huà)布寬
board.height = this.$refs.boardBox.offsetHeight; // 設(shè)置畫(huà)布高
this.ctx = board.getContext('2d'); // 二維繪圖
this.ctx.strokeStyle = '#000'; // 顏色
this.ctx.lineWidth = 3; // 線條寬度
2. 邏輯分析
由于本篇只討論移動(dòng)端端,因此無(wú)非是在畫(huà)布上監(jiān)聽(tīng)三個(gè)觸摸事件:touchstart、touchmove、touchend。
那么,在這三個(gè)事件中,分別需要做什么呢?
touchstart
開(kāi)始滑動(dòng)按下,需要做:
- 獲取觸摸點(diǎn)做畫(huà)布上的位置
- 存為一個(gè)點(diǎn)坐標(biāo)(起始點(diǎn))
- 以起始點(diǎn)建立一個(gè)路徑
- 開(kāi)啟畫(huà)布操作
touchmove
觸摸滑動(dòng)時(shí),又要做那些準(zhǔn)備呢?
- 判斷是否開(kāi)啟畫(huà)布操作,如果沒(méi)開(kāi)啟就禁止繪制,因此先判斷是否當(dāng)前狀態(tài)可繪制
- 獲取觸摸點(diǎn)做畫(huà)布上的位置
- 上一個(gè)點(diǎn)到這一個(gè)點(diǎn)作連線
- 繪制出來(lái)
- 當(dāng)前點(diǎn)存儲(chǔ),下一次用
touchend
滑動(dòng)結(jié)束,事件結(jié)束:
- closePath() // 停止繪制
- 關(guān)閉畫(huà)布操作的開(kāi)關(guān)
好了,其實(shí)就是這三個(gè)事件,理清楚之后去代碼實(shí)現(xiàn)就簡(jiǎn)單得多了。附上代碼一份。
3. 代碼
CSS略,如初始化即可,不是重點(diǎn)。
<div class="boardBox" ref="boardBox">
<canvas ref="board"
@touchstart="mStart"
@touchmove="mMove"
@touchend="mEnd">
</canvas>
</div>
data() {
return {
ctx: null,
point: {
x: 0,
y: 0
},
moving: false // 是否正在繪制中且移動(dòng)
};
},
mounted() {
let board = this.$refs.board; // 獲取DOM
board.width = this.$refs.boardBox.offsetWidth; // 設(shè)置畫(huà)布寬
board.height = this.$refs.boardBox.offsetHeight; // 設(shè)置畫(huà)布高
this.ctx = board.getContext('2d'); // 二維繪圖
this.ctx.strokeStyle = '#000'; // 顏色
this.ctx.lineWidth = 3; // 線條寬度
},
methods: {
// 觸摸(開(kāi)始)
mStart (e) {
console.log(e);
let x = e.touches[0].clientX - e.target.offsetLeft,
y = e.touches[0].clientY - e.target.offsetTop; // 獲取觸摸點(diǎn)在畫(huà)板(canvas)的坐標(biāo)
this.point.x = x;
this.point.y = y;
this.ctx.beginPath();
this.moving = true;
},
// 滑動(dòng)中...
mMove (e) {
if(this.moving) {
let x = e.touches[0].clientX - e.target.offsetLeft,
y = e.touches[0].clientY - e.target.offsetTop; // 獲取觸摸點(diǎn)在畫(huà)板(canvas)的坐標(biāo)
this.ctx.moveTo(this.point.x, this.point.y); // 把路徑移動(dòng)到畫(huà)布中的指定點(diǎn),不創(chuàng)建線條(起始點(diǎn))
this.ctx.lineTo(x, y); // 添加一個(gè)新點(diǎn),然后創(chuàng)建從該點(diǎn)到畫(huà)布中最后指定點(diǎn)的線條,不創(chuàng)建線條
this.ctx.stroke(); // 繪制
this.point.x = x, this.point.y = y; // 重置點(diǎn)坐標(biāo)為上一個(gè)坐標(biāo)
}
},
// 滑動(dòng)結(jié)束
mEnd () {
if(this.moving) {
this.ctx.closePath(); // 停止繪制
this.moving = false; // 關(guān)閉繪制開(kāi)關(guān)
}
},
},
思考
- 上一篇,在PC端完成繪制,本篇如法炮制,在移動(dòng)端也順利完成,相比pc端只是稍微的修改了一下獲取坐標(biāo)點(diǎn)的算法而已。那么PC端和移動(dòng)端如何并存呢?
- 出錯(cuò)了,怎么重新繪制呢?
- 繪制完成后,怎么保存呢?
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- vue?vue-touch移動(dòng)端手勢(shì)詳解
- atom-design(Vue.js移動(dòng)端組件庫(kù))手勢(shì)組件使用教程
- 詳解IOS微信上Vue單頁(yè)面應(yīng)用JSSDK簽名失敗解決方案
- vue+element加入簽名效果(移動(dòng)端可用)
- 使用vue實(shí)現(xiàn)手寫(xiě)簽名功能
- vue 使用 canvas 實(shí)現(xiàn)手寫(xiě)電子簽名
- VUE解決微信簽名及SPA微信invalid signature問(wèn)題(完美處理)
- 使用vue實(shí)現(xiàn)一個(gè)電子簽名組件的示例代碼
- 詳解Vue開(kāi)發(fā)微信H5微信分享簽名失敗問(wèn)題解決方案
- 基于Vue實(shí)現(xiàn)手勢(shì)簽名
相關(guān)文章
vue插件開(kāi)發(fā)之使用pdf.js實(shí)現(xiàn)手機(jī)端在線預(yù)覽pdf文檔的方法
這篇文章主要介紹了vue插件開(kāi)發(fā)之使用pdf.js實(shí)現(xiàn)手機(jī)端在線預(yù)覽pdf文檔的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
proxy實(shí)現(xiàn)vue3數(shù)據(jù)雙向綁定原理
這篇文章主要介紹了proxy實(shí)現(xiàn)vue3數(shù)據(jù)雙向綁定原理,文章以介紹proxy的優(yōu)點(diǎn)開(kāi)始展開(kāi)全文內(nèi)容,圍繞proxy實(shí)現(xiàn)vue3數(shù)據(jù)雙向綁定的相關(guān)資料,,需要的朋友可以參考一下2021-12-12
vue?background-image?不顯示問(wèn)題的解決
這篇文章主要介紹了vue?background-image?不顯示問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
Electron實(shí)現(xiàn)靜默打印小票的流程詳解
很多情況下程序中使用的打印都是用戶無(wú)感知的,并且想要靈活的控制打印內(nèi)容,往往需要借助打印機(jī)給我們提供的api再進(jìn)行開(kāi)發(fā),這種開(kāi)發(fā)方式非常繁瑣,并且開(kāi)發(fā)難度較大,本文給大家介紹了Electron實(shí)現(xiàn)靜默打印小票的流程,感興趣的朋友可以參考下2024-06-06
vue組件中節(jié)流函數(shù)的失效的原因和解決方法
這篇文章主要介紹了vue組件中節(jié)流函數(shù)的失效和解決方法,幫助大家更好的理解和學(xué)習(xí)vue框架,感興趣的朋友可以了解下2020-12-12
Vue版本vue2.9.6升級(jí)到vue3.0的詳細(xì)步驟
vue版本升級(jí)相信大家應(yīng)該都遇到過(guò),下面這篇文章主要給大家介紹了關(guān)于Vue版本vue2.9.6升級(jí)到vue3.0的詳細(xì)步驟,文中通過(guò)圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
vue打印瀏覽器頁(yè)面功能的兩種實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于vue打印瀏覽器頁(yè)面功能的兩種實(shí)現(xiàn)方法,這個(gè)功能其實(shí)也是自己學(xué)習(xí)到的,做完也有一段時(shí)間了,一直想記錄總結(jié)一下,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04

