c-signature
Version:
这是一个签名版插件
406 lines (381 loc) • 17.2 kB
JavaScript
/*
* @Author: unhum
* @Date: 2018-06-30 17:00:45
* @Last Modified by: unhum
* @Last Modified time: 2018-06-30 17:47:58
*/
;(function(global){
"use strict";
var _device = 0,
tools = [
{ icon: 'fa-refresh', name: 'refresh', fn: 'refresh()' },
{ icon: 'fa-th-large', name: 'color', fn: 'setColor(this)' },
{ icon: 'fa-eraser', name: 'eraser', fn: 'toggleEraser(this)' },
{ icon: 'fa-paint-brush', name: 'paint-brush', fn: 'setConfig("lineWidth",10,this)' },
{ icon: 'fa-arrows-alt', warning: '画板尺寸变化后,内容将丢失', name: 'arrows-alt', fn: 'resize(this,"all")' },
{ icon: 'fa-download', name: 'download', fn: 'download()' }
],
color_list = [
{ color: 'white', name: '白色' },
{ color: 'black', name: '黑色' },
{ color: 'yellow', name: '黄色' },
{ color: '#ffd700', name: '金黄色' },
{ color: '#292421', name: '象牙黑' },
{ color: '#ffffcd', name: '白杏仁' },
{ color: '#d2691e', name: '巧克力色' },
{ color: '#9933fa', name: '淡紫色' },
{ color: 'blue', name: '蓝色' },
{ color: 'red', name: '红色' },
{ color: '#b03060', name: '栗色' }
];
// 获取滚动条信息
function getScrollInfo(params) {
var scroll = 0;
if (document.documentElement && document.documentElement[params]) {
scroll = document.documentElement[params];
} else if (document.body) {
scroll = document.body[params];
}
return scroll;
};
//获取当前设备
function getDevice() {
var sUserAgent = navigator.userAgent.toLowerCase();
var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
var bIsMidp = sUserAgent.match(/midp/i) == "midp";
var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
var bIsAndroid = sUserAgent.match(/android/i) == "android";
var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
_device = 1;
} else {
_device = 0;
}
};
//取消事件冒泡
function stopBubble(e) {
//一般用在鼠标或键盘事件上
if (e && e.stopPropagation) {
//W3C取消冒泡事件
e.stopPropagation();
} else {
//IE取消冒泡事件
window.event.cancelBubble = true;
}
};
var signature = function(params) {
if (!params || !params.dom) return alert('必填参数不能为空');
this.dom = params.dom;
this.width = params.width || document.querySelector(this.dom).offsetWidth;
this.height = params.height || document.querySelector(this.dom).offsetHeight;
this.theme = params.theme || 'WB'; //WB:经典黑线白底 BW:白线黑底
this.lineWidth = params.lineWidth || 1;
this.follow = params.follow ? true : false;
this.console = params.console == false ? false : true;
this.consoleHeight = 0;
this.eraser = false;
this.tname = params.tname || 'signature';
this.tmp = {};
var that = this;
function create(ele) {
if (that.console) {
var div = document.createElement('div');
div.classList.add('signature-console');
// 初始化工具栏
for (var i = 0; i < tools.length; i++) {
var _i = document.createElement('i');
_i.setAttribute('onclick', that.tname + '.' + tools[i].fn);
_i.classList.add(tools[i].icon);
_i.classList.add('fa');
_i.innerHTML = '<span>' + tools[i].name + '</span>';
if (tools[i].class) {
_i.classList.add(tools[i].class);
}
if (tools[i].warning) {
var warning = document.createElement('div');
warning.innerHTML = tools[i].warning;
warning.classList.add('signature-warning');
_i.appendChild(warning);
}
div.appendChild(_i);
}
document.querySelector(ele.dom).appendChild(div);
//记录控制台高度
that.consoleHeight = document.querySelector(that.dom).querySelector('.signature-console').clientHeight;
}
var c = document.createElement('canvas');
c.innerHTML = '请升级您的浏览器或者更换您的浏览器。';
c.style.background = ele.bg;
c.width = ele.width;
c.height = that.console ? ele.height - that.consoleHeight : ele.height;
document.querySelector(ele.dom).appendChild(c);
ele.canvas = c;
// 相应容器变化
window.addEventListener('resize', function () {
if (that.width != document.querySelector(that.dom).offsetWidth) {
that.canvas.width = document.querySelector(that.dom).offsetWidth;
that.width = document.querySelector(that.dom).offsetWidth;
}
})
};
function init() {
switch (that.theme) {
case 'WB':
that.color = 'black';
that.bg = 'white';
break;
case 'BW':
that.color = 'white';
that.bg = 'black';
break;
default:
that.color = 'black';
that.bg = 'white';
break;
}
that.color = params.color ? params.color : that.color;
that.bg = params.bg ? params.bg : that.bg;
// 初始化canvas
create(that);
// 记录原有属性
for (var x in that) {
that.tmp[x] = that[x];
};
// 判断客户端设备
getDevice();
that.canvas.addEventListener(_device == 0 ? 'mousedown' : 'touchstart', function (event) {
//取消默认事件
event.preventDefault();
that.fnDown(event);
})
};
// 初始化
init();
};
signature.prototype = {
fnMove: function (event) {
var e = event || window.event;
if (_device == 1) e = e.touches[0];
var position = {
left: document.querySelector(this.dom).offsetLeft,
top: this.canvas.offsetTop
};
var x = (_device == 0 ? e.clientX : e.pageX) - position.left + getScrollInfo('scrollLeft');
var y = (_device == 0 ? e.clientY : e.pageY) - position.top + getScrollInfo('scrollTop');
this.pen.lineTo(x, y);
this.pen.stroke();
},
createTools: function (params, fn) {
if (!params) {
alert('请填写相关参数');
return
};
if (this.console) {
var _SIGNATURE = this;
// 用户自定义添加工具
var CONSOLE = document.querySelector(this.dom).querySelector('.signature-console');
var i = document.createElement('i');
i.onclick = fn ? function () { fn(_SIGNATURE) } : function () { alert('请填写方法') };
i.innerHTML = '<span>' + (params.name ? params.name : 'Untitled tool') + '</span>';
i.setAttribute('class', params.icon ? params.icon + ' fa' : 'fa-gear fa');
if (params.class) {
i.classList.add(tools[i].class);
}
if (params.warning) {
var warning = document.createElement('div');
warning.innerHTML = params.warning;
warning.classList.add('signature-warning');
i.appendChild(warning);
}
CONSOLE.appendChild(i);
}
},
download: function () {
var type = 'png';
var imgData = this.canvas.toDataURL();
// 修改图片类型,强制下载
var _fixType = function (type) {
type = type.toLowerCase().replace(/jpg/i, 'jpeg');
var r = type.match(/png|jpeg|bmp|gif/)[0];
return 'image/' + r;
};
imgData = imgData.replace(_fixType(type), 'image/octet-stream');
// 保存图片到本地
var saveFile = function (data, filename) {
var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
save_link.href = data;
save_link.download = filename;
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
save_link.dispatchEvent(event);
};
// 设置图片名称
var filename = 'signature_' + (new Date()).getTime() + '.' + type;
// download
saveFile(imgData, filename);
},
fnDown: function (event) {
var e = event || window.event;
var _dom = document.querySelector(this.dom);
var position = {
left: document.querySelector(this.dom).offsetLeft,
top: this.canvas.offsetTop
// - (this.console ? : 0)
};
if (_device == 1) e = e.touches[0];
var x = (_device == 0 ? e.clientX : e.pageX) - position.left + getScrollInfo('scrollLeft');
var y = (_device == 0 ? e.clientY : e.pageY) - position.top + getScrollInfo('scrollTop');
//初始化"画笔"
this.pen = this.canvas.getContext('2d');
//绘制开始
this.pen.beginPath();
if (_dom.querySelector('.signature-console')) {
this.pen.strokeStyle = _dom.querySelector('.fa-eraser').classList.contains('active') ? this.bg : this.color;
this.pen.lineWidth = _dom.querySelector('.fa-eraser').classList.contains('active') ? this.lineWidth + 4 : this.lineWidth - 1;
} else {
this.pen.strokeStyle = this.color;
this.pen.lineWidth = this.lineWidth - 1;
}
this.pen.shadowBlur = 1;
this.pen.shadowColor = this.color;
if (_dom.querySelector('.signature-console')) {
_dom.querySelector('.fa-eraser').classList.contains('active') ? this.pen.shadowColor = this.bg : this.pen.shadowColor = this.color;
}
this.pen.lineTo(x, y);
var _this = this;
//创建用户滑动轨迹
_device == 0 ? document.onmousemove = function (event) {
_this.fnMove(event);
} : document.addEventListener('touchmove', function (event) {
//取消默认事件
event.preventDefault();
_this.fnMove(event);
});
//终止签名
window.addEventListener(_device == 0 ? 'mouseup' : 'touchend', function (event) {
_this.fnUp(event);
});
},
fnUp: function () {
this.pen.closePath();
document.onmousemove = '';
},
toggleEraser(ele) {
this.active(ele);
},
refresh: function () {
if (this.pen) {
this.pen.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
},
active: function (ele, status, fn) {
if (status == true) {
fn();
} else {
ele.classList.contains('active') ? ele.classList.remove('active') : ele.classList.add('active');
}
},
selectColor: function (ele, color, event) {
var e = event || window.event;
var _this = this;
// 取消事件冒泡
stopBubble(e);
ele.classList.contains('select') ? function () {
ele.classList.remove('select');
_this.color = _this.tmp.color;
}() : function () {
var _dom = document.querySelector(_this.dom);
for (var i = 0; i < _dom.querySelectorAll('.signature-set-color > div').length; i++) {
_dom.querySelectorAll('.signature-set-color > div')[i].classList.remove('select');
}
_dom.querySelector('.signature-set-color').style.display = 'none';
_this.color = color;
ele.classList.add('select');
}()
},
setColor: function (ele) {
var _this = this;
var signature_set_color = ele.querySelector('.signature-set-color');
// 添加样式
this.active(ele, true, function () {
if (ele.querySelector('.signature-set-color .select')) {
signature_set_color.style.display = 'block';
} else {
ele.classList.contains('active') ? ele.classList.remove('active') : ele.classList.add('active');
}
});
if (ele.classList.contains('active')) {
if (signature_set_color) {
signature_set_color.style.display = 'block';
} else {
// 创建颜色框
var div = document.createElement('div');
div.classList.add('signature-set-color');
div.style.width = Math.ceil((this.width / 2 - 10) / 34) * 34 + 'px';
for (var i = 0; i < color_list.length; i++) {
var color = document.createElement('div');
color.classList.add('color');
color.title = color_list[i].name;
color.setAttribute('onclick', this.tname + '.selectColor(this,"' + color_list[i].color + '",event)');
color.style.background = color_list[i].color;
div.appendChild(color);
}
ele.appendChild(div);
}
} else {
signature_set_color.style.display = 'none';
this.color = this.tmp.color;
}
},
setConfig: function (params, num, ele) {
var _this = this;
if (ele.classList.contains('active')) {
ele.classList.remove('active');
_this[params] = _this.tmp[params];
} else {
ele.classList.add('active');
_this[params] = num;
}
},
config: function (params) {
params.dom ? function () {
alert('禁止修改dom');
return
}() : function () {
for (var p in params) {
_this[p] = params[p];
}
}()
},
resize: function (ele, w, j) {
var _this = this;
_this.active(ele, true, function () {
var _dom = document.querySelector(_this.dom);
if (ele.classList.contains('active')) {
ele.classList.remove('active');
_dom.classList.remove('signature-full');
_this.canvas.width = _this.tmp.width;
_this.canvas.height = _this.console ? _this.tmp.height - _this.consoleHeight : _this.tmp.height;
} else {
ele.classList.add('active');
if (w == 'all') {
_dom.classList.add('signature-full');
_this.canvas.width = document.documentElement.clientWidth;
_this.canvas.height = document.documentElement.clientHeight;
} else {
_dom.style.width = w;
_dom.style.height = h;
_this.canvas.width = document.documentElement.clientWidth;
_this.canvas.height = document.documentElement.clientHeight;
}
}
})
}
};
if (typeof module !== 'undefined' && module.exports) module.exports = signature;
if (typeof define === 'function') define(function () { return signature; });
global.signature = signature;
})(this)