يأتي H5 ذو التوقيع السلس مزودًا بتوقيع الكتابة اليدوية بطرف القلم ويدعم استخدام الكمبيوتر/الهاتف المحمول
مكتبة إدارة البرامج المصغرة ذات المخازن الصغيرة متعددة الحالات، تدعم استخدام البرامج المصغرة متعددة المنصات
متأثرة بالوباء، أصبحت العمليات غير الورقية والعقود الإلكترونية شائعة، كما استمر الطلب على التوقيعات الإلكترونية في الزيادة، وتحسنت تجربة التوقيع تدريجياً، من رسم الخطوط على قماش بسيط في البداية، إلى متابعة الخطوط الحريرية والمستديرة ، ومن ثم طلب الورق الياباني، فإن تأثير حافة القلم هو نفس تأثير الكتابة عليه، وما إلى ذلك. هناك العديد من مكتبات التوقيع الجاهزة مفتوحة المصدر على الإنترنت، ومن بينها تأثير ضربة التوقيع Sign_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' ,
} ) ;
options.width
عرض اللوحة القماشية المعروضة فعليًا على الصفحة (px)
number
options.height
ارتفاع اللوحة القماشية المعروضة فعليًا على الصفحة (px)
number
options.scale
تكبير قماش
number
options.color
لون الفرشاة
string
options.bgColor
لون الخلفية قماش
string
options.getImagePath
وظيفة الوعد التي تقوم بإنشاء صور مؤقتة لحفظ السجل إذا لم يتم تكوين هذا العنصر، فلن تكون وظيفة التراجع متاحة.
promise
options.toDataURL
إنشاء وظيفة صورة base64
function
options.requestAnimationFrame
يتم تنفيذه في المرة التالية التي يحدث فيها إعادة رسم. يستخدم لتحسين أداء الطلاء وتقليل التأخر وعدم النعومة
function
options.openSmooth
ما إذا كان سيتم تمكين تأثير حافة القلم، والذي يتم تمكينه افتراضيًا
boolean
options.minWidth
الحد الأدنى لعرض الفرشاة (px)، الحد الأدنى لعرض الفرشاة عند تشغيل رأس القلم
number
options.maxWidth
الحد الأقصى لعرض الفرشاة (px)، أو الحد الأقصى لعرض الفرشاة عند تشغيل حافة الفرشاة، أو العرض العادي للفرشاة عندما لا تكون حافة الفرشاة قيد التشغيل
number
options.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 ( )
عادة ما نكتب على الورق، إذا نظرت عن كثب، ستجد أن سمك ضربات القلم غير متساوٍ، وهذا بسبب اختلاف قوة الضغط وسرعة الحركة للقلم أثناء عملية الكتابة. في متصفحات الكمبيوتر والهواتف المحمولة، على الرغم من أننا لا نستطيع الحصول على ضغط اللمس، إلا أنه يمكننا استخدام سرعة حركة الفرشاة لتحقيق تأثيرات ضربات غير متساوية، مما يجعل الخط يبدو حادًا مثل الكتابة على الورق. ، يتم تقديم عملية التنفيذ المحددة أدناه (الكود الموضح أدناه هو فقط لسهولة الفهم، وليس رمز التنفيذ النهائي).
اجمع إحداثيات النقاط المنقولة من خلال الاستماع إلى حدث نقل اللوحة القماشية، وقم بتسجيل الوقت الحالي، ثم احفظه في مصفوفة النقاط.
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 ) ;
}
الآن بعد أن عرفت عرض الخط بين كل نقطتين، فإن الخطوة التالية هي رسم الخط. من أجل جعل الخطوط تبدو مستديرة والانتقال بين سمك الخط أكثر طبيعية، قمت بمتوسط الخط بين نقطتين إلى ثلاثة أجزاء، حيث:
ابدأ برسم الخط، انظر أولاً إلى الجزء الأول من الخط، لأن الجزء الأول من الخط يتقاطع مع السطر السابق، ولضمان الانتقال السلس بين الخطين، يتم استخدام منحنى بيزييه التربيعي، والبداية النقطة هي نقطة البداية للجزء الثالث من السطر السابق (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 ( ) ;
كرر العملية المذكورة أعلاه عند رسم السطر التالي في الفقرة الثالثة.