master
liuxinxin 5 years ago
parent 954dd83acf
commit cbcc7f1f07

@ -0,0 +1,234 @@
/** @preserve
jSignature v2 jSignature's custom "base30" format export and import plugins.
*/
/**
Copyright (c) 2011 Willow Systems Corp http://willow-systems.com
MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
;(function(){
var chunkSeparator = '_'
, charmap = {} // {'1':'g','2':'h','3':'i','4':'j','5':'k','6':'l','7':'m','8':'n','9':'o','a':'p','b':'q','c':'r','d':'s','e':'t','f':'u','0':'v'}
, charmap_reverse = {} // will be filled by 'uncompress*" function
// need to split below for IE7 (possibly others), which does not understand string[position] it seems (returns undefined)
, allchars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX'.split('')
, bitness = allchars.length / 2
, minus = 'Z'
, plus = 'Y'
for(var i = bitness-1; i > -1; i--){
charmap[allchars[i]] = allchars[i+bitness]
charmap_reverse[allchars[i+bitness]] = allchars[i]
}
var remapTailChars = function(number){
// for any given number as string, returning string with trailing chars remapped something like so:
// '345' -> '3de'
var chars = number.split('')
, l = chars.length
// we are skipping first char. standard hex number char = delimiter
for (var i = 1; i < l; i++ ){
chars[i] = charmap[chars[i]]
}
return chars.join('')
}
, compressstrokeleg = function(data){
// we convert half-stroke (only 'x' series or only 'y' series of numbers)
// data is like this:
// [517,516,514,513,513,513,514,516,519,524,529,537,541,543,544,544,539,536]
// that is converted into this:
// "5agm12100p1235584210m53"
// each number in the chain is converted such:
// - find diff from previous number
// - first significant digit is kept as digit char. digit char = start of new number.
// - consecutive numbers are mapped to letters, where 1 to 9 are A to I, 0 is O
// Sign changes are denoted by "P" - plus, "M" for minus.
var answer = []
, lastwhole = 0
, last = 0
, lastpolarity = 1
, l = data.length
, nwhole, n, absn
for(var i = 0; i < l; i++){
// we start with whole coordinates for each point
// coords are converted into series of vectors:
// [512, 514, 520]
// [512, +2, +6]
nwhole = Math.round(data[i])
n = nwhole - lastwhole
lastwhole = nwhole
// inserting sign change when needed.
if (n < 0 && lastpolarity > 0) {
lastpolarity = -1
answer.push(minus)
}
else if (n > 0 && lastpolarity < 0) {
lastpolarity = 1
answer.push(plus)
}
// since we have dealt with sign. let's absolute the value.
absn = Math.abs(n)
// adding number to list We convert these to Hex before storing on the string.
if (absn >= bitness) {
answer.push(remapTailChars(absn.toString(bitness)))
} else {
answer.push(absn.toString(bitness))
}
}
return answer.join('')
}
, uncompressstrokeleg = function(datastring){
// we convert half-stroke (only 'x' series or only 'y' series of numbers)
// datastring like this:
// "5agm12100p1235584210m53"
// is converted into this:
// [517,516,514,513,513,513,514,516,519,524,529,537,541,543,544,544,539,536]
// each number in the chain is converted such:
// - digit char = start of new whole number. Alpha chars except "p","m" are numbers in hiding.
// These consecutive digist expressed as alphas mapped back to digit char.
// resurrected number is the diff between this point and prior coord.
// - running polaritiy is attached to the number.
// - we undiff (signed number + prior coord) the number.
// - if char 'm','p', flip running polarity
var answer = []
, chars = datastring.split('')
, l = chars.length
, ch
, polarity = 1
, partial = []
, preprewhole = 0
, prewhole
for(var i = 0; i < l; i++){
ch = chars[i]
if (ch in charmap || ch === minus || ch === plus){
// this is new number - start of a new whole number.
// before we can deal with it, we need to flush out what we already
// parsed out from string, but keep in limbo, waiting for this sign
// that prior number is done.
// we deal with 3 numbers here:
// 1. start of this number - a diff from previous number to
// whole, new number, which we cannot do anything with cause
// we don't know its ending yet.
// 2. number that we now realize have just finished parsing = prewhole
// 3. number we keep around that came before prewhole = preprewhole
if (partial.length !== 0) {
// yep, we have some number parts in there.
prewhole = parseInt( partial.join(''), bitness) * polarity + preprewhole
answer.push( prewhole )
preprewhole = prewhole
}
if (ch === minus){
polarity = -1
partial = []
} else if (ch === plus){
polarity = 1
partial = []
} else {
// now, let's start collecting parts for the new number:
partial = [ch]
}
} else /* alphas replacing digits */ {
// more parts for the new number
partial.push(charmap_reverse[ch])
}
}
// we always will have something stuck in partial
// because we don't have closing delimiter
answer.push( parseInt( partial.join(''), bitness ) * polarity + preprewhole )
return answer
}
, compressstrokes = function(data){
var answer = []
, l = data.length
, stroke
for(var i = 0; i < l; i++){
stroke = data[i]
answer.push(compressstrokeleg(stroke.x))
answer.push(compressstrokeleg(stroke.y))
}
return answer.join(chunkSeparator)
}
, uncompressstrokes = function(datastring){
var data = []
, chunks = datastring.split(chunkSeparator)
, l = chunks.length / 2
for (var i = 0; i < l; i++){
data.push({
'x':uncompressstrokeleg(chunks[i*2])
, 'y':uncompressstrokeleg(chunks[i*2+1])
})
}
return data
}
, acceptedformat = 'image/jsignature;base30'
, pluginCompressor = function(data){
return [acceptedformat , compressstrokes(data)]
}
, pluginDecompressor = function(data, formattype, importcallable){
if (typeof data !== 'string') return
if (data.substring(0, acceptedformat.length).toLowerCase() === acceptedformat) {
data = data.substring(acceptedformat.length + 1) // chopping off "," there
}
importcallable( uncompressstrokes(data) )
}
, Initializer = function($){
var mothership = $.fn['jSignature']
mothership(
'addPlugin'
,'export'
,'base30' // alias
,pluginCompressor
)
mothership(
'addPlugin'
,'export'
,acceptedformat // full name
,pluginCompressor
)
mothership(
'addPlugin'
,'import'
,'base30' // alias
,pluginDecompressor
)
mothership(
'addPlugin'
,'import'
,acceptedformat // full name
,pluginDecompressor
)
}
// //Because plugins are minified together with jSignature, multiple defines per (minified) file blow up and dont make sense
// //Need to revisit this later.
// if ( typeof define === "function" && define.amd != null) {
// // AMD-loader compatible resource declaration
// // you need to call this one with jQuery as argument.
// define(function(){return Initializer} )
// } else {
// global-polluting outcome.
if(this.jQuery == null) {throw new Error("We need jQuery for some of the functionality. jQuery is not detected. Failing to initialize...")}
Initializer(this.jQuery)
// }
if (this.jSignatureDebug) {
this.jSignatureDebug['base30'] = {
'remapTailChars':remapTailChars
, 'compressstrokeleg':compressstrokeleg
, 'uncompressstrokeleg':uncompressstrokeleg
, 'compressstrokes':compressstrokes
, 'uncompressstrokes':uncompressstrokes
, 'charmap': charmap
}
}
}).call(typeof window !== 'undefined'? window : this);

