Capturing Signatures with Signature Pad

#44 Capturing Signatures with Signature Pad
8/28/2016

Summary

Using the Javascript Library, Signature Pad, learn how to capture user signatures and store them within your Ruby on Rails application.
5
rails javascript view 8:14 min

Summary

application.js.erb//= require signature_pad
signature.jsfunction resizeCanvas(canvas) {
    var ratio =  Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext("2d").scale(ratio, ratio);
}

$(document).on('turbolinks:load', function() {
  var canvas = document.querySelector("canvas");
  if (canvas){
    canvas.height = canvas.offsetHeight;
    canvas.width = canvas.offsetWidth;
    window.onresize = resizeCanvas(canvas);
    resizeCanvas(canvas);
    signature_pad = new SignaturePad(canvas);
    $('.signature_pad_clear').click(function() { signature_pad.clear() });
    $('.signature_pad_save').click(function(event) { 
      if (signature_pad.isEmpty()){
        alert('You must sign to accept the Terms and Conditions');
        event.preventDefault();
      } else {
        $('.signature_pad_input').val(signature_pad.toDataURL());
      }
    });
  }
});
application.css.signature_pad {
  width: 700px;
  height: 400px;
  margin: 0 auto;
}

.signature_pad_body canvas {
  width: 100%;
  height: 100%;
  border: dotted #444;
  background: #CCCCCC;
}
application_controller.rbclass ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :verify_terms_acceptance 

  private

  def verify_terms_acceptance
    unless user_signed_in? && current_user.document
      redirect_to new_document_path, alert: 'You must first accept terms and conditions before performing any actions.'
    end
  end
end
documents_controller.rbclass DocumentsController < ApplicationController
  before_action :authenticate_user!
  skip_before_action :verify_terms_acceptance

  def new
    @document = current_user.build_document
  end

  def create
    @document = current_user.build_document(document_params)
    @document.signed_on = DateTime.now
    if @document.save
      redirect_to root_url, notice: 'Terms and Conditions accepted.'
    else
      render :new
    end
  end

  private

    def document_params
      params.require(:document).permit(:signature)
    end
end

On controllers and/or specific actions which should not require the user to accept the Terms and Conditions, make sure that you add

controllerskip_before_action :verify_terms_acceptance

Adding this override should also apply to the authentication controllers.

documents/new.html.erb

<%= simple_form_for @document do |f| %>   <%= f.input_field :signature, as: :hidden, class: 'signature_pad_input' %>   <div class="signature_pad text-center">     <div class="signature_pad_body">       <canvas></canvas>     </div>     <div class="signature_pad_footer">       <div class="text-muted">Sign above</div>       <button type="button" class="btn btn-default signature_pad_clear">Clear</button>       <%= f.button :submit, 'Save', class: 'btn btn-success signature_pad_save'  %>     </div>   </div> <% end %>

visitors/private_content.html.erb<%= image_tag current_user.document.signature %>


8632141?v=3&s=64
RailsCod3rFuture said 7 months ago:

Greetings, I enjoyed watching your tutorial on signature pad. What I was wondering is how do you convert the signature into a PNG and store it alongside the form? I found some code below, but I was wondering if you had a better solution that I can use or is this good enough? Since I am running a SaaS company, I need the optimal way of implementing this feature. If possible, can you post the solution in the comments? Thank you

Controller File

@yourmodel.signature = tempfileend
  input.puts instructions
Open3.popen3("convert -size 600x100 xc:transparent -stroke blue -draw @- #{tempfile.path}") do |input, output, error|
tempfile = Tempfile.new(["signature", '.png'])
instructions = JSON.parse(params[:output]).map { |h| "line #{h['mx'].to_i},#{h['my'].to_i} #{h['lx'].to_i},#{h['ly'].to_i}" } * ' '

Carrierwave

rails generate uploader Signature

mount_uploader :signature, SignatureUploader


635114?v=3&s=64
kobaltz said 6 months ago:

It really depends on the situation. I wouldn't necessarily jump to converting the signature over to an image and store it separately (more so than it already is). If you will be displaying the signature often, you could look into Fragment Caching as a possible solution for the areas where you're displaying the image. Converting and storing the signature as an image seems like unnecessary overhead as well as an added complication.

However, if this is the route you need, you could create an attr_accessor for the signature and convert it to an image and upload it like you're describing.

00000000000000000000000000000000?d=mm&f=y&s=64
frank004 said 2 months ago:

Will love to see a converting signature and  store it like a img

Login to Comment