Smooth-Signature H5 มาพร้อมลายเซ็นลายมือปลายปากกา และรองรับการใช้งานพีซี/มือถือ
มินิสโตร์ มินิโปรแกรม ไลบรารีการจัดการหลายสถานะ รองรับการใช้งานมินิโปรแกรมหลายแพลตฟอร์ม
ได้รับผลกระทบจากการแพร่ระบาด กระบวนการไร้กระดาษและสัญญาอิเล็กทรอนิกส์ได้รับความนิยม ความต้องการลายเซ็นอิเล็กทรอนิกส์ก็เพิ่มขึ้นอย่างต่อเนื่อง และประสบการณ์เกี่ยวกับลายเซ็นก็ค่อยๆ ดีขึ้น ตั้งแต่การวาดเส้นบนผืนผ้าใบเรียบง่ายตั้งแต่เริ่มต้น ไปจนถึงการใช้เส้นที่นุ่มนวลและกลมมน แล้วต้องใช้กระดาษญี่ปุ่น เอฟเฟกต์ขอบปากกาก็เหมือนกับการเขียนบนกระดาษ เป็นต้น มีไลบรารีลายเซ็นแบบโอเพ่นซอร์สสำเร็จรูปมากมายบนอินเทอร์เน็ต ในหมู่พวกเขา เอฟเฟกต์ลายเส้นของ Signature_pad นั้นดีกว่า แต่คุณยังคงพบความรู้สึกหยักอย่างเห็นได้ชัดเมื่อใช้งาน ดังนั้นฉันจึงใช้เวลาว่างเพื่อปรับใช้โซลูชันอื่นตามของฉัน ความเข้าใจของตัวเอง ขณะเดียวกัน เรายังพัฒนาเวอร์ชันของมินิโปรแกรมและแบ่งปันกับนักเรียนที่ต้องการ
npm install mini-smooth-signature
# 或
yarn add mini-smooth-signature
รองรับมินิโปรแกรม WeChat/Alipay/DingTalk/QQ ต่อไปนี้คือโค้ดทดสอบสำหรับแพลตฟอร์ม DingTalk โปรดดูตัวอย่างโค้ดตัวอย่างของแต่ละแพลตฟอร์ม
< view >
< canvas
id = " signature "
width = " {{width * scale}} "
height = " {{height * scale}} "
style = " width:{{width}}px;height:{{height}}px; "
disable-scroll = " {{true}} "
onTouchStart = " handleTouchStart "
onTouchMove = " handleTouchMove "
onTouchCancel = " handleTouchEnd "
onTouchEnd = " handleTouchEnd "
/>
</ view >
import Signature from 'mini-smooth-signature' ;
Page ( {
data : {
width : 320 ,
height : 200 ,
scale : 2 ,
} ,
onReady ( ) {
this . initSignature ( )
} ,
// 初始化
initSignature ( ) {
const ctx = dd . createCanvasContext ( 'signature' ) ;
this . signature = new Signature ( ctx , {
width : this . data . width ,
height : this . data . height ,
scale : this . data . scale ,
getImagePath : ( ) => {
return new Promise ( ( resolve ) => {
ctx . toTempFilePath ( {
success : res => resolve ( res . filePath ) ,
} )
} )
}
} ) ;
} ,
// 绑定touchstart事件
handleTouchStart ( e ) {
const pos = e . touches [ 0 ] ;
this . signature . onDrawStart ( pos . x , pos . y ) ;
} ,
// 绑定touchmove事件
handleTouchMove ( e ) {
const pos = e . touches [ 0 ] ;
this . signature . onDrawMove ( pos . x , pos . y ) ;
} ,
// 绑定touchend/touchcancel事件
handleTouchEnd ( ) {
this . signature . onDrawEnd ( ) ;
} ,
} ) ;
รายการการกำหนดค่าทั้งหมดเป็นทางเลือก
const signature = new Signature ( ctx , {
width : 300 ,
height : 600 ,
scale : 2 ,
minWidth : 4 ,
maxWidth : 10 ,
color : '#1890ff' ,
bgColor : '#efefef' ,
} ) ;
ตัวเลือกความกว้าง
ความกว้างของผืนผ้าใบที่แสดงผลจริงบนหน้า (px)
number
ตัวเลือกความสูง
ความสูงของผืนผ้าใบที่แสดงผลจริงบนหน้า (px)
number
ตัวเลือก.ขนาด
แคนวาสซูม
number
ตัวเลือกสี
สีแปรง
string
options.bgColor
สีพื้นหลังแคนวาส
string
options.getImagePath
ฟังก์ชันสัญญาที่สร้างรูปภาพชั่วคราวสำหรับบันทึกประวัติ หากไม่ได้กำหนดค่ารายการนี้ ฟังก์ชันเลิกทำจะไม่สามารถใช้งานได้
promise
options.toDataURL
สร้างฟังก์ชันรูปภาพ base64
function
options.requestAnimationFrame
ดำเนินการในครั้งถัดไปที่มีการวาดใหม่เกิดขึ้น ใช้เพื่อปรับปรุงประสิทธิภาพการทาสีและลดความล่าช้าและความไม่ราบรื่น
function
options.openSmooth
ไม่ว่าจะเปิดใช้งานเอฟเฟกต์ขอบปากกาหรือไม่ เปิดใช้งานตามค่าเริ่มต้น
boolean
ตัวเลือก minWidth
ความกว้างขั้นต่ำของแปรง (px) ความกว้างขั้นต่ำของแปรงเมื่อเปิดปลายปากกา
number
ตัวเลือก.maxWidth
ความกว้างสูงสุดของแปรง (px) ความกว้างสูงสุดของแปรงเมื่อเปิดขอบแปรง หรือความกว้างปกติของแปรงเมื่อไม่ได้เปิดขอบแปรง
number
ตัวเลือก minSpeed
ความเร็วขั้นต่ำ (px/ms) ที่จำเป็นสำหรับแปรงเพื่อให้ได้ความกว้างขั้นต่ำ ช่วงค่าคือ 1.0-10.0 ยิ่งค่าน้อยเท่าใด แปรงก็จะบางลงได้ง่ายขึ้น และเอฟเฟกต์ปลายแปรงก็จะมากขึ้นเท่านั้น ชัดเจน คุณสามารถปรับเอฟเฟกต์การรับชมได้ด้วยตัวเองและเลือกค่าที่คุณพอใจ
number
options.maxWidthDiffRate
เปอร์เซ็นต์ที่เพิ่มขึ้นสูงสุด (ลดลง) ในความกว้างของเส้นสองเส้นที่อยู่ติดกัน ช่วงค่าคือ 1-100 เพื่อให้บรรลุเอฟเฟกต์เส้นขีด ความกว้างของแปรงจะเปลี่ยนไปตามความเร็วของแปรง มีขนาดใหญ่เกินไป เอฟเฟกต์การเปลี่ยนแปลงจะเกิดขึ้นอย่างกะทันหัน ให้ใช้ maxWidthDiffRate เพื่อจำกัดความแตกต่างของความกว้างเพื่อให้เอฟเฟกต์การเปลี่ยนแปลงเป็นธรรมชาติมากขึ้น คุณสามารถปรับเอฟเฟ็กต์การรับชมได้ด้วยตัวเอง และเลือกค่าที่คุณพึงพอใจ
number
options.maxHistoryLength
จำกัดจำนวนบันทึกประวัติ นั่นคือ จำนวนสูงสุดที่สามารถยกเลิกได้ การผ่าน 0 จะปิดฟังก์ชันบันทึกประวัติ
number
// 画布上下文context
signature . ctx
// 清屏
signature . clear ( )
// 撤销,如果未配置getImagePath,则不可用
signature . undo ( )
// 获取base64图片,若未配置toDataURL,则不可用
signature . toDataURL ( )
// 是否为空
signature . isEmpty ( )
เรามักจะเขียนบนกระดาษ หากมองใกล้ ๆ จะพบว่าความหนาของลายเส้นไม่เท่ากัน ซึ่งมีสาเหตุมาจากแรงกดและความเร็วในการเคลื่อนที่ที่แตกต่างกันของปากกาในระหว่างขั้นตอนการเขียน บนคอมพิวเตอร์และเบราว์เซอร์มือถือ แม้ว่าเราจะรับแรงกดจากการสัมผัสไม่ได้ แต่เราสามารถใช้ความเร็วของการเคลื่อนไหวของแปรงเพื่อให้ได้เอฟเฟกต์ลายเส้นที่ไม่สม่ำเสมอ ทำให้แบบอักษรดูคมชัดราวกับการเขียนบนกระดาษ มีการแนะนำขั้นตอนการใช้งานเฉพาะด้านล่าง (โค้ดที่แสดงด้านล่างมีไว้เพื่อความสะดวกในการทำความเข้าใจเท่านั้น ไม่ใช่โค้ดการใช้งานขั้นสุดท้าย)
รวบรวมพิกัดของจุดที่ย้ายโดยการฟังเหตุการณ์การย้ายแคนวาส บันทึกเวลาปัจจุบัน จากนั้นบันทึกลงในอาร์เรย์ Points
function onTouchMove ( x , y ) {
const point = { x , y , t : Date . now ( ) }
points . push ( point ) ;
} ;
คำนวณระยะห่างระหว่างจุดสองจุดผ่านพิกัดของจุดสองจุด แล้วหารด้วยส่วนต่างของเวลาเพื่อให้ได้ความเร็วในการเคลื่อนที่
const distance = Math . sqrt ( Math . pow ( end . x - start . x , 2 ) + Math . pow ( end . y - start . y , 2 ) ) ;
const speed = distance / ( end . t - start . t ) ;
รับความเร็วในการเคลื่อนที่ระหว่างสองจุดแล้วคำนวณความกว้างของเส้นผ่านอัลกอริธึมง่ายๆ โดยที่ maxWidth, minWidth และ minSpeed เป็นรายการกำหนดค่า
const addWidth = ( maxWidth - minWidth ) * speed / minSpeed ;
const lineWidth = Math . min ( Math . max ( maxWidth - addWidth , minWidth ) , maxWidth ) ;
นอกจากนี้ เพื่อป้องกันไม่ให้ความแตกต่างด้านความกว้างระหว่างสองบรรทัดที่อยู่ติดกันมีขนาดใหญ่เกินไปและทำให้เกิดเอฟเฟกต์การเปลี่ยนแปลงอย่างกะทันหัน จำเป็นต้องมีข้อจำกัด โดยที่ maxWidthDiffRate คือรายการการกำหนดค่า และ preLineWidth คือความกว้างของบรรทัดก่อนหน้า
const rate = ( lineWidth - preLineWidth ) / preLineWidth ;
const maxRate = maxWidthDiffRate / 100 ;
if ( Math . abs ( rate ) > maxRate ) {
const per = rate > 0 ? maxRate : - maxRate ;
lineWidth = preLineWidth * ( 1 + per ) ;
}
ตอนนี้คุณรู้ความกว้างของเส้นระหว่างทุกสองจุดแล้ว ขั้นตอนต่อไปคือการวาดเส้น เพื่อให้เส้นดูโค้งมนและการเปลี่ยนระหว่างความหนาของเส้นเป็นธรรมชาติมากขึ้น ฉันจึงเฉลี่ยเส้นระหว่างจุดสองจุดออกเป็นสามส่วน โดยที่:
เริ่มวาดเส้น ขั้นแรกให้ดูที่ส่วนแรกของเส้น เนื่องจากส่วนแรกของเส้นตัดกับเส้นก่อนหน้า เพื่อให้มั่นใจว่าการเปลี่ยนผ่านระหว่างสองเส้นเป็นไปอย่างราบรื่น จึงมีการใช้เส้นโค้ง Bezier กำลังสอง และจุดเริ่มต้น point คือจุดเริ่มต้นของส่วนที่สามของบรรทัดก่อนหน้า (pre_x2, pre_y2)
ctx . lineWidth = lineWidth1
ctx . beginPath ( ) ;
ctx . moveTo ( pre_x2 , pre_y2 ) ;
ctx . quadraticCurveTo ( x0 , y0 , x1 , y1 ) ;
ctx . stroke ( ) ;
ส่วนที่สองของเส้นคือเส้นเปลี่ยนที่เชื่อมระหว่างส่วนแรกและส่วนที่สาม เนื่องจากความกว้างของเส้นของส่วนแรกและส่วนที่สามแตกต่างกัน ส่วนที่สองของเส้นจึงเต็มไปด้วยสี่เหลี่ยมคางหมูเพื่อให้เอฟเฟกต์การเปลี่ยนแปลงมากขึ้น เป็นธรรมชาติ.
ctx . beginPath ( ) ;
ctx . moveTo ( point1 . x , point1 . y ) ;
ctx . lineTo ( point2 . x , point2 . y ) ;
ctx . lineTo ( point3 . x , point3 . y ) ;
ctx . lineTo ( point4 . x , point4 . y ) ;
ctx . fill ( ) ;
ทำซ้ำการดำเนินการข้างต้นเมื่อวาดบรรทัดถัดไปในย่อหน้าที่สาม