Created
February 23, 2020 18:59
-
-
Save calebergh/65b7f0f8b5d7e5d1e6cb977a4cb907f4 to your computer and use it in GitHub Desktop.
Electronic Signature Pad for Angular 8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Directive, ElementRef, EventEmitter, HostListener, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; | |
@Directive({ | |
// tslint:disable-next-line:directive-selector | |
selector: '[signature]', | |
}) | |
export class SignatureDirective implements OnInit, OnChanges { | |
@Output() imgSrc = new EventEmitter<string>(); | |
@Input('clear') clearMe; | |
@Input('options') options; | |
private context; | |
private density: number; | |
private isDrawing = false; | |
private sigPadElement; | |
ngOnInit() { | |
this.sigPadElement = this.signaturePad.nativeElement; | |
this.context = this.sigPadElement.getContext('2d'); | |
this.context.strokeStyle = this.options.color || '#3742fa'; | |
this.context.lineWidth = this.options.width || 2; | |
if ( this.options.blur) { | |
this.context.shadowBlur = this.options.blur || 2; | |
this.context.shadowColor = this.options.blurColor || this.context.strokeStyle; | |
} | |
this.context.lineCap = 'round'; | |
this.context.lineJoin = 'round'; | |
this.density = window.devicePixelRatio || 1; | |
} | |
ngOnChanges(changes: SimpleChanges) { | |
if (!this.context) { | |
return; | |
} | |
if (changes.clearMe) { | |
this.clear(); | |
this.save(); | |
} | |
} | |
constructor(private signaturePad: ElementRef) { | |
} | |
@HostListener('touchstart', ['$event']) | |
handleTouchStart(e) { | |
e.preventDefault(); | |
this.isDrawing = true; | |
this.start(e, 'layer'); | |
} | |
@HostListener('touchmove', ['$event']) | |
handleTouchMove(e) { | |
if (!this.isDrawing) { | |
return; | |
} | |
e.preventDefault(); | |
this.draw(e, 'layer'); | |
} | |
@HostListener('document:touchend', ['$event']) | |
@HostListener('document:mouseup', ['$event']) | |
onMouseUp() { | |
if ( this.isDrawing) { | |
this.save(); | |
} | |
this.isDrawing = false; | |
} | |
@HostListener('mousedown', ['$event']) | |
onMouseDown(e) { | |
this.isDrawing = true; | |
this.start(e); | |
} | |
@HostListener('mousemove', ['$event']) | |
onMouseMove(e) { | |
if (!this.isDrawing) { | |
return; | |
} | |
this.draw(e); | |
} | |
private start(e, type: 'client' | 'layer' = 'client') { | |
const coords = this.relativeCoords(e, type); | |
this.context.moveTo(coords.x, coords.y); | |
} | |
private draw(e, type: 'client' | 'layer' = 'client') { | |
const coords = this.relativeCoords(e, type); | |
this.context.lineTo(coords.x, coords.y); | |
this.context.stroke(); | |
} | |
private relativeCoords(event, type: 'client' | 'layer') { | |
const bounds = this.sigPadElement.getBoundingClientRect(); | |
let x = event[ type + 'X' ]; | |
let y = event[ type + 'Y' ]; | |
if ('layer' !== type) { | |
x -= bounds.left; | |
y -= bounds.top; | |
} | |
return { x, y }; | |
} | |
clear() { | |
this.context.clearRect(0, 0, this.sigPadElement.width, this.sigPadElement.height); | |
this.context.beginPath(); | |
} | |
save() { | |
this.imgSrc.emit(this.sigPadElement.toDataURL('image/png')); | |
} | |
} |
first of all ,thanks a lot for this great directive I have only one problem ,when toggling device toolbar on google chrome ,to test the code in responsive and in different screens ,it doesn't draw and events in the directive are not fired ,any idea why is that ?
The directive does not watch for window resize events, but certainly could be made to do so. Adding a HostListener for document resize, and triggering some of the "init" code would likely make it work in a responsive manner.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
first of all ,thanks a lot for this great directive
I have only one problem ,when toggling device toolbar on google chrome ,to test the code in responsive and in different screens ,it doesn't draw and events in the directive are not fired ,any idea why is that ?