Draw and Export a Signature

In some cases, it is essential to provide the user with the option to export customly drawn objects.

The Drawing library allows the user to save a drawn object in SVG format. An undo feature is also provided.

The following example demonstrates the implementation of these features.

import { Component, ElementRef, ViewChild } from '@angular/core';
import { AfterViewInit, OnDestroy } from '@angular/core';
import { Image, Surface, Path, Text, Group, geometry, drawDOM, exportSVG } from '@progress/kendo-drawing';
import { saveAs } from '@progress/kendo-file-saver';

const { Rect, Point, Size, transform } = geometry;

@Component({
  selector: 'my-app',
  template: `
      <div #surface style="width: 750px; height: 300px; border: 1px solid black;"></div>

      <button class='k-button' (click)="export()">Export as SVG</button>
      <button class='k-button' (click)="onClear()">Clear drawing</button>
  `
})
export class AppComponent implements AfterViewInit, OnDestroy {
  @ViewChild('surface', {static: false})
  private surfaceElement: ElementRef;

  private surface: Surface;
  private path;

  public ngAfterViewInit(): void {
    this.surface = Surface.create(this.surfaceElement.nativeElement);
    this.surfaceElement.nativeElement.addEventListener('mousemove', this.onMouseMove);
    this.surfaceElement.nativeElement.addEventListener('mousedown', this.onMouseDown);
    this.surfaceElement.nativeElement.addEventListener('mouseup', this.onMouseUp);
  }

  public ngOnDestroy() {
    this.surfaceElement.nativeElement.removeEventListener('mousemove', this.onMouseMove);
    this.surfaceElement.nativeElement.removeEventListener('mousedown', this.onMouseDown);
    this.surfaceElement.nativeElement.removeEventListener('mouseup', this.onMouseUp);
    this.surface.destroy();
  }

  public onClear() {
    this.surface.clear();
  }

  public export() {
    // Convert the DOM element to a drawing using kendo.drawing.drawDOM
    drawDOM(this.surfaceElement.nativeElement)
      .then(function(group) {
      // Render the result as a SVG document
      return exportSVG(group);
    }).then(function(data) {
      // Save the SVG document
      saveAs(data, 'signature.svg');
    });
  }

  private onMouseMove = (e) => {
    if (!this.path) {
      return;
    }

    const offset = {
      top: this.surfaceElement.nativeElement.offsetTop,
      left: this.surfaceElement.nativeElement.offsetLeft
    };

    const newPoint = new Point(e.pageX - offset.left, e.pageY - offset.top);

    this.path.lineTo(newPoint);
  };

  private onMouseDown = (e) => {
    this.path = new Path({
      stroke: {
        color: '#E4141B',
        width: 2,
        lineCap: 'round',
        lineJoin: 'round'
      }
    });

    const offset = {
      top: this.surfaceElement.nativeElement.offsetTop,
      left: this.surfaceElement.nativeElement.offsetLeft
    };

    const newPoint = new Point(e.pageX - offset.left, e.pageY - offset.top);

    for (let i = 0; i < 1; i++) {
      this.path.lineTo(newPoint.clone().translate(i * 1, 0));
    }

    this.surface.draw(this.path);
  }

  private onMouseUp = (e) => this.path = undefined;
}