Skip to Content
Author's profile photo Sri Divya

Displaying a digital signature in editable mode

Hi all,

Recently I have got a requirement in which I need to display the captured digital signature in editable mode.

SVG is is a graphic container element in HTML which stands for Scalable Vector Graphics. It used for defining graphics for the web.

Earlier we used to capture and display signatures using Canvas. But I found it is better opting for SVG rather than going for Canvas for my requirement after going through many links. I also came know that when ever we need to make a change in Canvas we need to redraw the entire scene. The main advantage of SVG is it is scalable and it supports event handlers.

Firstly I have created an OData service to get and create an entity.

The logic for get entity operation: 

DATA: lt_keys       TYPE /iwbep/t_mgw_tech_pairs,
      ls_key        TYPE /iwbep/s_mgw_tech_pair,
      LV_name TYPE char20.

   lt_keys = io_tech_request_context->get_keys( ). //Get key elements
**Reading key properties
    READ TABLE lt_keys WITH KEY  NAME = 'NAME'
                                INTO ls_key.
***Setting key value to a local variable
   lv_name = ls_key-value.
***Retrieving data
  SELECT SINGLE * from ztsvg_signature into ER_ENTITY WHERE Name = lv_name.

Create operation:

Logic is as follows:

DATA: wsvg_signature TYPE ztsvg_signature.
**Read request data
IO_DATA_PROVIDER->READ_ENTRY_DATA( IMPORTING ES_DATA = wsvg_signature ).

ER_ENTITY-Name   = wsvg_signature-Name.
ER_ENTITY-SIGNURL  = wsvg_signature-SIGNURL.

INSERT ztsvg_signature FROM ER_ENTITY.

In order to create an entity, perform get to read a single entity and click on use as request to perform post operation.

Create the entity as highlighted in the HTTP Request and select HTTP method as Post. Click on execute

Custom Controller: 

In the custom controller, we are providing meta data to create a signature pad, its properties to capture mouse movement and the functions to get, set and clear signature details. The logic is as follows.