@ -0,0 +1,519 @@
/** @license
jSignature v2 SVG export plugin.
*/
/**
Copyright (c) 2012 Willow Systems Corp http://willow-systems.com
MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
;(function(){
'use strict'
/** @preserve
Simplify.js BSD
(c) 2012, Vladimir Agafonkin
mourner.github.com/simplify-js
*/
;(function(a,b){function c(a,b){var c=a.x-b.x,d=a.y-b.y;return c*c+d*d}function d(a,b,c){var d=b.x,e=b.y,f=c.x-d,g=c.y-e,h;if(f!==0||g!==0)h=((a.x-d)*f+(a.y-e)*g)/(f*f+g*g),h>1?(d=c.x,e=c.y):h>0&&(d+=f*h,e+=g*h);return f=a.x-d,g=a.y-e,f*f+g*g}function e(a,b){var d,e=a.length,f,g=a[0],h=[g];for(d=1;d<e;d++)f=a[d],c(f,g)>b&&(h.push(f),g=f);return g!==f&&h.push(f),h}function f(a,c){var e=a.length,f=typeof Uint8Array!=b+""?Uint8Array:Array,g=new f(e),h=0,i=e-1,j,k,l,m,n=[],o=[],p=[];g[h]=g[i]=1;while(i){k=0;for(j=h+1;j<i;j++)l=d(a[j],a[h],a[i]),l>k&&(m=j,k=l);k>c&&(g[m]=1,n.push(h),o.push(m),n.push(m),o.push(i)),h=n.pop(),i=o.pop()}for(j=0;j<e;j++)g[j]&&p.push(a[j]);return p}"use strict";var g=a;g.simplify=function(a,c,d){var g=c!==b?c*c:1;return d||(a=e(a,g)),a=f(a,g),a}})(window);
/**
Vector class. Allows us to simplify representation and manipulation of coordinate-pair
representing shift against (0, 0)
@public
@class
@param
@returns {Type}
*/
function Vector(x,y){
this.x = x
this.y = y
this.reverse = function(){
return new this.constructor(
this.x * -1
, this.y * -1
)
}
this._length = null
this.getLength = function(){
if (!this._length){
this._length = Math.sqrt( Math.pow(this.x, 2) + Math.pow(this.y, 2) )
}
return this._length
}
var polarity = function (e){
return Math.round(e / Math.abs(e))
}
this.resizeTo = function(length){
// proportionally changes x,y such that the hypotenuse (vector length) is = new length
if (this.x === 0 && this.y === 0){
this._length = 0
} else if (this.x === 0){
this._length = length
this.y = length * polarity(this.y)
} else if(this.y === 0){
this._length = length
this.x = length * polarity(this.x)
} else {
var proportion = Math.abs(this.y / this.x)
, x = Math.sqrt(Math.pow(length, 2) / (1 + Math.pow(proportion, 2)))
, y = proportion * x
this._length = length
this.x = x * polarity(this.x)
this.y = y * polarity(this.y)
}
return this
}
/**
* Calculates the angle between 'this' vector and another.
* @public
* @function
* @returns {Number} The angle between the two vectors as measured in PI.
*/
this.angleTo = function(vectorB) {
var divisor = this.getLength() * vectorB.getLength()
if (divisor === 0) {
return 0
} else {
// JavaScript floating point math is screwed up.
// because of it, the core of the formula can, on occasion, have values
// over 1.0 and below -1.0.
return Math.acos(
Math.min(
Math.max(
( this.x * vectorB.x + this.y * vectorB.y ) / divisor
, -1.0
)
, 1.0
)
) / Math.PI
}
}
}
function Point(x,y){
this.x = x
this.y = y
this.getVectorToCoordinates = function (x, y) {
return new Vector(x - this.x, y - this.y)
}
this.getVectorFromCoordinates = function (x, y) {
return this.getVectorToCoordinates(x, y).reverse()
}
this.getVectorToPoint = function (point) {
return new Vector(point.x - this.x, point.y - this.y)
}
this.getVectorFromPoint = function (point) {
return this.getVectorToPoint(point).reverse()
}
}
/**
Allows one to round a number to arbitrary precision.
Math.round() rounds to whole only.
Number.toFixed(precision) returns a string.
I need float to float, but with arbitrary precision, hence:
@public
@function
@param number {Number}
@param position {Number} number of digits right of decimal point to keep. If negative, rounding to the left of decimal.
@returns {Type}
*/
function round (number, position){
var tmp = Math.pow(10, position)
return Math.round( number * tmp ) / tmp
}
// /**
// * This is a simple, points-to-lines (not curves) renderer.
// * Keeping it around so we can activate it from time to time and see
// * if smoothing logic is off much.
// * @public
// * @function
// * @returns {String} Like so "l 1 2 3 5' with stroke as long line chain.
// */
// function compressstroke(stroke, shiftx, shifty){
// // we combine strokes data into string like this:
// // 'M 53 7 l 1 2 3 4 -5 -6 5 -6'
// // see SVG documentation for Path element's 'd' argument.
// var lastx = stroke.x[0]
// , lasty = stroke.y[0]
// , i
// , l = stroke.x.length
// , answer = ['M', lastx - shiftx, lasty - shifty, 'l']
//
// if (l === 1){
// // meaning this was just a DOT, not a stroke.
// // instead of creating a circle, we just create a short line
// answer.concat(1, -1)
// } else {
// for(i = 1; i < l; i++){
// answer = answer.concat(stroke.x[i] - lastx, stroke.y[i] - lasty)
// lastx = stroke.x[i]
// lasty = stroke.y[i]
// }
// }
// return answer.join(' ')
// }
function segmentToCurve(stroke, positionInStroke, lineCurveThreshold){
'use strict'
// long lines (ones with many pixels between them) do not look good when they are part of a large curvy stroke.
// You know, the jaggedy crocodile spine instead of a pretty, smooth curve. Yuck!
// We want to approximate pretty curves in-place of those ugly lines.
// To approximate a very nice curve we need to know the direction of line before and after.
// Hence, on long lines we actually wait for another point beyond it to come back from
// mousemoved before we draw this curve.
// So for "prior curve" to be calc'ed we need 4 points
// A, B, C, D (we are on D now, A is 3 points in the past.)
// and 3 lines:
// pre-line (from points A to B),
// this line (from points B to C), (we call it "this" because if it was not yet, it's the only one we can draw for sure.)
// post-line (from points C to D) (even through D point is 'current' we don't know how we can draw it yet)
//
// Well, actually, we don't need to *know* the point A, just the vector A->B
// Again, we can only derive curve between points positionInStroke-1 and positionInStroke
// Thus, since we can only draw a line if we know one point ahead of it, we need to shift our focus one point ahead.
positionInStroke += 1
// Let's hope the code that calls us knows we do that and does not call us with positionInStroke = index of last point.
var Cpoint = new Point(stroke.x[positionInStroke-1], stroke.y[positionInStroke-1])
, Dpoint = new Point(stroke.x[positionInStroke], stroke.y[positionInStroke])
, CDvector = Cpoint.getVectorToPoint(Dpoint)
// Again, we have a chance here to draw only PREVIOUS line segment - BC
// So, let's start with BC curve.
// if there is only 2 points in stroke array (C, D), we don't have "history" long enough to have point B, let alone point A.
// so positionInStroke should start with 2, ie
// we are here when there are at least 3 points in stroke array.
var Bpoint = new Point(stroke.x[positionInStroke-2], stroke.y[positionInStroke-2])
, BCvector = Bpoint.getVectorToPoint(Cpoint)
, ABvector
, rounding = 2
if ( BCvector.getLength() > lineCurveThreshold ){
// Yey! Pretty curves, here we come!
if(positionInStroke > 2) {
ABvector = (new Point(stroke.x[positionInStroke-3], stroke.y[positionInStroke-3])).getVectorToPoint(Bpoint)
} else {
ABvector = new Vector(0,0)
}
var minlenfraction = 0.05
, maxlen = BCvector.getLength() * 0.35
, ABCangle = BCvector.angleTo(ABvector.reverse())
, BCDangle = CDvector.angleTo(BCvector.reverse())
, BtoCP1vector = new Vector(ABvector.x + BCvector.x, ABvector.y + BCvector.y).resizeTo(
Math.max(minlenfraction, ABCangle) * maxlen
)
, CtoCP2vector = (new Vector(BCvector.x + CDvector.x, BCvector.y + CDvector.y)).reverse().resizeTo(
Math.max(minlenfraction, BCDangle) * maxlen
)
, BtoCP2vector = new Vector(BCvector.x + CtoCP2vector.x, BCvector.y + CtoCP2vector.y)
// returing curve for BC segment
// all coords are vectors against Bpoint
return [
'c' // bezier curve
, round( BtoCP1vector.x, rounding )
, round( BtoCP1vector.y, rounding )
, round( BtoCP2vector.x, rounding )
, round( BtoCP2vector.y, rounding )
, round( BCvector.x, rounding )
, round( BCvector.y, rounding )
]
} else {
return [
'l' // line
, round( BCvector.x, rounding )
, round( BCvector.y, rounding )
]
}
}
function lastSegmentToCurve(stroke, lineCurveThreshold){
'use strict'
// Here we tidy up things left unfinished
// What's left unfinished there is the curve between the last points
// in the stroke
// We can also be called when there is only one point in the stroke (meaning, the
// stroke was just a dot), in which case there is nothing for us to do.
// So for "this curve" to be calc'ed we need 3 points
// A, B, C
// and 2 lines:
// pre-line (from points A to B),
// this line (from points B to C)
// Well, actually, we don't need to *know* the point A, just the vector A->B
// so, we really need points B, C and AB vector.
var positionInStroke = stroke.x.length - 1
// there must be at least 2 points in the stroke.for us to work. Hope calling code checks for that.
var Cpoint = new Point(stroke.x[positionInStroke], stroke.y[positionInStroke])
, Bpoint = new Point(stroke.x[positionInStroke-1], stroke.y[positionInStroke-1])
, BCvector = Bpoint.getVectorToPoint(Cpoint)
, rounding = 2
if (positionInStroke > 1 && BCvector.getLength() > lineCurveThreshold){
// we have at least 3 elems in stroke
var ABvector = (new Point(stroke.x[positionInStroke-2], stroke.y[positionInStroke-2])).getVectorToPoint(Bpoint)
, ABCangle = BCvector.angleTo(ABvector.reverse())
, minlenfraction = 0.05
, maxlen = BCvector.getLength() * 0.35
, BtoCP1vector = new Vector(ABvector.x + BCvector.x, ABvector.y + BCvector.y).resizeTo(
Math.max(minlenfraction, ABCangle) * maxlen
)
return [
'c' // bezier curve
, round( BtoCP1vector.x, rounding )
, round( BtoCP1vector.y, rounding )
, round( BCvector.x, rounding ) // CP2 is same as Cpoint
, round( BCvector.y, rounding ) // CP2 is same as Cpoint
, round( BCvector.x, rounding )
, round( BCvector.y, rounding )
]
} else {
// Since there is no AB leg, there is no curve to draw. This is just line
return [
'l' // simple line
, round( BCvector.x, rounding )
, round( BCvector.y, rounding )
]
}
}
function addstroke(stroke, shiftx, shifty){
'use strict'
// we combine strokes data into string like this:
// 'M 53 7 l 1 2 c 3 4 -5 -6 5 -6'
// see SVG documentation for Path element's 'd' argument.
var lines = [
'M' // move to
, round( (stroke.x[0] - shiftx), 2)
, round( (stroke.y[0] - shifty), 2)
]
// processing all points but first and last.
, i = 1 // index zero item in there is STARTING point. we already extracted it.
, l = stroke.x.length - 1 // this is a trick. We are leaving last point coordinates for separate processing.
, lineCurveThreshold = 1
for(; i < l; i++){
lines.push.apply(lines, segmentToCurve(stroke, i, lineCurveThreshold))
}
if (l > 0 /* effectively more than 1, since we "-1" above */){
lines.push.apply(lines, lastSegmentToCurve(stroke, i, lineCurveThreshold))
} else if (l === 0){
// meaning we only have ONE point in the stroke (and otherwise refer to the stroke as "dot")
lines.push.apply(lines, ['l' , 1, 1])
}
return lines.join(' ')
}
function simplifystroke(stroke){
var d = []
, newstroke = {'x':[], 'y':[]}
, i, l
for (i = 0, l = stroke.x.length; i < l; i++){
d.push({'x':stroke.x[i], 'y':stroke.y[i]})
}
d = simplify(d, 0.7, true)
for (i = 0, l = d.length; i < l; i++){
newstroke.x.push(d[i].x)
newstroke.y.push(d[i].y)
}
return newstroke
}
// generate SVG style from settings
function styleFromSettings(settings){
var styles = [];
var meta = [
// ["style attr", "key in settings", "default value"]
["fill", undefined, "none"],
["stroke", "color", "#000000"],
["stroke-width", "lineWidth", 2],
["stroke-linecap", undefined, "round"],
["stroke-linejoin", undefined, "round"]
];
for (var i = meta.length - 1; i >= 0; i--){
var attr = meta[i][0]
, key = meta[i][1]
, defaultVal = meta[i][2];
styles.push(attr + '="' + (key in settings && settings[key] ? settings[key] : defaultVal) + '"');
}
return styles.join(' ');
}
function compressstrokes(data, settings){
'use strict'
var answer = [
'<?xml version="1.0" encoding="UTF-8" standalone="no"?>'
, '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'
]
, i , l = data.length
, stroke
, xlimits = []
, ylimits = []
, sizex = 0
, sizey = 0
, shiftx = 0
, shifty = 0
, minx, maxx, miny, maxy, padding = 1
, simplifieddata = []
if(l !== 0){
for(i = 0; i < l; i++){
stroke = simplifystroke( data[i] )
simplifieddata.push(stroke)
xlimits = xlimits.concat(stroke.x)
ylimits = ylimits.concat(stroke.y)
}
minx = Math.min.apply(null, xlimits) - padding
maxx = Math.max.apply(null, xlimits) + padding
miny = Math.min.apply(null, ylimits) - padding
maxy = Math.max.apply(null, ylimits) + padding
shiftx = minx < 0? 0 : minx
shifty = miny < 0? 0 : miny
sizex = maxx - minx
sizey = maxy - miny
}
answer.push(
'<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="'+
sizex.toString() +
'" height="'+
sizey.toString() +
'">'
)
// // This is a nice idea: use style declaration on top, and mark the lines with 'class="f"'
// // thus saving space in svg...
// // alas, many SVG renderers don't understand "class" and render the strokes in default "fill = black, no stroke" style. Ugh!!!
// // TODO: Rewrite ImageMagic / GraphicsMagic, InkScape, http://svg.codeplex.com/ to support style + class. until then, we hardcode the stroke style within the path.
// answer.push(
// '<style type="text/css"><![CDATA[.f {fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}]]></style>'
// )
// // This set is accompaniment to "simple line renderer" - compressstroke
// answer.push(
// '<style type="text/css"><![CDATA[.t {fill:none;stroke:#FF0000;stroke-width:2}]]></style>'
// )
// for(i = 0; i < l; i++){
// stroke = data[i]
// // This one is accompaniment to "simple line renderer"
// answer.push('<path class="t" d="'+ compressstroke(stroke, shiftx, shifty) +'"/>')
// }
for(i = 0, l = simplifieddata.length; i < l; i++){
stroke = simplifieddata[i]
answer.push('<path ' + styleFromSettings(settings) + ' d="'+ addstroke(stroke, shiftx, shifty) + '"/>')
}
answer.push('</svg>')
return answer.join('')
}
if (typeof btoa !== 'function')
{
var btoa = function(data) {
/** @preserve
base64 encoder
MIT, GPL
http://phpjs.org/functions/base64_encode
+ original by: Tyler Akins (http://rumkin.com)
+ improved by: Bayron Guevara
+ improved by: Thunder.m
+ improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ bugfixed by: Pellentesque Malesuada
+ improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ improved by: Rafal Kukawski (http://kukawski.pl)
*/
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
, b64a = b64.split('')
, o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
ac = 0,
enc = "",
tmp_arr = [];
do { // pack three octets into four hexets
o1 = data.charCodeAt(i++);
o2 = data.charCodeAt(i++);
o3 = data.charCodeAt(i++);
bits = o1 << 16 | o2 << 8 | o3;
h1 = bits >> 18 & 0x3f;
h2 = bits >> 12 & 0x3f;
h3 = bits >> 6 & 0x3f;
h4 = bits & 0x3f;
// use hexets to index into b64, and append result to encoded string
tmp_arr[ac++] = b64a[h1] + b64a[h2] + b64a[h3] + b64a[h4];
} while (i < data.length);
enc = tmp_arr.join('');
var r = data.length % 3;
return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
// end of base64 encoder MIT, GPL
}
}
var unencodedmime = 'image/svg+xml'
function getUnencodedSVG(data, settings){
return [unencodedmime , compressstrokes(data, settings)];
}
var base64encodedmime = 'image/svg+xml;base64'
function getBase64encodedSVG(data, settings){
return [base64encodedmime , btoa( compressstrokes(data, settings) )];
}
function Initializer($){
var mothership = $.fn['jSignature']
mothership(
'addPlugin'
,'export'
,'svg' // alias
,getUnencodedSVG
)
mothership(
'addPlugin'
,'export'
,unencodedmime // full name
,getUnencodedSVG
)
mothership(
'addPlugin'
,'export'
,'svgbase64' // alias
,getBase64encodedSVG
)
mothership(
'addPlugin'
,'export'
,base64encodedmime // full name
,getBase64encodedSVG
)
}
// //Because plugins are minified together with jSignature, multiple defines per (minified) file blow up and dont make sense
// //Need to revisit this later.
if(typeof $ === 'undefined') {throw new Error("We need jQuery for some of the functionality. jQuery is not detected. Failing to initialize...")}
Initializer($)
})();

