UNPKG

7.59 kBJavaScriptView Raw
1var Handsign = function Handsign(container, params) {
2 /* ----------------------
3 Model
4 ---------------------- */
5 var defaults = {
6 strokeStyle: '#000',
7 lineWidth: 3,
8
9 suffix: 'image/png',
10 quality: 0.92
11 };
12 params = params || {};
13 for (var def in defaults) {
14 if (params[def] === undefined) {
15 params[def] = defaults[def];
16 }
17 }
18 var s = this;
19 s.params = params;
20 s.container = typeof container === 'string' ? document.querySelector(container) : container;
21 if (!s.container) {
22 console.log('SeedsUI Error : HandSign container不存在,请检查页面中是否有此元素');
23 return;
24 }
25 s.width = s.container.width;
26 s.height = s.container.height;
27 s.ctx = s.container.getContext('2d');
28 s.stageInfo = s.container.getBoundingClientRect();
29 s.path = {
30 beginX: 0,
31 beginY: 0,
32 endX: 0,
33 endY: 0
34 // 标识是否绘制过
35 };s.isDrew = false;
36 /* ----------------------
37 Model Method
38 ---------------------- */
39 s.setStrokeStyle = function (strokeStyle) {
40 if (strokeStyle) {
41 s.params.strokeStyle = strokeStyle;
42 }
43 };
44 s.setLineWidth = function (lineWidth) {
45 if (lineWidth) {
46 s.params.lineWidth = lineWidth;
47 }
48 };
49 s.setSuffix = function (suffix) {
50 if (suffix) {
51 s.params.suffix = suffix;
52 }
53 };
54 s.setQuality = function (quality) {
55 if (quality) {
56 s.params.quality = quality;
57 }
58 };
59 /* ----------------------
60 Events
61 ---------------------- */
62 s.preventDefault = function (e) {
63 e.preventDefault();
64 };
65 s.events = function (detach) {
66 var action = detach ? 'removeEventListener' : 'addEventListener';
67 s.container[action]('touchstart', s.onTouchStart, false);
68 s.container[action]('touchmove', s.onTouchMove, false);
69 s.container[action]('touchend', s.onTouchEnd, false);
70 s.container[action]('touchcancel', s.onTouchEnd, false);
71 };
72 // attach、detach事件
73 s.attach = function () {
74 s.events();
75 };
76 s.detach = function () {
77 s.events(true);
78 };
79 s.onTouchStart = function (e) {
80 e.stopPropagation();
81 s.container.addEventListener('touchmove', s.preventDefault, false);
82 window.getSelection() ? window.getSelection().removeAllRanges() : document.selection.empty();
83 s.ctx.strokeStyle = s.params.strokeStyle;
84 s.ctx.lineWidth = s.params.lineWidth;
85 s.stageInfo = s.container.getBoundingClientRect();
86 s.ctx.beginPath();
87 s.ctx.moveTo(e.changedTouches[0].clientX - s.stageInfo.left, e.changedTouches[0].clientY - s.stageInfo.top);
88 s.path.beginX = e.changedTouches[0].clientX - s.stageInfo.left;
89 s.path.beginY = e.changedTouches[0].clientY - s.stageInfo.top;
90 };
91 s.onTouchMove = function (e) {
92 e.stopPropagation();
93 s.ctx.lineTo(e.changedTouches[0].clientX - s.stageInfo.left, e.changedTouches[0].clientY - s.stageInfo.top);
94 s.path.endX = e.changedTouches[0].clientX - s.stageInfo.left;
95 s.path.endY = e.changedTouches[0].clientY - s.stageInfo.top;
96 s.ctx.stroke();
97 // 标识是否绘制过
98 s.isDrew = true;
99 };
100 s.onTouchEnd = function (e) {
101 s.container.removeEventListener('touchmove', s.preventDefault, false);
102 };
103 /* ----------------------
104 Method
105 ---------------------- */
106 // 获取设备缩放比率
107 s.getPixelRatio = function () {
108 var context = s.ctx;
109 var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1;
110 return (window.devicePixelRatio || 1) / backingStore;
111 };
112 // 清除签名
113 s.clear = function () {
114 s.ctx.clearRect(0, 0, s.width, s.height);
115 // 清除画过
116 s.isDrew = false;
117 };
118 // 是否空白
119 s.blank = function () {
120 var blank = document.createElement('canvas');
121 blank.width = s.container.width;
122 blank.height = s.container.height;
123 if (s.container.toDataURL() === blank.toDataURL()) return true;
124 return false;
125 };
126 // 保存签名
127 s.save = function () {
128 return s.container.toDataURL(s.params.suffix, s.params.quality);
129 };
130 // 计算top left bottom center的位置
131 s.calcPosition = function (w, h, pos) {
132 var posArr = pos.split(' ').map(function (item, index) {
133 var x = 0;
134 var y = 0;
135 // 如果是数字
136 if (!isNaN(item)) {
137 if (index === 0) return { x: item };
138 if (index === 1) return { y: item };
139 }
140 // 如果是字符串
141 if (item === 'top') return { y: 0 };
142 if (item === 'left') return { x: 0 };
143 if (item === 'right') {
144 x = s.width < w ? 0 : s.width - w;
145 return { x: x };
146 }
147 if (item === 'bottom') {
148 y = s.height < h ? 0 : s.height - h;
149 return { y: y };
150 }
151 if (item === 'center') {
152 x = (s.width - w) / 2;
153 return { x: x };
154 }
155 if (item === 'middle') {
156 y = (s.height - h) / 2;
157 return { y: y };
158 }
159 return { x: 0, y: 0 };
160 });
161 var posJson = {
162 x: 0,
163 y: 0
164 };
165 posArr.forEach(function (item) {
166 if (item.x) {
167 posJson.x = item.x;
168 } else if (item.y) {
169 posJson.y = item.y;
170 }
171 });
172 return {
173 x: posJson.x || 0,
174 y: posJson.y || 0
175 };
176 };
177 // 绘制图片
178 s.drawImg = function (imgSrc) {
179 var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
180
181 if (!imgSrc) {
182 console.log('SeedsUI Error:手写签名drawImg缺少imgSrc');
183 return;
184 }
185 var imgW = opts.width;
186 var imgH = opts.height;
187 var imgP = opts.position || 'bottom right';
188
189 var img = new Image();
190 img.crossOrigin = 'Anonymous';
191 img.src = imgSrc;
192 img.onload = function () {
193 var sx = 0; // 剪切的 x 坐标
194 var sy = 0; // 剪切的 y 坐标
195 var width = imgW || img.width; // 使用的图像宽度
196 var height = imgH || img.height; // 使用的图像高度
197 var swidth = img.width; // 剪切图像的宽度
198 var sheight = img.height; // 剪切图像的高度
199 var pos = s.calcPosition(width, height, imgP); // 画布上放置xy坐标
200 s.ctx.drawImage(img, sx, sy, swidth, sheight, pos.x, pos.y, width, height);
201 // 成功回调
202 if (opts.onSuccess) opts.onSuccess();
203 };
204 };
205 // 绘制文字
206 s.drawFont = function (text) {
207 var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
208
209 if (!text) {
210 console.log('SeedsUI Error:手写签名drawFont缺少文字');
211 return;
212 }
213 var fontSize = opts.fontSize || 15;
214 var fontFamily = opts.fontFamily || 'microsoft yahei';
215 var fontPosition = opts.position || 'bottom center';
216 var fontStyle = opts.color || 'rgba(0, 0, 0, 1)';
217 if (isNaN(fontSize)) {
218 console.log('SeedsUI Error:文字大小请输入数字类型');
219 return;
220 }
221 var height = fontSize;
222 var width = text.length * height;
223 var pos = s.calcPosition(width, height, fontPosition); // 画布上放置xy坐标
224 var calcY = pos.y === 0 ? Number(pos.y) + Number(height) : Number(pos.y) + Number(height) - 5; // 文字垂直位置有整个高度的偏差
225 // 写字
226 s.ctx.font = fontSize + 'px ' + fontFamily;
227 s.ctx.fillStyle = fontStyle;
228 s.ctx.fillText(text, pos.x, calcY);
229 };
230 // 绘制背景
231 s.drawBackgroundColor = function (fillStyle) {
232 s.ctx.fillStyle = fillStyle;
233 s.ctx.fillRect(0, 0, s.width, s.height);
234 };
235 // 主函数
236 s.init = function () {
237 s.attach();
238 };
239
240 s.init();
241};
242
243export default Handsign;
\No newline at end of file