smooth-signature H5 est livré avec une signature manuscrite à pointe de stylet et prend en charge une utilisation sur PC/mobile
bibliothèque de gestion multi-états de mini-programmes de mini-magasins, prend en charge l'utilisation de mini-programmes multiplateformes
Affectés par l'épidémie, les processus sans papier et les contrats électroniques sont devenus populaires, la demande de signatures électroniques a également continué d'augmenter et l'expérience de signature s'est progressivement améliorée, du dessin de lignes sur une simple toile au début à la poursuite de lignes soyeuses et rondes. , puis nécessiter du papier japonais. L'effet de trait est le même que celui d'écrire dessus, etc. Il existe de nombreuses bibliothèques de signatures open source prêtes à l'emploi sur Internet. Parmi elles, l'effet de trait signature_pad est meilleur, mais lorsqu'il est utilisé spécifiquement, il y aura toujours une sensation irrégulière évidente. J'ai donc utilisé mon temps libre pour implémenter une autre solution basée sur. ma propre compréhension. En même temps, nous avons également développé une version du mini-programme et l'avons partagé avec les étudiants dans le besoin.
npm install mini-smooth-signature
# 或
yarn add mini-smooth-signature
Prend en charge les mini-programmes WeChat/Alipay/DingTalk/QQ. Ce qui suit est le code de test pour la plate-forme DingTalk. Veuillez consulter les exemples de codes de chaque plate-forme. Les mini-programmes sur d'autres plates-formes peuvent se référer aux exemples existants pour les vérifier et les utiliser par vous-même.
< 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 ( ) ;
} ,
} ) ;
Tous les éléments de configuration sont facultatifs
const signature = new Signature ( ctx , {
width : 300 ,
height : 600 ,
scale : 2 ,
minWidth : 4 ,
maxWidth : 10 ,
color : '#1890ff' ,
bgColor : '#efefef' ,
} ) ;
options.largeur
La largeur du canevas réellement rendu sur la page (px)
number
options.hauteur
La hauteur du canevas réellement rendu sur la page (px)
number
options.scale
Zoom sur la toile
number
options.color
couleur du pinceau
string
options.bgColor
Couleur du fond de la toile
string
options.getImagePath
Fonction de promesse qui génère des images temporaires pour enregistrer l'historique. Si cet élément n'est pas configuré, la fonction d'annulation n'est pas disponible.
promise
options.toDataURL
Générer une fonction d'image base64
function
options.requestAnimationFrame
Exécuté la prochaine fois qu'un redessinage se produit. Utilisé pour améliorer les performances de la peinture et réduire les décalages et les irrégularités.
function
options.openSmooth
S'il faut activer l'effet de bord du stylet, activé par défaut
boolean
options.minWidth
La largeur minimale du pinceau (px), la largeur minimale du pinceau lorsque la pointe du stylet est allumée
number
options.maxWidth
La largeur maximale du pinceau (px), la largeur maximale du pinceau lorsque le bord du pinceau est activé ou la largeur normale du pinceau lorsque le bord du pinceau n'est pas activé
number
options.minVitesse
La vitesse minimale (px/ms) requise pour que le pinceau atteigne la largeur minimale. La plage de valeurs est comprise entre 1,0 et 10,0. Plus la valeur est petite, plus il est facile pour le pinceau de devenir plus fin et l'effet de trait sera plus évident. . Vous pouvez ajuster l'effet par vous-même et choisir une valeur qui vous convient.
number
options.maxWidthDiffRate
Le pourcentage maximum d'augmentation (diminution) de la largeur de deux lignes adjacentes. La plage de valeurs est comprise entre 1 et 100. Afin d'obtenir l'effet de trait, la largeur du pinceau changera avec la vitesse du pinceau. trop grand, l'effet de transition sera brusque, utilisez maxWidthDiffRate pour limiter la différence de largeur afin de rendre l'effet de transition plus naturel. Vous pouvez régler vous-même l'effet de visualisation et choisir une valeur qui vous convient.
number
options.maxHistoryLength
Limitez le nombre d'enregistrements d'historique, c'est-à-dire le nombre maximum pouvant être annulé. Passer 0 désactivera la fonction d'enregistrement d'historique.
number
// 画布上下文context
signature . ctx
// 清屏
signature . clear ( )
// 撤销,如果未配置getImagePath,则不可用
signature . undo ( )
// 获取base64图片,若未配置toDataURL,则不可用
signature . toDataURL ( )
// 是否为空
signature . isEmpty ( )
Nous écrivons généralement sur du papier. Si vous regardez attentivement, vous constaterez que l'épaisseur des traits est inégale. Cela est dû à la force de pression et à la vitesse de déplacement différentes du stylo pendant le processus d'écriture. Sur les navigateurs informatiques et mobiles, même si nous ne pouvons pas obtenir la pression du toucher, nous pouvons utiliser la vitesse du mouvement du pinceau pour obtenir des effets de trait inégaux, rendant les polices aussi nettes que l'écriture sur papier. , le processus d'implémentation spécifique est présenté ci-dessous (le code présenté ci-dessous est uniquement destiné à faciliter la compréhension, pas le code d'implémentation final).
Collectez les coordonnées des points déplacés en écoutant l'événement de déplacement du canevas, enregistrez l'heure actuelle, puis enregistrez-la dans le tableau de points.
function onTouchMove ( x , y ) {
const point = { x , y , t : Date . now ( ) }
points . push ( point ) ;
} ;
Calculez la distance entre les deux points grâce aux coordonnées des deux points, puis divisez-la par la différence de temps pour obtenir la vitesse de déplacement.
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 ) ;
Obtenez la vitesse de déplacement entre deux points, puis calculez la largeur de la ligne grâce à un algorithme simple, où maxWidth, minWidth et minSpeed sont des éléments de configuration
const addWidth = ( maxWidth - minWidth ) * speed / minSpeed ;
const lineWidth = Math . min ( Math . max ( maxWidth - addWidth , minWidth ) , maxWidth ) ;
De plus, afin d'éviter que la différence de largeur entre deux lignes adjacentes ne soit trop importante et ne provoque un effet de transition brusque, des restrictions doivent être apportées, où maxWidthDiffRate est un élément de configuration et preLineWidth est la largeur de la ligne précédente.
const rate = ( lineWidth - preLineWidth ) / preLineWidth ;
const maxRate = maxWidthDiffRate / 100 ;
if ( Math . abs ( rate ) > maxRate ) {
const per = rate > 0 ? maxRate : - maxRate ;
lineWidth = preLineWidth * ( 1 + per ) ;
}
Maintenant que vous connaissez la largeur de la ligne entre deux points, l’étape suivante consiste à tracer la ligne. Afin de rendre les lignes arrondies et la transition entre les épaisseurs de ligne plus naturelle, j'ai fait la moyenne de la ligne entre deux points en trois segments, où :
Commencez à tracer la ligne, regardez d'abord le premier segment de la ligne, car le premier segment de la ligne coupe la ligne précédente, afin d'assurer une transition en douceur entre les deux lignes, une courbe de Bézier quadratique est utilisée et le point de départ point est le point de départ du troisième segment de la ligne précédente (pre_x2, pre_y2).
ctx . lineWidth = lineWidth1
ctx . beginPath ( ) ;
ctx . moveTo ( pre_x2 , pre_y2 ) ;
ctx . quadraticCurveTo ( x0 , y0 , x1 , y1 ) ;
ctx . stroke ( ) ;
Le deuxième segment de ligne est la ligne de transition reliant le premier segment et le troisième segment. Étant donné que les largeurs de ligne du premier segment et du troisième segment sont différentes, le deuxième segment de la ligne est rempli d'un trapèze pour rendre l'effet de transition plus important. naturel.
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 ( ) ;
Répétez l’opération ci-dessus lorsque vous tracez la ligne suivante dans le troisième paragraphe.