File diff suppressed because one or more lines are too long

@ -0,0 +1,165 @@
/** @license
jSignature v2 jSignature's Undo Button and undo functionality plugin
*/
/**
Copyright (c) 2011 Willow Systems Corp http://willow-systems.com
MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
;(function(){
var apinamespace = 'jSignature'
function attachHandlers(buttonRenderer, apinamespace, extensionName) {
var $undoButton = buttonRenderer.call(this)
;(function(jSignatureInstance, $undoButton, apinamespace) {
jSignatureInstance.events.subscribe(
apinamespace + '.change'
, function(){
if (jSignatureInstance.dataEngine.data.length) {
$undoButton.show()
} else {
$undoButton.hide()
}
}
)
})( this, $undoButton, apinamespace )
;(function(jSignatureInstance, $undoButton, apinamespace) {
var eventName = apinamespace + '.undo'
$undoButton.bind('click', function(){
jSignatureInstance.events.publish(eventName)
})
// This one creates new "undo" event listener to jSignature instance
// It handles the actual undo-ing.
jSignatureInstance.events.subscribe(
eventName
, function(){
var data = jSignatureInstance.dataEngine.data
if (data.length) {
data.pop()
jSignatureInstance.resetCanvas(data)
}
}
)
})(
this
, $undoButton
, this.events.topics.hasOwnProperty( apinamespace + '.undo' ) ?
// oops, seems some other plugin or code has already claimed "jSignature.undo" event
// we will use this extension's name for event name prefix
extensionName :
// Great! we will use 'jSignature' for event name prefix.
apinamespace
)
}
function ExtensionInitializer(extensionName){
// we are called very early in instance's life.
// right after the settings are resolved and
// jSignatureInstance.events is created
// and right before first ("jSignature.initializing") event is called.
// You don't really need to manupilate
// jSignatureInstance directly, just attach
// a bunch of events to jSignatureInstance.events
// (look at the source of jSignatureClass to see when these fire)
// and your special pieces of code will attach by themselves.
// this function runs every time a new instance is set up.
// this means every var you create will live only for one instance
// unless you attach it to something outside, like "window."
// and pick it up later from there.
// when globalEvents' events fire, 'this' is globalEvents object
// when jSignatureInstance's events fire, 'this' is jSignatureInstance
// Here,
// this = is new jSignatureClass's instance.
// The way you COULD approch setting this up is:
// if you have multistep set up, attach event to "jSignature.initializing"
// that attaches other events to be fired further lower the init stream.
// Or, if you know for sure you rely on only one jSignatureInstance's event,
// just attach to it directly
var apinamespace = 'jSignature'
this.events.subscribe(
// name of the event
apinamespace + '.attachingEventHandlers'
// event handlers, can pass args too, but in majority of cases,
// 'this' which is jSignatureClass object instance pointer is enough to get by.
, function(){
// hooking up "undo" button to lower edge of Canvas.
// but only when options passed to jSignature('init', options)
// contain "undoButton":renderingFunction pair.
// or "undoButton":true (in which case default, internal rendering fn is used)
if (this.settings[extensionName]) {
var oursettings = this.settings[extensionName]
if (typeof oursettings !== 'function') {
// we make it a function.
// we allow people to override the button rendering code,
// but when developler is OK with default look (and just passes "truthy" value)
// this defines default look for the button:
// centered against canvas, hanging on its lower side.
oursettings = function(){
// this === jSignatureInstance
var undoButtonSytle = 'position:absolute;display:none;margin:0 !important;top:auto'
, $undoButton = $('<input type="button" value="Undo last stroke" style="'+undoButtonSytle+'" />')
.appendTo(this.$controlbarLower)
// this centers the button against the canvas.
var buttonWidth = $undoButton.width()
$undoButton.css(
'left'
, Math.round(( this.canvas.width - buttonWidth ) / 2)
)
// IE 7 grows the button. Correcting for that.
if ( buttonWidth !== $undoButton.width() ) {
$undoButton.width(buttonWidth)
}
return $undoButton
}
}
attachHandlers.call(
this
, oursettings
, apinamespace
, extensionName
)
}
}
)
}
var ExtensionAttacher = function(){
$.fn[apinamespace](
'addPlugin'
,'instance' // type of plugin
,'UndoButton' // extension name
,ExtensionInitializer
)
}
// //Because plugins are minified together with jSignature, multiple defines per (minified) file blow up and dont make sense
// //Need to revisit this later.
// if ( typeof define === "function" && define.amd != null) {
// // AMD-loader compatible resource declaration
// // you need to call this one with jQuery as argument.
// define(function(){return Initializer} )
// } else {
ExtensionAttacher()
// }
})();

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

@ -0,0 +1,4 @@
/* Modernizr 2.5.2 (Custom Build) | MIT & BSD
* Build: http://www.modernizr.com/download/#-borderradius-csscolumns-canvas-touch-mq-cssclasses-addtest-teststyles-testprop-testallprops-prefixes-domprefixes-fullscreen_api
*/
;window.Modernizr=function(a,b,c){function A(a){j.cssText=a}function B(a,b){return A(m.join(a+";")+(b||""))}function C(a,b){return typeof a===b}function D(a,b){return!!~(""+a).indexOf(b)}function E(a,b){for(var d in a)if(j[a[d]]!==c)return b=="pfx"?a[d]:!0;return!1}function F(a,b,d){for(var e in a){var f=b[a[e]];if(f!==c)return d===!1?a[e]:C(f,"function")?f.bind(d||b):f}return!1}function G(a,b,c){var d=a.charAt(0).toUpperCase()+a.substr(1),e=(a+" "+o.join(d+" ")+d).split(" ");return C(b,"string")||C(b,"undefined")?E(e,b):(e=(a+" "+p.join(d+" ")+d).split(" "),F(e,b,c))}var d="2.5.2",e={},f=!0,g=b.documentElement,h="modernizr",i=b.createElement(h),j=i.style,k,l={}.toString,m=" -webkit- -moz- -o- -ms- ".split(" "),n="Webkit Moz O ms",o=n.split(" "),p=n.toLowerCase().split(" "),q={},r={},s={},t=[],u=t.slice,v,w=function(a,c,d,e){var f,i,j,k=b.createElement("div"),l=b.body,m=l?l:b.createElement("body");if(parseInt(d,10))while(d--)j=b.createElement("div"),j.id=e?e[d]:h+(d+1),k.appendChild(j);return f=["&#173;","<style>",a,"</style>"].join(""),k.id=h,m.innerHTML+=f,m.appendChild(k),l||g.appendChild(m),i=c(k,a),l?k.parentNode.removeChild(k):m.parentNode.removeChild(m),!!i},x=function(b){var c=a.matchMedia||a.msMatchMedia;if(c)return c(b).matches;var d;return w("@media "+b+" { #"+h+" { position: absolute; } }",function(b){d=(a.getComputedStyle?getComputedStyle(b,null):b.currentStyle)["position"]=="absolute"}),d},y={}.hasOwnProperty,z;!C(y,"undefined")&&!C(y.call,"undefined")?z=function(a,b){return y.call(a,b)}:z=function(a,b){return b in a&&C(a.constructor.prototype[b],"undefined")},Function.prototype.bind||(Function.prototype.bind=function(b){var c=this;if(typeof c!="function")throw new TypeError;var d=u.call(arguments,1),e=function(){if(this instanceof e){var a=function(){};a.prototype=c.prototype;var f=new a,g=c.apply(f,d.concat(u.call(arguments)));return Object(g)===g?g:f}return c.apply(b,d.concat(u.call(arguments)))};return e});var H=function(c,d){var f=c.join(""),g=d.length;w(f,function(c,d){var f=b.styleSheets[b.styleSheets.length-1],h=f?f.cssRules&&f.cssRules[0]?f.cssRules[0].cssText:f.cssText||"":"",i=c.childNodes,j={};while(g--)j[i[g].id]=i[g];e.touch="ontouchstart"in a||a.DocumentTouch&&b instanceof DocumentTouch||(j.touch&&j.touch.offsetTop)===9},g,d)}([,["@media (",m.join("touch-enabled),("),h,")","{#touch{top:9px;position:absolute}}"].join("")],[,"touch"]);q.canvas=function(){var a=b.createElement("canvas");return!!a.getContext&&!!a.getContext("2d")},q.touch=function(){return e.touch},q.borderradius=function(){return G("borderRadius")},q.csscolumns=function(){return G("columnCount")};for(var I in q)z(q,I)&&(v=I.toLowerCase(),e[v]=q[I](),t.push((e[v]?"":"no-")+v));return e.addTest=function(a,b){if(typeof a=="object")for(var d in a)z(a,d)&&e.addTest(d,a[d]);else{a=a.toLowerCase();if(e[a]!==c)return e;b=typeof b=="function"?b():b,g.className+=" "+(b?"":"no-")+a,e[a]=b}return e},A(""),i=k=null,e._version=d,e._prefixes=m,e._domPrefixes=p,e._cssomPrefixes=o,e.mq=x,e.testProp=function(a){return E([a])},e.testAllProps=G,e.testStyles=w,g.className=g.className.replace(/(^|\s)no-js(\s|$)/,"$1$2")+(f?" js "+t.join(" "):""),e}(this,this.document),Modernizr.addTest("fullscreen",function(){for(var a=0;a<Modernizr._domPrefixes.length;a++)if(document[Modernizr._domPrefixes[a].toLowerCase()+"CancelFullScreen"])return!0;return!!document.cancelFullScreen||!1});