jQuery.sap.declare("com.finalcanvasFinal.controller.SignaturePad");
sap.ui.core.Control.extend("com.finalcanvasFinal.controller.SignaturePad", {	
  metadata: {
      properties: {
        width: {type: 'int', defaultValue: 300},
        height: {type: 'int', defaultValue: 100},
        bgcolor: {type: 'string', defaultValue: '#ffa'},
        lineColor: {type: 'string', defaultValue: '#666'},
        penColor: {type: 'string', defaultValue: '#333'},
        signature: 'string'
      }
    },
    
    renderer: function(oRm, oControl) {
      var bgColor = oControl.getBgcolor();
      var lineColor = oControl.getLineColor();
      var pen = oControl.getPenColor();
      var id = oControl.getId();
      var w = oControl.getWidth();
      var h = oControl.getHeight();
      oRm.write("<div");
      oRm.writeControlData(oControl);
      oRm.write(">");
      oRm.write('<svg xmlns="http://www.w3.org/2000/svg" width="' + w +
                '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '">');
      
      oRm.write('<rect id="' + id  + '_r" width="' + w + '" height="' + h + 
                '" fill="' + bgColor  + '"/>');
      
      var hh = h - 20;
      oRm.write('<line x1="0" y1="' + hh  + '" x2="' + w + '" y2="' + hh + 
                '" stroke="' + lineColor + 
                '" stroke-width="1" stroke-dasharray="3" ' + 
                'shape-rendering="crispEdges" pointer-events="none"/>');
      
      oRm.write('<path id="' + id + '_p" stroke="' + pen + '" stroke-width="2" ' +
                'fill="none" pointer-events="none"/>');
      oRm.write('</svg>');
      oRm.write("</div>");
    },
    
    clear: function() {
    	var that = this;
      that.signaturePath = '';
      var p = document.getElementById(that.getId() + '_p');
      p.setAttribute('d', '');
    },

    onAfterRendering: function() {
      var that = this;
      that.signaturePath ='';
      isDown = false;
      var elm = that.$()[0];
      var r = document.getElementById(that.getId() + '_r');
      var p = document.getElementById(that.getId() + '_p');

      function isTouchEvent(e) {
        return e.type.match(/^touch/);
      }

      function getCoords(e) {
        if (isTouchEvent(e)) {
          return e.targetTouches[0].clientX + ',' +
            e.targetTouches[0].clientY;
        }
        return e.clientX + ',' + e.clientY;
      }

      function down(e) {
        that.signaturePath += 'M' + getCoords(e) + ' ';
        p.setAttribute('d', that.signaturePath);
        isDown = true;
        if (isTouchEvent(e)) e.preventDefault();
      }

      function move(e) {
        if (isDown) {
          that.signaturePath += 'L' + getCoords(e) + ' ';
          p.setAttribute('d', that.signaturePath);
        }
        if (isTouchEvent(e)) e.preventDefault();
      }

      function up(e) {
        isDown = false; 
        if (isTouchEvent(e)) e.preventDefault();
      }

      r.addEventListener('mousedown', down, false);
      r.addEventListener('mousemove', move, false);
      r.addEventListener('mouseup', up, false);
      r.addEventListener('touchstart', down, false);
      r.addEventListener('touchmove', move, false);
      r.addEventListener('touchend', up, false);
      r.addEventListener('mouseout', up, false);
     //To get signature path 
       if (this.getSignature()) {
        this.signaturePath = this.getSignature();
        var p = document.getElementById(this.getId() + '_p');
        if (p) {
          p.setAttribute('d', this.signaturePath);
        }
      }
      // to set signature path to the signaturepad to display
       that.setSignature = function(s) {
        that.setProperty('signature', s);
        that.invalidate();
      };
     }

  });

Controller Logic:

Here I have accessed the custom controller to load all the metadata to create SVG Container and all the functions necessary to draw SVG graphics.

I have created an instance for signature pad and all other UI elements like buttons and input field for name,.

//Global variables
var prevSignature;
var isDown;
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"com/finalcanvasFinal/controller/SignaturePad"
], function(Controller, SignaturePad) {
	"use strict";

	return Controller.extend("com.finalcanvasFinal.controller.View1", {
		onInit: function() {
		//instance for signature pad	
			var oCtrl = new SignaturePad({
				id: "signPad",
				width: 400,
				height: 200
			});
		//Adding signature pad to page content
			var content = this.byId("signEdit");
			content.addContent(oCtrl);
			var that = this;
		//Input field for Name	
			var textField = new sap.m.Input({
				id: "nameValue",
				width: '10rem',
				placeholder: 'Name'

			});
			content.addContent(textField);
		//Clear button	to clear signaturePad
			var clearButton = (new sap.m.Button({
				text: 'Clear',
				press: function() {
					oCtrl.getSignature();
					sap.ui.getCore().byId("nameValue").setValue(" ");
					oCtrl.clear();
				}
			}));
			content.addContent(clearButton);
		//Accept button to save data in backend
			var acceptButton = (new sap.m.Button({
				text: 'Save',
				press: function() {
					
					var signaturePath = oCtrl.getSignature(); 
					if (signaturePath !== ' ') {

						var oEntry = {}; // instantiating the object
						oEntry.Name = sap.ui.getCore().byId("nameValue").getValue();	//Name
						oEntry.Signurl = signaturePath;									//SVG path
						var sServiceUrl = "/sap/opu/odata/sap/ZSVG_SIGNATURES_SRV/";
						var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, false);
						
						oModel.create("/SigntureSet()", oEntry, null, function(response) {
							sap.m.MessageBox.show("Success! Data is saved");
						}, function(error) {
							sap.m.MessageBox.show("Error!");

						});
					}
				}

			}));
			content.addContent(acceptButton);
			// Adding display button
			var Display = new sap.m.Button({
				text: 'Display',
				enabled: true,
				// Displaying signature based on input		
				press: function() {
					var Name = sap.ui.getCore().byId("nameValue").getValue(); //getting input value

					var sServiceUrl = "/sap/opu/odata/sap/ZSVG_SIGNATURES_SRV/";
					var oModel = new sap.ui.model.odata.ODataModel(sServiceUrl, false);
					//reading details based on name
					oModel.read("/SigntureSet(Name='" + Name + "')", null, null, false, function(oData, oResponse) {
						prevSignature = oData.Signurl;
						//Calling set signatuer method from custom controller
						oCtrl.setSignature(prevSignature);
					});
				}
			});
			content.addContent(Display);
		}

	});
});

