diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..2043af1a --- /dev/null +++ b/.jshintrc @@ -0,0 +1,3 @@ +{ + "laxbreak": true +} diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000..7bbe0688 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,43 @@ +/*jslint node: true */ + +'use strict'; + +module.exports = function(grunt) { + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: [ + 'Gruntfile.js', + 'signature_pad.js' + ] + }, + + uglify: { + options: { + banner: "/*!\n" + + " * Signature Pad v<%= pkg.version %> | <%= pkg.homepage %>\n" + + " * (c) 2013 Szymon Nowak | Released under the MIT license\n" + + " */\n" + }, + build: { + files: { + 'signature_pad.min.js': [ + 'signature_pad.js' + ] + } + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + + grunt.registerTask('default', [ + 'jshint', + 'uglify' + ]); +}; diff --git a/package.json b/package.json new file mode 100644 index 00000000..bb34488d --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "signature_pad", + "description": "Library for drawing smooth signatures.", + "version": "1.0.0", + "homepage": "https://github.com/szimek/signature_pad", + "author": { + "name": "Szymon Nowak", + "url": "https://github.com/szimek" + }, + "repository" : { + "type" : "git", + "url" : "https://github.com/szimek/signature_pad.git" + }, + "licenses": [{ + "type": "MIT" + }], + "devDependencies": { + "grunt": "~0.4.1", + "grunt-contrib-jshint": "~0.6.3", + "grunt-contrib-uglify": "~0.2.2" + } +} diff --git a/signature_pad.js b/signature_pad.js index efa5b359..1495d48e 100644 --- a/signature_pad.js +++ b/signature_pad.js @@ -1,19 +1,23 @@ -// Signature Pad -// https://github.com/szimek/signature_pad -// -// Copyright 2013 Szymon Nowak -// Released under the MIT license -// -// The main idea and some parts of the code (e.g. drawing variable width Bézier curve) are taken from: -// http://corner.squareup.com/2012/07/smoother-signatures.html -// -// Implementation of interpolation using cubic Bézier curves is taken from: -// http://benknowscode.wordpress.com/2012/09/14/path-interpolation-using-cubic-bezier-and-control-point-estimation-in-javascript -// -// Algorithm for approximated length of a Bézier curve is taken from: -// http://www.lemoda.net/maths/bezier-length/index.html -// +/*! + * Signature Pad v1.0.0 + * https://github.com/szimek/signature_pad + * + * Copyright 2013 Szymon Nowak + * Released under the MIT license + * + * The main idea and some parts of the code (e.g. drawing variable width Bézier curve) are taken from: + * http://corner.squareup.com/2012/07/smoother-signatures.html + * + * Implementation of interpolation using cubic Bézier curves is taken from: + * http://benknowscode.wordpress.com/2012/09/14/path-interpolation-using-cubic-bezier-and-control-point-estimation-in-javascript + * + * Algorithm for approximated length of a Bézier curve is taken from: + * http://www.lemoda.net/maths/bezier-length/index.html + * + */ var SignaturePad = (function (document) { + "use strict"; + var SignaturePad = function (canvas, options) { var self = this, opts = options || {}; diff --git a/signature_pad.min.js b/signature_pad.min.js new file mode 100644 index 00000000..1a028452 --- /dev/null +++ b/signature_pad.min.js @@ -0,0 +1,5 @@ +/*! + * Signature Pad v1.0.0 | https://github.com/szimek/signature_pad + * (c) 2013 Szymon Nowak | Released under the MIT license + */ +var SignaturePad=function(a){"use strict";var b=function(b,c){var d=this,e=c||{};this.velocityFilterWeight=e.velocityFilterWeight||.7,this.minWidth=e.minWidth||.5,this.maxWidth=e.maxWidth||2.5,this.color=e.color||"black",this._canvas=b,this._ctx=b.getContext("2d"),this._reset(),this._mouseButtonDown=!1,b.addEventListener("mousedown",function(a){if(1===a.which){d._mouseButtonDown=!0,d._reset();var b=d._createPoint(a);d._addPoint(b)}}),b.addEventListener("mousemove",function(a){if(d._mouseButtonDown){var b=d._createPoint(a);d._addPoint(b)}}),a.addEventListener("mouseup",function(a){if(1===a.which&&d._mouseButtonDown){d._mouseButtonDown=!1;var b=d.points.length>2,c=d.points[0],e=d._ctx;!b&&c&&(e.beginPath(),d._drawPoint(c.x,c.y,2),e.closePath(),e.fill())}}),b.addEventListener("touchstart",function(a){d._reset();var b=a.changedTouches[0],c=d._createPoint(b);d._addPoint(c)}),b.addEventListener("touchmove",function(a){a.preventDefault();var b=a.changedTouches[0],c=d._createPoint(b);d._addPoint(c)}),a.addEventListener("touchend",function(a){var b=a.target===d._canvas,c=d.points.length>2,e=d.points[0],f=d._ctx;b&&!c&&e&&(f.beginPath(),d._drawPoint(e.x,e.y,2),f.closePath(),f.fill())})};b.prototype.clear=function(){this._ctx.clearRect(0,0,this._canvas.width,this._canvas.height),this._reset()},b.prototype.toDataURL=function(){return this._canvas.toDataURL(arguments)},b.prototype.fromDataURL=function(a){var b=new Image;b.src=a,this._ctx.drawImage(b,0,0,this._canvas.width,this._canvas.height)},b.prototype.isEmpty=function(){return this._isEmpty},b.prototype._reset=function(){this.points=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._isEmpty=!0,this._ctx.fillStyle=this.color},b.prototype._createPoint=function(a){var b=this._canvas.getBoundingClientRect();return new c(a.clientX-b.left,a.clientY-b.top)},b.prototype._addPoint=function(a){var b,c,e,f,g=this.points;g.push(a),g.length>2&&(3===g.length&&g.unshift(g[0]),f=this._calculateCurveControlPoints(g[0],g[1],g[2]),b=f.c2,f=this._calculateCurveControlPoints(g[1],g[2],g[3]),c=f.c1,e=new d(g[1],b,c,g[2]),this._addCurve(e),g.shift())},b.prototype._calculateCurveControlPoints=function(a,b,d){var e=a.x-b.x,f=a.y-b.y,g=b.x-d.x,h=b.y-d.y,i={x:(a.x+b.x)/2,y:(a.y+b.y)/2},j={x:(b.x+d.x)/2,y:(b.y+d.y)/2},k=Math.sqrt(e*e+f*f),l=Math.sqrt(g*g+h*h),m=i.x-j.x,n=i.y-j.y,o=l/(k+l),p={x:j.x+m*o,y:j.y+n*o},q=b.x-p.x,r=b.y-p.y;return{c1:new c(i.x+q,i.y+r),c2:new c(j.x+q,j.y+r)}},b.prototype._addCurve=function(a){var b,c,d=a.startPoint,e=a.endPoint;b=e.velocityFrom(d),b=this.velocityFilterWeight*b+(1-this.velocityFilterWeight)*this._lastVelocity,c=this._strokeWidth(b),this._drawCurve(a,this._lastWidth,c),this._lastVelocity=b,this._lastWidth=c},b.prototype._drawPoint=function(a,b,c){var d=this._ctx;d.moveTo(a,b),d.arc(a,b,c,0,2*Math.PI,!1),this._isEmpty=!1},b.prototype._drawCurve=function(a,b,c){var d,e,f,g,h,i,j,k,l,m,n,o=this._ctx,p=c-b;for(d=Math.floor(a.length()),o.beginPath(),f=0;d>f;f++)g=f/d,h=g*g,i=h*g,j=1-g,k=j*j,l=k*j,m=l*a.startPoint.x,m+=3*k*g*a.control1.x,m+=3*j*h*a.control2.x,m+=i*a.endPoint.x,n=l*a.startPoint.y,n+=3*k*g*a.control1.y,n+=3*j*h*a.control2.y,n+=i*a.endPoint.y,e=b+i*p,this._drawPoint(m,n,e);o.closePath(),o.fill()},b.prototype._strokeWidth=function(a){return Math.max(this.maxWidth/(a+1),this.minWidth)};var c=function(a,b,c){this.x=a,this.y=b,this.time=c||(new Date).getTime()};c.prototype.velocityFrom=function(a){return this.distanceTo(a)/(this.time-a.time)},c.prototype.distanceTo=function(a){return Math.sqrt(Math.pow(this.x-a.x,2)+Math.pow(this.y-a.y,2))};var d=function(a,b,c,d){this.startPoint=a,this.control1=b,this.control2=c,this.endPoint=d};return d.prototype.length=function(){var a,b,c,d,e,f,g,h,i=10,j=0;for(a=0;i>=a;a++)b=a/i,c=this._point(b,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),d=this._point(b,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y),a>0&&(g=c-e,h=d-f,j+=Math.sqrt(g*g+h*h)),e=c,f=d;return j},d.prototype._point=function(a,b,c,d,e){return b*(1-a)*(1-a)*(1-a)+3*c*(1-a)*(1-a)*a+3*d*(1-a)*a*a+e*a*a*a},b}(document); \ No newline at end of file