@ -1,31 +0,0 @@
function mSign_signMark_app(){
debugger;
var wrapper = document.getElementById("mSign_signMark_signature_pad"),
clearButton = document.getElementById("mSign_signMark_clear_out"),
canvas = wrapper.querySelector("canvas"),
sure = document.getElementsByClassName("mSign_signMark_footer_sure"),
signaturePad;
function resizeCanvas() {
var ratio = Math.max(window.devicePixelRatio || 1, 1);
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
}
window.onresize = resizeCanvas;
resizeCanvas();
signaturePad = new SignaturePad(canvas,{
minWidth: 1,
maxWidth: 2,
penColor: "rgb(0,0,0)"
});
clearButton.addEventListener("click", function (event) {
signaturePad.clear();
});
}

@ -1,368 +0,0 @@
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], function () {
return (root['SignaturePad'] = factory());
});
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root['SignaturePad'] = factory();
}
}(this, function () {
var SignaturePad = (function (document) {
"use strict";
var SignaturePad = function (canvas, options) {
var self = this,
opts = options || {};
this.velocityFilterWeight = opts.velocityFilterWeight || 0.7;
this.minWidth = opts.minWidth || 0.5;
this.maxWidth = opts.maxWidth || 2.5;
this.dotSize = opts.dotSize || function () {
return (this.minWidth + this.maxWidth) / 2;
};
this.penColor = opts.penColor || "black";
this.backgroundColor = opts.backgroundColor || "rgba(0,0,0,0)";
this.onEnd = opts.onEnd;
this.onBegin = opts.onBegin;
this._canvas = canvas;
this._ctx = canvas.getContext("2d");
this.clear();
this._handleMouseDown = function (event) {
if (event.which === 1) {
self._mouseButtonDown = true;
self._strokeBegin(event);
}
};
this._handleMouseMove = function (event) {
if (self._mouseButtonDown) {
self._strokeUpdate(event);
}
};
this._handleMouseUp = function (event) {
if (event.which === 1 && self._mouseButtonDown) {
self._mouseButtonDown = false;
self._strokeEnd(event);
}
};
this._handleTouchStart = function (event) {
if (event.targetTouches.length == 1) {
var touch = event.changedTouches[0];
self._strokeBegin(touch);
}
};
this._handleTouchMove = function (event) {
// Prevent scrolling.
event.preventDefault();
var touch = event.targetTouches[0];
self._strokeUpdate(touch);
};
this._handleTouchEnd = function (event) {
var wasCanvasTouched = event.target === self._canvas;
if (wasCanvasTouched) {
event.preventDefault();
self._strokeEnd(event);
}
};
this._handleMouseEvents();
this._handleTouchEvents();
};
SignaturePad.prototype.clear = function () {
var ctx = this._ctx,
canvas = this._canvas;
ctx.fillStyle = this.backgroundColor;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(0, 0, canvas.width, canvas.height);
this._reset();
};
SignaturePad.prototype.toDataURL = function (imageType, quality) {
var canvas = this._canvas;
return canvas.toDataURL.apply(canvas, arguments);
};
SignaturePad.prototype.fromDataURL = function (dataUrl) {
var self = this,
image = new Image(),
ratio = window.devicePixelRatio || 1,
width = this._canvas.width / ratio,
height = this._canvas.height / ratio;
this._reset();
image.src = dataUrl;
image.onload = function () {
self._ctx.drawImage(image, 0, 0, width, height);
};
this._isEmpty = false;
};
SignaturePad.prototype._strokeUpdate = function (event) {
var point = this._createPoint(event);
this._addPoint(point);
};
SignaturePad.prototype._strokeBegin = function (event) {
this._reset();
this._strokeUpdate(event);
if (typeof this.onBegin === 'function') {
this.onBegin(event);
}
};
SignaturePad.prototype._strokeDraw = function (point) {
var ctx = this._ctx,
dotSize = typeof(this.dotSize) === 'function' ? this.dotSize() : this.dotSize;
ctx.beginPath();
this._drawPoint(point.x, point.y, dotSize);
ctx.closePath();
ctx.fill();
};
SignaturePad.prototype._strokeEnd = function (event) {
var canDrawCurve = this.points.length > 2,
point = this.points[0];
if (!canDrawCurve && point) {
this._strokeDraw(point);
}
if (typeof this.onEnd === 'function') {
this.onEnd(event);
}
};
SignaturePad.prototype._handleMouseEvents = function () {
this._mouseButtonDown = false;
this._canvas.addEventListener("mousedown", this._handleMouseDown);
this._canvas.addEventListener("mousemove", this._handleMouseMove);
document.addEventListener("mouseup", this._handleMouseUp);
};
SignaturePad.prototype._handleTouchEvents = function () {
// Pass touch events to canvas element on mobile IE11 and Edge.
this._canvas.style.msTouchAction = 'none';
this._canvas.style.touchAction = 'none';
this._canvas.addEventListener("touchstart", this._handleTouchStart);
this._canvas.addEventListener("touchmove", this._handleTouchMove);
this._canvas.addEventListener("touchend", this._handleTouchEnd);
};
SignaturePad.prototype.on = function () {
this._handleMouseEvents();
this._handleTouchEvents();
};
SignaturePad.prototype.off = function () {
this._canvas.removeEventListener("mousedown", this._handleMouseDown);
this._canvas.removeEventListener("mousemove", this._handleMouseMove);
document.removeEventListener("mouseup", this._handleMouseUp);
this._canvas.removeEventListener("touchstart", this._handleTouchStart);
this._canvas.removeEventListener("touchmove", this._handleTouchMove);
this._canvas.removeEventListener("touchend", this._handleTouchEnd);
};
SignaturePad.prototype.isEmpty = function () {
return this._isEmpty;
};
SignaturePad.prototype._reset = function () {
this.points = [];
this._lastVelocity = 0;
this._lastWidth = (this.minWidth + this.maxWidth) / 2;
this._isEmpty = true;
this._ctx.fillStyle = this.penColor;
};
SignaturePad.prototype._createPoint = function (event) {
var rect = this._canvas.getBoundingClientRect();
return new Point(
event.clientX - rect.left,
event.clientY - rect.top
);
};
SignaturePad.prototype._addPoint = function (point) {
var points = this.points,
c2, c3,
curve, tmp;
points.push(point);
if (points.length > 2) {
// To reduce the initial lag make it work with 3 points
// by copying the first point to the beginning.
if (points.length === 3) points.unshift(points[0]);
tmp = this._calculateCurveControlPoints(points[0], points[1], points[2]);
c2 = tmp.c2;
tmp = this._calculateCurveControlPoints(points[1], points[2], points[3]);
c3 = tmp.c1;
curve = new Bezier(points[1], c2, c3, points[2]);
this._addCurve(curve);
// Remove the first element from the list,
// so that we always have no more than 4 points in points array.
points.shift();
}
};
SignaturePad.prototype._calculateCurveControlPoints = function (s1, s2, s3) {
var dx1 = s1.x - s2.x, dy1 = s1.y - s2.y,
dx2 = s2.x - s3.x, dy2 = s2.y - s3.y,
m1 = {x: (s1.x + s2.x) / 2.0, y: (s1.y + s2.y) / 2.0},
m2 = {x: (s2.x + s3.x) / 2.0, y: (s2.y + s3.y) / 2.0},
l1 = Math.sqrt(dx1*dx1 + dy1*dy1),
l2 = Math.sqrt(dx2*dx2 + dy2*dy2),
dxm = (m1.x - m2.x),
dym = (m1.y - m2.y),
k = l2 / (l1 + l2),
cm = {x: m2.x + dxm*k, y: m2.y + dym*k},
tx = s2.x - cm.x,
ty = s2.y - cm.y;
return {
c1: new Point(m1.x + tx, m1.y + ty),
c2: new Point(m2.x + tx, m2.y + ty)
};
};
SignaturePad.prototype._addCurve = function (curve) {
var startPoint = curve.startPoint,
endPoint = curve.endPoint,
velocity, newWidth;
velocity = endPoint.velocityFrom(startPoint);
velocity = this.velocityFilterWeight * velocity
+ (1 - this.velocityFilterWeight) * this._lastVelocity;
newWidth = this._strokeWidth(velocity);
this._drawCurve(curve, this._lastWidth, newWidth);
this._lastVelocity = velocity;
this._lastWidth = newWidth;
};
SignaturePad.prototype._drawPoint = function (x, y, size) {
var ctx = this._ctx;
ctx.moveTo(x, y);
ctx.arc(x, y, size, 0, 2 * Math.PI, false);
this._isEmpty = false;
};
SignaturePad.prototype._drawCurve = function (curve, startWidth, endWidth) {
var ctx = this._ctx,
widthDelta = endWidth - startWidth,
drawSteps, width, i, t, tt, ttt, u, uu, uuu, x, y;
drawSteps = Math.floor(curve.length());
ctx.beginPath();
for (i = 0; i < drawSteps; i++) {
// Calculate the Bezier (x, y) coordinate for this step.
t = i / drawSteps;
tt = t * t;
ttt = tt * t;
u = 1 - t;
uu = u * u;
uuu = uu * u;
x = uuu * curve.startPoint.x;
x += 3 * uu * t * curve.control1.x;
x += 3 * u * tt * curve.control2.x;
x += ttt * curve.endPoint.x;
y = uuu * curve.startPoint.y;
y += 3 * uu * t * curve.control1.y;
y += 3 * u * tt * curve.control2.y;
y += ttt * curve.endPoint.y;
width = startWidth + ttt * widthDelta;
this._drawPoint(x, y, width);
}
ctx.closePath();
ctx.fill();
};
SignaturePad.prototype._strokeWidth = function (velocity) {
return Math.max(this.maxWidth / (velocity + 1), this.minWidth);
};
var Point = function (x, y, time) {
this.x = x;
this.y = y;
this.time = time || new Date().getTime();
};
Point.prototype.velocityFrom = function (start) {
return (this.time !== start.time) ? this.distanceTo(start) / (this.time - start.time) : 1;
};
Point.prototype.distanceTo = function (start) {
return Math.sqrt(Math.pow(this.x - start.x, 2) + Math.pow(this.y - start.y, 2));
};
var Bezier = function (startPoint, control1, control2, endPoint) {
this.startPoint = startPoint;
this.control1 = control1;
this.control2 = control2;
this.endPoint = endPoint;
};
// Returns approximated length.
Bezier.prototype.length = function () {
var steps = 10,
length = 0,
i, t, cx, cy, px, py, xdiff, ydiff;
for (i = 0; i <= steps; i++) {
t = i / steps;
cx = this._point(t, this.startPoint.x, this.control1.x, this.control2.x, this.endPoint.x);
cy = this._point(t, this.startPoint.y, this.control1.y, this.control2.y, this.endPoint.y);
if (i > 0) {
xdiff = cx - px;
ydiff = cy - py;
length += Math.sqrt(xdiff * xdiff + ydiff * ydiff);
}
px = cx;
py = cy;
}
return length;
};
Bezier.prototype._point = function (t, start, c1, c2, end) {
return start * (1.0 - t) * (1.0 - t) * (1.0 - t)
+ 3.0 * c1 * (1.0 - t) * (1.0 - t) * t
+ 3.0 * c2 * (1.0 - t) * t * t
+ end * t * t * t;
};
return SignaturePad;
})(document);
return SignaturePad;
}));