My view looks as follows:

When a name and signature is provided and hit save, the name and SVG path will get saved to the backend system.

In order to display the signature provide the name and click on display. The result is as follows.

Thank you..!! 🙂 🙂

 

 

Assigned Tags

      14 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      Former Member

      That's one interesting topic! Thanks for sharing.

      Is this signature captured through FIRST PHONES/ Pin Pad?  (or)

      What is the phone or touch device through which this signature is captured?

       

      Kind Regards,

      Prabha

      Author's profile photo Sri Divya
      Sri Divya
      Blog Post Author

      Hi Prabhakaran,

       

      I had tested it on Desktop.I will test it on phone/ tab and will let you know.

       

      Thank you,

      Sri Divya.

       

      Author's profile photo Former Member
      Former Member

      Great Work

      SVG Canvas
      Vector based (composed of shapes) Raster based (composed of pixel)
      Multiple graphical elements, which become the part of the DOM Single HTML element similar to <img> in behavior
      Modified through script and CSS Modified through script only
      Give better performance with smaller number of objects or larger surface, or both Give better performance with smaller surface or larger number of objects, or both
      Better scalability — can be printed with high quality at any resolution Poor scalability — not suitable for printing on higher resolution

      Thank You Sri Divya Bandaru 

      Author's profile photo Sri Divya
      Sri Divya
      Blog Post Author

      Thank you Former Member

      Author's profile photo Former Member
      Former Member

      Hi divya,

      I'm involved with a project where I need to use a routing concept

      if i declare same pattern for two different views (view1,view2 same pattern) if i call the pattern using routing API what will happen

      is it call 1st view or 2nd view or we will get error?

      Thanks

       

      Author's profile photo Sri Divya
      Sri Divya
      Blog Post Author

      Hi Jagdeesh,

       

      It won’t raises any error even if we use same pattern for 2 views.

      Based on the route you hit the corresponding target view will get loaded.

      In case of single route the first view (out of two views with same pattern) whose pattern matches will get loaded.

      Thank you,

      SriDivya.

      Author's profile photo Former Member
      Former Member
      thank you sri divya
      Author's profile photo Nagandla Raghu Ram
      Nagandla Raghu Ram

      Hi Sri Divya,

      Can we keep this Digital-Sign-Pad in a simple-form and Print it. Is it possible ?

      Is there any other for this?

      Thanks and Regards,

      RR

       

      Author's profile photo Sri Divya
      Sri Divya
      Blog Post Author

      Hi Raghu,

      Greetings.

      Yes we can keep a digital signature in a simple form and we can print it.

      Please let me know if I could help you any way. 🙂

       

      Thank you,

      Sri Divya.

      Author's profile photo Nagandla Raghu Ram
      Nagandla Raghu Ram

      Hi Divya,

      How are you? Thank you for your reply.

      I have tried the following way, I kept the below code in form. It is not showing pdfform.

      But Iam able to capture the signature on Signature-pad.

      Thanks and Regards,

      Raghuram

      <VBox id="IdTable1" alignContent="SpaceBetween" justifyContent="End" alignItems="Center" class="sapUiSmallMargin">
      <core:HTML id="html"/>
      </VBox>
      
      Author's profile photo Praseena Nair
      Praseena Nair

      Hi Sri Divya,

       

      I followed your process, and was able to successfully get SVG image path in my backend service. But my requirement is to use this signature in a PDF. How can I use this SVG path in a PDF form? Do we have something in ABAP to convert SVG path to XML content ?

       

      Thanks a lot!

      -Praseena

      Author's profile photo Sven Schuberth
      Sven Schuberth

      Great Work!

       

      I've the issue, that pen, or path is not displayed...

      Do you have any solution?

       

      kr - Sven

      Author's profile photo Enrico Grasso
      Enrico Grasso

      Sri Divya where is the view created?

      Author's profile photo Santhosh Kumar
      Santhosh Kumar

      Hi SriDivya,

      I have the similar requirement where i need to insert this SVG signature into Adobeform(SFP).

      Odata value updated into Z table (Signature as String).

      Is there any way to convert this Signature into JPG Image using ABAP class or FM ?

      Thanks,

      Liya