@ -1,4 +1,15 @@
<style>
<!-- required JS files -->
<script src="/static/lib/jSignature/jquery.js"></script>
<script src="/static/lib/jSignature/jSignature.js"></script>
<!-- optional plugins -->
<script src="/static/lib/jSignature/jSignature.CompressorBase30.js"></script>
<script src="/static/lib/jSignature/jSignature.CompressorSVG.js"></script>
<script src="/static/lib/jSignature/jSignature.UndoButton.js"></script>
<script src="/static/lib/jSignature/jSignature.SignHere.js"></script>
<style type="text/css">
td {text-align:center}
@ -13,47 +24,31 @@
margin: 0px 15%;
}
.sign{
/* // line color
color:"#f00",
// line width
lineWidth:5,
// width/height of signature pad
width:300,
height:200,
// background color
background-color:"#0f0"*/
min-height: 150px;
}
@media (min-width:100px) and (max-width:399px){*{font-size:1px;}}
@media (min-width:400px) and (max-width:799px){*{font-size:5px;}}
@media (min-width:800px) and (max-width:1024px) {*{font-size:10px;}}
@media (min-width:1025px) and (max-width:1440px) {*{font-size:15px;}}
@media (min-width:1441px) and (max-width:1600px){*{font-size:20px;}}
.mSign_signMark_box{padding: 15px 15px 26px 15px;}
.mSign_signMark_footer{max-width:640px;margin:0 auto;height: 44px;background: #4ba7eb;position: fixed;bottom: 0;left: 0;right: 0;color:#fff;font-size: 16px;text-align: center;line-height: 44px;}
.mSign_signMark_footer span{display: block;width: 50%;text-align: center;float: left;}
.mSign_signMark_footer_cancle{background: #f4f4f5;color: #333333;}
/*手写签名*/
.mSign_signMark_write_box{position: relative;height: 240px;}
.mSign_signMark_body_box {position: absolute;background-color: #fff;border: 1px solid #ccc;top:0;left: 0;right: 0;bottom: 0;width: 99%;height: auto;min-width: 250px;min-height: 140px;}
.mSign_signMark_body {position: absolute;left: 0;right: 0;top: 0;bottom: 0;}
.mSign_signMark_body canvas {position: absolute;left: 0;top: 0;width: 100%;height: 100%;}
.mSign_signMark_body p{position: absolute;font-size: 14px;color: #ccc;text-align: center;width: 100%;top: 50%;margin-top: -22px;}
.mSign_signMark_clear_out{position: absolute;top:-10px;right: -5px;z-index: 10;display: none;}
.mSign_signMark_clear_out img{width: 18px;height: 18px;}
</style>
<script src="static/lib/mSign_signMark_app.js"></script>
<script src="static/lib/mSign_signMark_signature_pad.js"></script>
<script>
$(function() {
var ctouch=$('.mSign_signMark_body canvas');
ctouch.bind("touchstart",function(event){
$('.mSign_signMark_body p').hide();
});
ctouch.mouseover(function(event) {
$('.mSign_signMark_body p').hide();
});
});
</script>
<div ui-view>
<section class="content" style="background:#4F4F4F;">
<div class="row">
@ -70,6 +65,10 @@
<p>
<button class="btn btn-success" type="button" ng-click="submitContract()">确认签署</button>
</p>
<p>
<button class="btn btn-success" type="button" ui-sref="testSign">确认签署</button>
</p>
</table>
</div>
@ -80,6 +79,14 @@
</div>
<div style="z-index: 9999; position: fixed ! important; right: 85%; top: 20%;">
<table width=""100% style="position: absolute; width:260px; right: 0px; top: 0px;">
<input name="" type="button" ui-sref="testSign" style=" width:81px; height:39px; border:0; background:url(https://file.royalpay.com.au/open/2019/08/23/1566552615778_7vCo6vyDQ8Nf0uVLW9kI9jQSoIZKPK.png) no-repeat left top" />
</table>
</div>
<!--Title Start-->
<div>
<p><img class="col-sm-12" ng-src="https://file.royalpay.com.au/open/2019/08/23/1566528847626_ZRvrievyWEayhByRpkCDwV1P0k7FXt.png"></p>
@ -1125,9 +1132,11 @@
<tr>
<td width="24%">
<p><strong><strong>Signature of Director/Secretary:</strong></strong></p>
<span style="color:blue">(请在此签名 --></span>
</td>
<td width="38%">
<canvas id="myCanvas" width="200" height="100"></canvas>
</td>
<td width="38%">
<p></p>
@ -1136,6 +1145,7 @@
<tr>
<td>
<p><strong><strong>Print Full Name:</strong></strong></p>
<span style="color:blue">(请在此输入全名 --></span>
</td>
<td>
<input ng-bind="aggregateFileInfo.full_name" style="width:100%"/>
@ -1168,33 +1178,51 @@
</tbody>
</table>
</div>
</div>
</div>
</div>
</section>
</div>
</section>
</div>
<div clas="row">
<img id="img1" src="">
<div class="row">
<div class="container-fluid">
<div class="card-boxs widget-box-two widget-two-custom" style="overflow-x: auto;">
<div id="signatureparent" class="sign" >
<div id="signature" style="background-color: grey; lineWidth:5; color: black"></div>
</div>
<button onclick="reset()">重置</button><button onclick="ok()">ok</button>
<div class="mSign_signMark_box">
<div class="mSign_signMark_write_box">
<div id="mSign_signMark_signature_pad" class="mSign_signMark_body_box">
<div class="mSign_signMark_body">
<span class="mSign_signMark_clear_out">
<img src="../images/mCommon_basicIcon_deleteRed.png">
</span>
<p>手写区</p>
<canvas id="mSign_signMark_canvas"></canvas>
</div>
</div>
</div>
</div>
</div>
<!--手写区 end-->
<!--底部按钮-->
<div class="mSign_signMark_footer">
<span id="mSign_signMark_clear_out" class="mSign_signMark_footer_cancle">清除</span>
<span id="mSign_signMark_submit" class="mSign_signMark_footer_sure">确定</span>
</section>
</div>
<!--底部按钮 end-->
<script>
$(function() {
$("#signature").jSignature();
})
function reset() {
$("#signature").jSignature('reset');
}
function ok() {
var x = $("#signature").jSignature('getData','image');
console.log(x);
document.getElementById("img1").src= x;
debugger
}
</script>

Loading…
Cancel
Save