gxd-uni-library-editx 1.0.39 → 1.0.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gxd-uni-library-editx",
3
- "version": "1.0.39",
3
+ "version": "1.0.44",
4
4
  "private": false,
5
5
  "description": "聚福宝基础插件专用库",
6
6
  "main": "index.js",
@@ -31,29 +31,25 @@
31
31
  <slot>{{confirm.content}}</slot>
32
32
  </view>
33
33
  <view class="xd-input-confirm__body-btn">
34
- <view>
34
+ <view v-if="confirm.cancel">
35
35
  <xd-button
36
36
  :font-size="32"
37
- v-if="confirm.cancel"
38
37
  @click="handleConfirm('cancel')"
39
38
  :type="confirm.cancelColorType"
40
39
  size="medium"
41
40
  :system-style="$currentStyle"
42
41
  :radius="confirm.btnRadius"
43
- >{{confirm.cancelText}}
44
- </xd-button>
42
+ >{{confirm.cancelText}}</xd-button>
45
43
  </view>
46
- <view>
44
+ <view v-if="confirm.confirm">
47
45
  <xd-button
48
46
  :font-size="32"
49
47
  @click="handleConfirm('confirm')"
50
- v-if="confirm.confirm"
51
48
  :type="confirm.confirmColorType"
52
49
  :system-style="$currentStyle"
53
50
  size="medium"
54
51
  :radius="confirm.btnRadius"
55
- >{{confirm.confirmText}}
56
- </xd-button>
52
+ >{{confirm.confirmText}}</xd-button>
57
53
  </view>
58
54
  </view>
59
55
  </view>
@@ -0,0 +1,475 @@
1
+ <template>
2
+ <view class="lime-signature" v-if="show" :style="[canvasStyle, styles]" ref="limeSignature">
3
+ <!-- #ifndef APP-VUE || APP-NVUE -->
4
+ <canvas v-if="useCanvas2d" class="lime-signature__canvas" :id="canvasId" type="2d"
5
+ :disableScroll="disableScroll" @touchstart="touchStart" @touchmove="touchMove"
6
+ @touchend="touchEnd"></canvas>
7
+ <canvas v-else :disableScroll="disableScroll" class="lime-signature__canvas" :canvas-id="canvasId"
8
+ :id="canvasId" :width="canvasWidth" :height="canvasHeight" @touchstart="touchStart" @touchmove="touchMove"
9
+ @touchend="touchEnd" @mousedown="touchStart" @mousemove="touchMove" @mouseup="touchEnd"></canvas>
10
+ <canvas class="offscreen" canvas-id="offscreen" id="offscreen"
11
+ :style="'width:' + offscreenSize[0] + 'px;height:' + offscreenSize[1] + 'px'" :width="offscreenSize[0]"
12
+ :height="offscreenSize[1]">
13
+ </canvas>
14
+ <view v-if="showMask" class="mask" @touchstart="touchStart" @touchmove.stop.prevent="touchMove" @touchend="touchEnd"></view>
15
+ <!-- #endif -->
16
+ <!-- #ifdef APP-VUE -->
17
+ <view :id="canvasId" :disableScroll="disableScroll" :rparam="param" :change:rparam="sign.update"
18
+ :rclear="rclear" :change:rclear="sign.clear" :rundo="rundo" :change:rundo="sign.undo" :rsave="rsave"
19
+ :change:rsave="sign.save" :rempty="rempty" :change:rempty="sign.isEmpty"></view>
20
+ <!-- #endif -->
21
+ <!-- #ifdef APP-NVUE -->
22
+ <web-view src="/uni_modules/lime-signature/hybrid/html/index.html" class="lime-signature__canvas" ref="webview"
23
+ @pagefinish="onPageFinish" @error="onError" @onPostMessage="onMessage"></web-view>
24
+ <!-- #endif -->
25
+ </view>
26
+ </template>
27
+
28
+ <script>
29
+ // #ifndef APP-NVUE
30
+ import { canIUseCanvas2d, wrapEvent, requestAnimationFrame, sleep , isPC} from './utils'
31
+ import {Signature} from './signature'
32
+ // import {Signature} from '@signature';
33
+ import { uniContext, createImage, toDataURL } from './context'
34
+ // #endif
35
+ import props from './props';
36
+ import { base64ToPath, getRect } from './utils'
37
+
38
+ /**
39
+ * LimeSignature 手写板签名
40
+ * @description 手写板签名插件:一款能跑在uniapp各端中的签名插件,支持横屏、背景色、笔画颜色、笔画大小等功能,可生成有内容的区域,减小图片尺寸,节省空间。
41
+ * @tutorial https://ext.dcloud.net.cn/plugin?id=4354
42
+ * @property {Number} penSize 画笔大小
43
+ * @property {Number} minLineWidth 线条最小宽
44
+ * @property {Number} maxLineWidth 线条最大宽
45
+ * @property {String} penColor 画笔颜色
46
+ * @property {String} backgroundColor 背景颜色,不填则为透明
47
+ * @property {type} 指定 canvas 类型
48
+ * @value 2d canvas 2d
49
+ * @value '' 非 canvas 2d 旧接口,微信不再维护
50
+ * @property {Boolean} openSmooth 模拟笔锋
51
+ * @property {Number} beforeDelay 延时初始化,在放在弹窗里可以使用 (毫秒)
52
+ * @property {Number} maxHistoryLength 限制历史记录数,即最大可撤销数,传入0则关闭历史记录功能
53
+ * @property {Boolean} landscape 横屏,使用后在最后生成图片时会图片旋转90度
54
+ * @property {Boolean} disableScroll 当在写字时,禁止屏幕滚动以及下拉刷新,nvue无效
55
+ * @property {Boolean} boundingBox 只生成内容区域,即未画部分不生成,有性能的损耗
56
+ */
57
+ export default {
58
+ props,
59
+ data() {
60
+ return {
61
+ canvasWidth: null,
62
+ canvasHeight: null,
63
+ offscreenWidth: null,
64
+ offscreenHeight: null,
65
+ useCanvas2d: true,
66
+ show: true,
67
+ offscreenStyles: '',
68
+ showMask: false,
69
+ // #ifdef APP-PLUS
70
+ rclear: 0,
71
+ rundo: 0,
72
+ rsave: JSON.stringify({
73
+ n: 0,
74
+ fileType: 'png',
75
+ quality: 1
76
+ }),
77
+ rempty: 0,
78
+ risEmpty: true,
79
+ toDataURL: null,
80
+ tempFilePath: [],
81
+ // #endif
82
+ }
83
+ },
84
+ computed: {
85
+ canvasId() {
86
+ // #ifdef VUE2
87
+ return `lime-signature${this._uid}`
88
+ // #endif
89
+ // #ifdef VUE3
90
+ return `lime-signature${this._.uid}`
91
+ // #endif
92
+ },
93
+ offscreenId() {
94
+ return this.canvasId + 'offscreen'
95
+ },
96
+ offscreenSize() {
97
+ const {offscreenWidth,offscreenHeight} = this
98
+ return this.landscape ? [offscreenHeight, offscreenWidth] : [offscreenWidth, offscreenHeight]
99
+ },
100
+ canvasStyle() {
101
+ const { canvasWidth, canvasHeight, backgroundColor } = this
102
+ return {
103
+ width: canvasWidth && (canvasWidth + 'px'),
104
+ height: canvasHeight && (canvasHeight + 'px'),
105
+ background: backgroundColor
106
+ }
107
+ },
108
+ param() {
109
+ const {
110
+ penColor,
111
+ penSize,
112
+ backgroundColor,
113
+ landscape,
114
+ boundingBox,
115
+ openSmooth,
116
+ minLineWidth,
117
+ maxLineWidth,
118
+ minSpeed,
119
+ maxWidthDiffRate,
120
+ maxHistoryLength,
121
+ disableScroll
122
+ } = this
123
+ return JSON.parse(JSON.stringify({
124
+ penColor,
125
+ penSize,
126
+ backgroundColor,
127
+ landscape,
128
+ boundingBox,
129
+ openSmooth,
130
+ minLineWidth,
131
+ maxLineWidth,
132
+ minSpeed,
133
+ maxWidthDiffRate,
134
+ maxHistoryLength,
135
+ disableScroll
136
+ }))
137
+ }
138
+ },
139
+ // #ifdef APP-NVUE
140
+ watch: {
141
+ param(v) {
142
+ this.$refs.webview.evalJS(`update(${JSON.stringify(v)})`)
143
+ }
144
+ },
145
+ // #endif
146
+ // #ifndef APP-PLUS
147
+ created() {
148
+ this.useCanvas2d = this.type == '2d' && canIUseCanvas2d() && !isPC
149
+ this.showMask = isPC
150
+ },
151
+ // #endif
152
+ // #ifndef APP-PLUS
153
+ async mounted() {
154
+ if (this.beforeDelay) {
155
+ await sleep(this.beforeDelay)
156
+ }
157
+ const config = await this.getContext()
158
+ this.signature = new Signature(config)
159
+ this.canvasEl = this.signature.canvas.get('el')
160
+ this.offscreenWidth = this.canvasWidth = this.signature.canvas.get('width')
161
+ this.offscreenHeight = this.canvasHeight = this.signature.canvas.get('height')
162
+
163
+ this.stopWatch = this.$watch('param', (v) => {
164
+ this.signature.pen.setOption(v)
165
+ }, {
166
+ immediate: true
167
+ })
168
+ },
169
+ // #endif
170
+ // #ifndef APP-PLUS
171
+ // #ifdef VUE3
172
+ beforeUnmount() {
173
+ this.stopWatch && this.stopWatch()
174
+ this.signature.destroy()
175
+ this.signature = null
176
+ this.show = false;
177
+ },
178
+ // #endif
179
+ // #ifdef VUE2
180
+ beforeDestroy() {
181
+ this.stopWatch && this.stopWatch()
182
+ this.signature.destroy()
183
+ this.show = false;
184
+ this.signature = null
185
+ },
186
+ // #endif
187
+ // #endif
188
+ methods: {
189
+ // #ifdef MP-QQ
190
+ // toJSON() { return this },
191
+ // #endif
192
+ // #ifdef APP-PLUS
193
+ onPageFinish() {
194
+ this.$refs.webview.evalJS(`update(${JSON.stringify(this.param)})`)
195
+ },
196
+ onMessage(e = {}) {
197
+ const {
198
+ detail: {
199
+ data: [res]
200
+ }
201
+ } = e
202
+ if (res.event?.save) {
203
+ this.toDataURL = res.event.save
204
+ }
205
+ if (res.event?.changeSize) {
206
+ const {
207
+ width,
208
+ height
209
+ } = res.event.changeSize
210
+ }
211
+ if (res.event.hasOwnProperty('isEmpty')) {
212
+ this.risEmpty = res.event.isEmpty
213
+ }
214
+ if (res.event?.file) {
215
+ this.tempFilePath.push(res.event.file)
216
+ if (this.tempFilePath.length > 7) {
217
+ this.tempFilePath.shift()
218
+ }
219
+ return
220
+ }
221
+ if (res.event?.success) {
222
+ if (res.event.success) {
223
+ this.tempFilePath.push(res.event.success)
224
+ if (this.tempFilePath.length > 8) {
225
+ this.tempFilePath.shift()
226
+ }
227
+ this.toDataURL = this.tempFilePath.join('')
228
+ this.tempFilePath = []
229
+ } else {
230
+ this.$emit('fail', 'canvas no data')
231
+ }
232
+ return
233
+ }
234
+ },
235
+ // #endif
236
+ undo() {
237
+ // #ifdef APP-VUE || APP-NVUE
238
+ this.rundo += 1
239
+ // #endif
240
+ // #ifdef APP-NVUE
241
+ this.$refs.webview.evalJS(`undo()`)
242
+ // #endif
243
+ // #ifndef APP-VUE
244
+ if (this.signature)
245
+ this.signature.undo()
246
+ // #endif
247
+ },
248
+ clear() {
249
+ // #ifdef APP-VUE || APP-NVUE
250
+ this.rclear += 1
251
+ // #endif
252
+ // #ifdef APP-NVUE
253
+ this.$refs.webview.evalJS(`clear()`)
254
+ // #endif
255
+ // #ifndef APP-VUE
256
+ if (this.signature)
257
+ this.signature.clear()
258
+ // #endif
259
+ },
260
+ isEmpty() {
261
+ // #ifdef APP-NVUE
262
+ this.$refs.webview.evalJS(`isEmpty()`)
263
+ // #endif
264
+ // #ifdef APP-VUE || APP-NVUE
265
+ this.rempty += 1
266
+ // #endif
267
+ // #ifndef APP-VUE || APP-NVUE
268
+ return this.signature.isEmpty()
269
+ // #endif
270
+ },
271
+ canvasToTempFilePath(param) {
272
+ const isEmpty = this.isEmpty()
273
+ // #ifdef APP-NVUE
274
+ this.$refs.webview.evalJS(`save()`)
275
+ // #endif
276
+ // #ifdef APP-VUE || APP-NVUE
277
+ const stopURLWatch = this.$watch('toDataURL', (v, n) => {
278
+ if (v && v !== n) {
279
+ // if(param.pathType == 'url') {
280
+ base64ToPath(v).then(res => {
281
+ param.success({
282
+ tempFilePath: res,
283
+ isEmpty: this.risEmpty
284
+ })
285
+ })
286
+ // } else {
287
+ // param.success({tempFilePath: v,isEmpty: this.risEmpty })
288
+ // }
289
+ this.toDataURL = ''
290
+ }
291
+ stopURLWatch && stopURLWatch()
292
+ })
293
+ const {
294
+ fileType,
295
+ quality
296
+ } = param
297
+ const rsave = JSON.parse(this.rsave)
298
+ rsave.n++
299
+ rsave.fileType = fileType
300
+ rsave.quality = quality
301
+ this.rsave = JSON.stringify(rsave)
302
+ // #endif
303
+ // #ifndef APP-VUE || APP-NVUE
304
+ const success = (success) => param.success && param.success(success)
305
+ const fail = (err) => param.fail && param.fail(err)
306
+ const { canvas } = this.signature.canvas.get('el')
307
+ const {
308
+ backgroundColor,
309
+ landscape,
310
+ boundingBox
311
+ } = this
312
+ let width = this.signature.canvas.get('width')
313
+ let height = this.signature.canvas.get('height')
314
+ let x = 0
315
+ let y = 0
316
+
317
+ const canvasToTempFilePath = (image) => {
318
+ const context = uni.createCanvasContext('offscreen', this)
319
+ context.save()
320
+ context.setTransform(1, 0, 0, 1, 0, 0)
321
+ if (landscape) {
322
+ context.translate(0, width)
323
+ context.rotate(-Math.PI / 2)
324
+ }
325
+ if (backgroundColor) {
326
+ context.fillStyle = backgroundColor
327
+ context.fillRect(0, 0, width, height)
328
+ }
329
+ context.drawImage(image, 0, 0, width, height);
330
+
331
+ context.draw(false, () => {
332
+ toDataURL('offscreen', this, param).then((res) => {
333
+ const size = Math.max(width, height)
334
+ context.restore()
335
+ context.clearRect(0, 0, size, size)
336
+ success({
337
+ tempFilePath: res,
338
+ isEmpty
339
+ })
340
+ })
341
+ })
342
+ }
343
+ const next = () => {
344
+ // #ifndef MP-WEIXIN
345
+ const param = { x, y, width, height, canvas }
346
+ // #endif
347
+
348
+ // #ifdef MP-WEIXIN
349
+ const param = { x, y, width, height, canvas: this.useCanvas2d ? canvas : null}
350
+ // #endif
351
+ toDataURL(this.canvasId, this, param).then(canvasToTempFilePath).catch(fail)
352
+ }
353
+ // PC端小程序获取不到 ImageData 数据,长度为0
354
+ if (boundingBox && !isPC) {
355
+ this.signature.getContentBoundingBox(async res => {
356
+ this.offscreenWidth = width = res.width
357
+ this.offscreenHeight = height = res.height
358
+
359
+ x = res.startX
360
+ y = res.startY
361
+ await sleep(100)
362
+ next()
363
+ })
364
+ } else {
365
+ next()
366
+ }
367
+ // #endif
368
+ },
369
+ // #ifndef APP-PLUS
370
+ getContext() {
371
+ return getRect(`#${this.canvasId}`, {
372
+ context: this,
373
+ type: this.useCanvas2d ? 'fields' : 'boundingClientRect'
374
+ }).then(res => {
375
+ if (res) {
376
+ let { width, height, node: canvas, left, top, right} = res
377
+ let {pixelRatio} = uni.getSystemInfoSync()
378
+ let context;
379
+ if (canvas) {
380
+ context = canvas.getContext('2d')
381
+ canvas.width = width * pixelRatio;
382
+ canvas.height = height * pixelRatio;
383
+ } else {
384
+ pixelRatio = 1
385
+ context = uniContext(this.canvasId, this)
386
+ canvas = {
387
+ createImage,
388
+ toDataURL: () => toDataURL(this.canvasId, this),
389
+ requestAnimationFrame
390
+ }
391
+ }
392
+ // 支付宝小程序 使用stroke有个默认背景色
393
+ context.clearRect(0, 0, width, height)
394
+ return {
395
+ left,
396
+ top,
397
+ right,
398
+ width,
399
+ height,
400
+ context,
401
+ canvas,
402
+ pixelRatio
403
+ };
404
+ }
405
+ })
406
+ },
407
+ getTouch(e) {
408
+ if(isPC && this.canvasRect) {
409
+ e.touches = e.touches.map(item => {
410
+ return {
411
+ ...item,
412
+ x: item.clientX - this.canvasRect.left,
413
+ y: item.clientY - this.canvasRect.top,
414
+ }
415
+ })
416
+ }
417
+ return e
418
+ },
419
+ touchStart(e) {
420
+ if (!this.canvasEl) return
421
+ this.isStart = true
422
+ // 微信小程序PC端不支持事件,使用这方法模拟一下
423
+ if(isPC) {
424
+ getRect(`#${this.canvasId}`, {context: this}).then(res => {
425
+ this.canvasRect = res
426
+ this.canvasEl.dispatchEvent('touchstart', wrapEvent(this.getTouch(e)))
427
+ })
428
+ return
429
+ }
430
+ this.canvasEl.dispatchEvent('touchstart', wrapEvent(e))
431
+ },
432
+ touchMove(e) {
433
+ if (!this.canvasEl || !this.isStart && this.canvasEl) return
434
+ this.canvasEl.dispatchEvent('touchmove', wrapEvent(this.getTouch(e)))
435
+ },
436
+ touchEnd(e) {
437
+ if (!this.canvasEl) return
438
+ this.isStart = false
439
+ this.canvasEl.dispatchEvent('touchend', wrapEvent(e))
440
+ },
441
+ // #endif
442
+ }
443
+ }
444
+ </script>
445
+ <!-- #ifdef APP-VUE -->
446
+ <script module="sign" lang="renderjs">
447
+ import sign from './render'
448
+ export default sign
449
+ </script>
450
+ <!-- #endif -->
451
+ <style lang="scss">
452
+ .lime-signature,
453
+ .lime-signature__canvas {
454
+ /* #ifndef APP-NVUE */
455
+ position: relative;
456
+ width: 100%;
457
+ height: 100%;
458
+ /* #endif */
459
+ /* #ifdef APP-NVUE */
460
+ flex: 1;
461
+ /* #endif */
462
+ }
463
+ .mask {
464
+ position: absolute;
465
+ left: 0;
466
+ right: 0;
467
+ bottom: 0;
468
+ top: 0;
469
+ }
470
+ .offscreen {
471
+ position: fixed;
472
+ top: 0;
473
+ left: 9999px;
474
+ }
475
+ </style>
@@ -0,0 +1,118 @@
1
+ export const uniContext = (canvasId, context) => {
2
+ let ctx = uni.createCanvasContext(canvasId, context)
3
+ if (!ctx.uniDrawImage) {
4
+ ctx.uniDrawImage = ctx.drawImage
5
+ ctx.drawImage = (image, ...agrs) => {
6
+ ctx.uniDrawImage(image.src, ...agrs)
7
+ }
8
+ }
9
+ if (!ctx.getImageData) {
10
+ ctx.getImageData = (x, y, width, height) => {
11
+ return new Promise((resolve, reject) => {
12
+ // #ifdef MP || VUE2
13
+ if (context.proxy) context = context.proxy
14
+ // #endif
15
+ uni.canvasGetImageData({
16
+ canvasId,
17
+ x,
18
+ y,
19
+ width,
20
+ height,
21
+ success(res) {
22
+ resolve(res)
23
+ },
24
+ fail(error) {
25
+ reject(error)
26
+ }
27
+ }, context)
28
+ })
29
+ }
30
+ }
31
+
32
+ return ctx
33
+ }
34
+
35
+ class Image {
36
+ constructor() {
37
+ this.currentSrc = null
38
+ this.naturalHeight = 0
39
+ this.naturalWidth = 0
40
+ this.width = 0
41
+ this.height = 0
42
+ this.tagName = 'IMG'
43
+ }
44
+ set src(src) {
45
+ this.currentSrc = src
46
+ uni.getImageInfo({
47
+ src,
48
+ success: (res) => {
49
+ this.naturalWidth = this.width = res.width
50
+ this.naturalHeight = this.height = res.height
51
+ this.onload()
52
+ },
53
+ fail: () => {
54
+ this.onerror()
55
+ }
56
+ })
57
+ }
58
+ get src() {
59
+ return this.currentSrc
60
+ }
61
+ }
62
+
63
+ export const createImage = () => {
64
+ return new Image()
65
+ }
66
+ export function useCurrentPage() {
67
+ const pages = getCurrentPages();
68
+ return pages[pages.length - 1];
69
+ }
70
+ export const toDataURL = (canvasId, context, options = {}) => {
71
+ // #ifdef MP-QQ
72
+ // context = context.$scope
73
+ // #endif
74
+ // #ifdef MP-ALIPAY
75
+ context = ''
76
+ // #endif
77
+ return new Promise((resolve, reject) => {
78
+ let {canvas, width, height, destWidth = 0, destHeight = 0, x = 0, y = 0} = options
79
+
80
+ // #ifdef MP-ALIPAY
81
+ const {pixelRatio} =uni.getSystemInfoSync()
82
+ if(!destWidth || !destHeight) {
83
+ destWidth = width * pixelRatio;
84
+ destHeight = height * pixelRatio;
85
+ width = destWidth;
86
+ height = destHeight;
87
+ x = x * pixelRatio
88
+ y = y * pixelRatio
89
+ }
90
+ // #endif
91
+ const params = {
92
+ ...options,
93
+ canvasId,
94
+ id: canvasId,
95
+ // #ifdef MP-ALIPAY
96
+ x,
97
+ y,
98
+ width,
99
+ height,
100
+ destWidth,
101
+ destHeight,
102
+ // #endif
103
+ canvas,
104
+ success: (res) => {
105
+ resolve(res.tempFilePath)
106
+ },
107
+ fail: (err) => {
108
+ reject(err)
109
+ }
110
+ }
111
+ if(canvas && canvas.toTempFilePath) {
112
+ canvas.toTempFilePath(params)
113
+ } else {
114
+ uni.canvasToTempFilePath(params, context)
115
+ }
116
+ })
117
+
118
+ }
@@ -0,0 +1,59 @@
1
+ export default {
2
+ styles: String,
3
+ disableScroll: {
4
+ type: Boolean,
5
+ default: true
6
+ },
7
+ type: {
8
+ type: String,
9
+ default: '2d'
10
+ },
11
+ // 画笔颜色
12
+ penColor: {
13
+ type: String,
14
+ default: 'black'
15
+ },
16
+ penSize: {
17
+ type: Number,
18
+ default: 2
19
+ },
20
+ // 画板背景颜色
21
+ backgroundColor: String,
22
+ // 笔锋
23
+ openSmooth: Boolean,
24
+ // 画笔最小值
25
+ minLineWidth: {
26
+ type: Number,
27
+ default: 2
28
+ },
29
+ // 画笔最大值
30
+ maxLineWidth: {
31
+ type: Number,
32
+ default: 6
33
+ },
34
+ // 画笔达到最小宽度所需最小速度(px/ms),取值范围1.0-10.0,值越小,画笔越容易变细,笔锋效果会比较明显,可以自行调整查看效果,选出自己满意的值。
35
+ minSpeed: {
36
+ type: Number,
37
+ default: 1.5
38
+ },
39
+ // 相邻两线宽度增(减)量最大百分比,取值范围1-100,为了达到笔锋效果,画笔宽度会随画笔速度而改变,如果相邻两线宽度差太大,过渡效果就会很突兀,使用maxWidthDiffRate限制宽度差,让过渡效果更自然。可以自行调整查看效果,选出自己满意的值。
40
+ maxWidthDiffRate: {
41
+ type: Number,
42
+ default: 20
43
+ },
44
+ // 限制历史记录数,即最大可撤销数,传入0则关闭历史记录功能
45
+ maxHistoryLength: {
46
+ type: Number,
47
+ default: 20
48
+ },
49
+ beforeDelay: {
50
+ type: Number,
51
+ default: 10
52
+ },
53
+ landscape: {
54
+ type: Boolean
55
+ },
56
+ boundingBox: {
57
+ type: Boolean
58
+ }
59
+ }
@@ -0,0 +1,140 @@
1
+ // #ifdef APP-VUE
2
+ // import { Signature } from '@signature'
3
+ import { Signature } from './signature'
4
+ export default {
5
+ data() {
6
+ return {
7
+ canvasid: null,
8
+ signature: null,
9
+ observer: null,
10
+ options: {},
11
+ saveCount: 0,
12
+ }
13
+ },
14
+ mounted() {
15
+ this.$nextTick(this.init)
16
+ },
17
+ methods: {
18
+ init() {
19
+ const el = this.$refs.limeSignature||this.$ownerInstance.$el;
20
+ const canvas = document.createElement('canvas')
21
+ canvas.style = 'width: 100%; height: 100%;'
22
+ el.appendChild(canvas)
23
+ this.signature = new Signature({
24
+ el: canvas
25
+ })
26
+ this.signature.pen.setOption(this.options)
27
+ const width = this.signature.canvas.get('width')
28
+ const height = this.signature.canvas.get('height')
29
+
30
+ this.emit({
31
+ changeSize: {
32
+ width,
33
+ height
34
+ }
35
+ })
36
+ },
37
+ undo(v) {
38
+ if (v && this.signature) {
39
+ this.signature.undo()
40
+ }
41
+ },
42
+ clear(v) {
43
+ if (v && this.signature) {
44
+ this.signature.clear()
45
+ }
46
+ },
47
+ save(param) {
48
+ let {fileType = 'png', quality = 1, n} = JSON.parse(param)
49
+ const type = `image/${fileType}`.replace(/jpg/, 'jpeg');
50
+ if (n !== this.saveCount) {
51
+ this.saveCount = n;
52
+ const {backgroundColor, landscape, boundingBox} = this.options
53
+ const flag = landscape || backgroundColor || boundingBox
54
+ console.log('type', type)
55
+ console.log('flag', flag)
56
+ const image = this.signature.canvas.get('el').toDataURL(!flag && type, !flag && quality)
57
+ console.log('image', image.length)
58
+ if (flag) {
59
+ const canvas = document.createElement('canvas')
60
+ const pixelRatio = this.signature.canvas.get('pixelRatio')
61
+ let width = this.signature.canvas.get('width')
62
+ let height = this.signature.canvas.get('height')
63
+ let x = 0
64
+ let y = 0
65
+
66
+ const next = () => {
67
+ const size = [width, height]
68
+ console.log('size width', width)
69
+ console.log('size height', height)
70
+ console.log('size pixelRatio', pixelRatio)
71
+ if(landscape) {size.reverse()}
72
+ canvas.width = size[0] * pixelRatio
73
+ canvas.height = size[1] * pixelRatio
74
+ const param = [x, y, width, height, 0 , 0, width, height].map(item => item * pixelRatio)
75
+ const context = canvas.getContext('2d')
76
+ // context.scale(pixelRatio, pixelRatio)
77
+ if (landscape) {
78
+ context.translate(0, width * pixelRatio)
79
+ context.rotate(-Math.PI / 2)
80
+ }
81
+ console.log('backgroundColor', backgroundColor)
82
+ if (backgroundColor) {
83
+ context.fillStyle = backgroundColor
84
+ context.fillRect(0, 0, width * pixelRatio, height * pixelRatio)
85
+ }
86
+ // param
87
+ context.drawImage(this.signature.canvas.get('el'), ...param)
88
+ this.emit({
89
+ save: canvas.toDataURL(type, quality)
90
+ })
91
+ canvas.remove()
92
+ }
93
+ if(boundingBox) {
94
+ const res = this.signature.getContentBoundingBox()
95
+ width = res.width
96
+ height = res.height
97
+ x = res.startX
98
+ y = res.startY
99
+ next()
100
+ } else {
101
+ next()
102
+ }
103
+
104
+ } else {
105
+ this.emit({
106
+ save: image
107
+ })
108
+ }
109
+ }
110
+ },
111
+ isEmpty(v) {
112
+ if (v && this.signature) {
113
+ const isEmpty = this.signature.isEmpty()
114
+ this.emit({
115
+ isEmpty
116
+ })
117
+ }
118
+ },
119
+ emit(event) {
120
+ this.$ownerInstance.callMethod('onMessage', {
121
+ detail: {
122
+ data: [{
123
+ event
124
+ }]
125
+ }
126
+ })
127
+ },
128
+ update(v) {
129
+ if (v) {
130
+ if (this.signature) {
131
+ this.options = v
132
+ this.signature.pen.setOption(v)
133
+ } else {
134
+ this.options = v
135
+ }
136
+ }
137
+ }
138
+ }
139
+ }
140
+ // #endif
@@ -0,0 +1 @@
1
+ function t(t,e){var n=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter((function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable}))),n.push.apply(n,i)}return n}function e(e){for(var n=1;arguments.length>n;n++){var i=null!=arguments[n]?arguments[n]:{};n%2?t(Object(i),!0).forEach((function(t){a(e,t,i[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(i)):t(Object(i)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(i,t))}))}return e}function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function o(t,e){for(var n=0;e.length>n;n++){var i=e[n];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}function r(t,e,n){return e&&o(t.prototype,e),n&&o(t,n),Object.defineProperty(t,"prototype",{writable:!1}),t}function a(t,e,n){return e in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function s(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&h(t,e)}function u(t){return u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)},u(t)}function h(t,e){return h=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t},h(t,e)}function c(t,e){if(e&&("object"==typeof e||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}function l(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}();return function(){var n,i=u(t);if(e){var o=u(this).constructor;n=Reflect.construct(i,arguments,o)}else n=i.apply(this,arguments);return c(this,n)}}var v=function(t){var e=n(t);return null!==t&&"object"===e||"function"===e},f={}.toString,d=function(t,e){return f.call(t)==="[object "+e+"]"},y=function(t){return d(t,"String")},p=function(t){return d(t,"Number")},g=function(t){return d(t,"Function")},m=function(){function t(){i(this,t),this.__events=void 0,this.__events={}}return r(t,[{key:"on",value:function(t,e){if(t&&e){var n=this.__events[t]||[];n.push(e),this.__events[t]=n}}},{key:"emit",value:function(t,e){var n=this;if(v(t)&&(t=(e=t)&&e.type),t){var i=this.__events[t];i&&i.length&&i.forEach((function(t){t.call(n,e)}))}}},{key:"off",value:function(t,e){var n=this.__events,i=n[t];if(i&&i.length)if(e)for(var o=0,r=i.length;r>o;o++)i[o]===e&&(i.splice(o,1),o--);else delete n[t]}},{key:"getEvents",value:function(){return this.__events}}]),t}(),x=function(t){s(n,m);var e=l(n);function n(t,o){var r;return i(this,n),(r=e.call(this)).context=void 0,r.canvas=void 0,r.attrs=void 0,r.isCanvasElement=void 0,r.context=t,r.canvas=o.canvas||t.canvas||{width:o.width||0,height:o.height||0},r.attrs=o||{},r.isCanvasElement=!0,r}return r(n,[{key:"width",get:function(){return this.canvas.width},set:function(t){this.canvas.width=t}},{key:"height",get:function(){return this.canvas.height},set:function(t){this.canvas.height=t}},{key:"getContext",value:function(){return this.context}},{key:"getBoundingClientRect",value:function(){var t=this.attrs||{},e=t.top,n=t.right,i=t.width,o=t.height,r=t.left,a=t.bottom;return{top:void 0===e?0:e,width:void 0===i?0:i,right:void 0===n?0:n,height:void 0===o?0:o,bottom:void 0===a?0:a,left:void 0===r?0:r}}},{key:"setAttribute",value:function(t,e){this.attrs[t]=e}},{key:"addEventListener",value:function(t,e){this.on(t,e)}},{key:"removeEventListener",value:function(t,e){this.off(t,e)}},{key:"dispatchEvent",value:function(t,e){this.emit(t,e)}}]),n}();var w=function(t,e){return t?function(t){if(!t)return!1;if(1!==t.nodeType||!t.nodeName||"canvas"!==t.nodeName.toLowerCase())return!1;var e=!1;try{t.addEventListener("eventTest",(function(){e=!0})),t.dispatchEvent(new Event("eventTest"))}catch(t){e=!1}return e}(t.canvas)?t.canvas:new x(t,e):null};function b(t,e){try{return t.currentStyle?t.currentStyle[e]:document.defaultView&&document.defaultView.getComputedStyle(t,null).getPropertyValue(e)}catch(t){return{width:300,height:150}[e]}}function k(t,e){var n=e.get("el");if(!n)return t;var i=n.getBoundingClientRect(),o=i.top,r=void 0===o?0:o,a=i.left,s=void 0===a?0:a,u=parseFloat(b(n,"padding-left"))||0,h=parseFloat(b(n,"padding-top"))||0;return{x:t.x-s-u,y:t.y-r-h}}function _(t,e){var n=e.get("landscape");if(!n)return t;if(g(n))return n(t,e);var i=e.get("height");return{x:t.y,y:i-t.x}}var E=function(t,e){var n=t.touches;if(!n||!n.length)return[_(k({x:t.clientX,y:t.clientY},e),e)];n.length||(n=t.changedTouches||[]);for(var i=[],o=0,r=n.length;r>o;o++){var a=n[o],s=a.x,u=a.y,h=a.clientX,c=a.clientY,l=void 0;l=p(s)||p(u)?{x:s,y:u}:k({x:h,y:c},e),i.push(_(l,e))}return i},L=function(t,e){var n=e.x-t.x,i=e.y-t.y;return Math.abs(n)>Math.abs(i)?n>0?"right":"left":i>0?"down":"up"},M=function(t,e){var n=Math.abs(e.x-t.x),i=Math.abs(e.y-t.y);return Math.sqrt(n*n+i*i)},P=function(){function t(e){var n=this,o=e.canvas,r=e.el;i(this,t),this.processEvent=void 0,this.canvas=void 0,this.startTime=0,this.endTime=0,this.startPoints=null,this.startDistance=0,this.center=null,this.pressTimeout=void 0,this.eventType=null,this.direction=null,this.lastMoveTime=0,this.prevMovePoints=null,this.prevMoveTime=0,this.lastMovePoints=null,this.pinch=!1,this._click=function(t){var e=E(t,n.canvas);t.points=e,n.emitEvent("click",t)},this._start=function(t){var e,i,o=E(t,n.canvas);o&&(t.points=o,n.emitEvent("touchstart",t),n.reset(),n.startTime=Date.now(),n.startPoints=o,o.length>1?(n.startDistance=M(o[0],o[1]),n.center={x:(e=o[0]).x+((i=o[1]).x-e.x)/2,y:e.y+(i.y-e.y)/2}):n.pressTimeout=setTimeout((function(){var e="press",i="none";t.direction=i,n.emitStart(e,t),n.emitEvent(e,t),n.eventType=e,n.direction=i}),250))},this._move=function(t){var e=E(t,n.canvas);if(e){t.points=e,n.emitEvent("touchmove",t);var i=n.startPoints;if(i)if(e.length>1){var o=n.startDistance,r=M(e[0],e[1]);t.zoom=r/o,t.center=n.center,n.emitStart("pinch",t),n.emitEvent("pinch",t)}else{var a=e[0].x-i[0].x,s=e[0].y-i[0].y,u=n.direction||L(i[0],e[0]);n.direction=u;var h=n.getEventType(e);t.direction=u,t.deltaX=a,t.deltaY=s,n.emitStart(h,t),n.emitEvent(h,t);var c=n.lastMoveTime,l=Date.now();l-c>0&&(n.prevMoveTime=c,n.prevMovePoints=n.lastMovePoints,n.lastMoveTime=l,n.lastMovePoints=e)}}},this._end=function(t){var e=E(t,n.canvas);t.points=e,n.emitEnd(t),n.emitEvent("touchend",t);var i=n.lastMoveTime;if(100>Date.now()-i){var o=i-(n.prevMoveTime||n.startTime);if(o>0){var r=n.prevMovePoints||n.startPoints,a=n.lastMovePoints;if(!r||!a)return;var s=M(r[0],a[0])/o;s>.3&&(t.velocity=s,t.direction=L(r[0],a[0]),n.emitEvent("swipe",t))}}n.reset();var u=t.touches;u&&u.length>0&&n._start(t)},this._cancel=function(t){n.emitEvent("touchcancel",t),n.reset()},this.canvas=o,this.delegateEvent(r),this.processEvent={}}return r(t,[{key:"delegateEvent",value:function(t){t.addEventListener("click",this._click),t.addEventListener("touchstart",this._start),t.addEventListener("touchmove",this._move),t.addEventListener("touchend",this._end),t.addEventListener("touchcancel",this._cancel)}},{key:"emitEvent",value:function(t,e){this.canvas.emit(t,e)}},{key:"getEventType",value:function(t){var e,n=this.eventType,i=this.startTime,o=this.startPoints;if(n)return n;var r=this.canvas.__events.pan;if(r&&r.length){var a=Date.now();if(!o)return;e=a-i>250&&10>M(o[0],t[0])?"press":"pan"}else e="press";return this.eventType=e,e}},{key:"enable",value:function(t){this.processEvent[t]=!0}},{key:"isProcess",value:function(t){return this.processEvent[t]}},{key:"emitStart",value:function(t,e){this.isProcess(t)||(this.enable(t),this.emitEvent("".concat(t,"start"),e))}},{key:"emitEnd",value:function(t){}},{key:"clearPressTimeout",value:function(){this.pressTimeout&&(clearTimeout(this.pressTimeout),this.pressTimeout=null)}},{key:"reset",value:function(){this.clearPressTimeout(),this.startTime=0,this.startPoints=null,this.startDistance=0,this.direction=null,this.eventType=null,this.pinch=!1,this.prevMoveTime=0,this.prevMovePoints=null,this.lastMoveTime=0,this.lastMovePoints=null}}]),t}(),T=function(t){s(o,m);var e=l(o);function o(t){var n;i(this,o),(n=e.call(this))._attrs={},n._isWindow=void 0,n._attrs=Object.assign({},t),n._isWindow="undefined"!=typeof window,n._initPixelRatio(),n._initCanvas();return["createImage","toDataURL","requestAnimationFrame"].forEach((function(e){n._initAttrs(e,t.canvas||n.get("el"))})),n}return r(o,[{key:"get",value:function(t){return this._attrs[t]}},{key:"set",value:function(t,e){this._attrs[t]=e}},{key:"_initAttrs",value:function(t,e){var n=this;if(!this.get(t)){this.set(t,(function(){return e[t]?e[t].apply(e,arguments):n._isWindow?window[t]?(i=window)[t].apply(i,arguments):"createImage"==t?new Image:null:void 0;var i}))}}},{key:"_initCanvas",value:function(){var t,e,n=this.get("el"),i=this.get("context");if(!n&&!i)throw Error("请指定 id、el 或 context!");t=n?y(n)?(e=n)?document.getElementById(e):null:n:w(i,this._attrs),i&&t&&!t.getContext&&(t.getContext=function(){return i});var o=this.get("width")||function(t){var e=b(t,"width");return"auto"===e&&(e=t.offsetWidth),parseFloat(e)}(t)||t.width,r=this.get("height")||function(t){var e=b(t,"height");return"auto"===e&&(e=t.offsetHeight),parseFloat(e)}(t)||t.height;this.set("canvas",this),this.set("el",t),this.set("context",i||t.getContext("2d")),this.changeSize(o,r);var a=new P({canvas:this,el:t,parent:this.get("parent")});this.set("eventController",a)}},{key:"_initPixelRatio",value:function(){this.get("pixelRatio")||this.set("pixelRatio",window&&window.devicePixelRatio||1)}},{key:"changeSize",value:function(t,e){var i,o=this.get("pixelRatio"),r=this.get("el");(r.style&&(r.style.width=t+"px",r.style.height=e+"px"),(i=r)&&"object"===n(i)&&(1===i.nodeType&&i.nodeName||i.isCanvasElement))&&(r.width=t*o,r.height=e*o,1!==o&&this.get("context").scale(o,o));this.set("width",t),this.set("height",e)}},{key:"destroy",value:function(){if(!this.get("destroyed")){var t=this.get("el");t.width=0,t.height=0,this.clear(),this._attrs={},this.set("destroyed",!0)}}},{key:"clear",value:function(){}},{key:"isDestroyed",value:function(){return this.get("destroyed")}}]),o}();var S={penColor:"black",backgroundColor:"",openSmooth:!0,penSize:2,minLineWidth:2,maxLineWidth:6,minSpeed:1.5,maxWidthDiffRate:20,maxHistoryLength:20},D=null,O=function(){function t(e){var n=this;i(this,t),this.canAddHistory=!0,this.points=[],this.historyList=[],this.canvas=void 0,this._isEmpty=!0,this.active=!1,this.getLineWidth=function(t){var e=n.get("options"),i=e.minSpeed,o=e.minLineWidth,r=n.getMaxLineWidth();return Math.min(Math.max(r-(r-o)*t/Math.max(Math.min(i,10),1),o),r)},this.drawTrapezoid=function(t,e,i,o){var r=n.get("context");r.beginPath(),r.moveTo(Number(t.x.toFixed(1)),Number(t.y.toFixed(1))),r.lineTo(Number(e.x.toFixed(1)),Number(e.y.toFixed(1))),r.lineTo(Number(i.x.toFixed(1)),Number(i.y.toFixed(1))),r.lineTo(Number(o.x.toFixed(1)),Number(o.y.toFixed(1))),r.fillStyle=n.get("options").penColor,r.fill(),r.draw&&r.draw(!0)},this.drawNoSmoothLine=function(t,e){e.lastX=t.x+.5*(e.x-t.x),e.lastY=t.y+.5*(e.y-t.y),"number"==typeof t.lastX&&n.drawCurveLine(t.lastX,t.lastY,t.x,t.y,e.lastX,e.lastY,n.getMaxLineWidth())},this.drawCurveLine=function(t,e,i,o,r,a,s){s=Number(s.toFixed(1));var u=n.get("context");u.lineWidth=s,u.beginPath(),u.moveTo(Number(t.toFixed(1)),Number(e.toFixed(1))),u.quadraticCurveTo(Number(i.toFixed(1)),Number(o.toFixed(1)),Number(r.toFixed(1)),Number(a.toFixed(1))),u.stroke(),u.draw&&u.draw(!0)},this.getRadianData=function(t,e,n,i){var o=n-t,r=i-e;if(0===o)return{val:0,pos:-1};if(0===r)return{val:0,pos:1};var a=Math.abs(Math.atan(r/o));return n>t&&e>i||t>n&&i>e?{val:a,pos:1}:{val:a,pos:-1}},this.getRadianPoints=function(t,e,n,i){if(0===t.val)return 1===t.pos?[{x:e,y:n+i},{x:e,y:n-i}]:[{y:n,x:e+i},{y:n,x:e-i}];var o=Math.sin(t.val)*i,r=Math.cos(t.val)*i;return 1===t.pos?[{x:e+o,y:n+r},{x:e-o,y:n-r}]:[{x:e+o,y:n-r},{x:e-o,y:n+r}]},this.drawSmoothLine=function(t,e){var i=e.x-t.x,o=e.y-t.y;if(Math.abs(i)+Math.abs(o)>2?(e.lastX1=t.x+.3*i,e.lastY1=t.y+.3*o,e.lastX2=t.x+.7*i,e.lastY2=t.y+.7*o):(e.lastX1=e.lastX2=t.x+.5*i,e.lastY1=e.lastY2=t.y+.5*o),e.perLineWidth=(t.lineWidth+e.lineWidth)/2,"number"==typeof t.lastX1){if(n.drawCurveLine(t.lastX2,t.lastY2,t.x,t.y,e.lastX1,e.lastY1,e.perLineWidth),t.isFirstPoint)return;if(t.lastX1===t.lastX2&&t.lastY1===t.lastY2)return;var r=n.getRadianData(t.lastX1,t.lastY1,t.lastX2,t.lastY2),a=n.getRadianPoints(r,t.lastX1,t.lastY1,t.perLineWidth/2),s=n.getRadianPoints(r,t.lastX2,t.lastY2,e.perLineWidth/2);n.drawTrapezoid(a[0],s[0],s[1],a[1])}else e.isFirstPoint=!0},this.addHistory=function(){var t=n.get("options").maxHistoryLength;if(t&&n.canAddHistory)if(n.canAddHistory=!1,n.get("createImage")){var e=null;e=n.get("createImage")();var i=n.get("toDataURL")&&n.get("toDataURL")();y(i)?e.src=i:i.then((function(t){e.src=t})),e.onload=function(){var i=D;D=e,n.historyList.push(i),n.historyList=n.historyList.slice(-t)}}else n.historyList.length++},this.drawByImage=function(t){var e=n.get("context"),i=n.get("width"),o=n.get("height");e.clearRect(0,0,i,o);try{t&&e.drawImage(t,0,0,i,o),e.draw&&e.draw(!0)}catch(t){n.historyList.length=0}},this.isEmpty=function(){return n.get("options").maxHistoryLength>0?0===n.historyList.length:n._isEmpty},this.clear=function(){var t=n.get("context");t.clearRect(0,0,n.get("width"),n.get("height")),t.draw&&t.draw(),n._isEmpty=!0,D=null,n.historyList.length=0},this.undo=function(){if(0===n.get("options").maxHistoryLength&&n.clear(),n.get("createImage")&&n.historyList.length){var t=n.historyList.splice(-1)[0];n.drawByImage(t),0===n.historyList.length&&n.clear()}},this.canvas=e,this.canvas.set("pen",S),this.init()}return r(t,[{key:"getOption",value:function(){}},{key:"setOption",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e({},t),i=n.maxLineWidth;if(i&&t.penSize&&i==S.maxLineWidth){var o=Math.max(i,t.penSize);n.maxLineWidth=o}this.canvas.set("pen",Object.assign({},S,n))}},{key:"get",value:function(t){return this.canvas.get("options"==t?"pen":t)}},{key:"init",value:function(){var t=this;this.get("context").lineCap="round",this.canvas.on("touchstart",(function(e){return t.onDrawStart(e)})),this.canvas.on("touchmove",(function(e){return t.onDrawMove(e)})),this.canvas.on("touchend",(function(e){return t.onDrawEnd(e)}))}},{key:"drawBackground",value:function(){var t=this.get("context"),e=this.get("width"),n=this.get("height"),i=this.get("options"),o=i.backgroundColor,r=i.backgroundImage;o&&(t.fillStyle=o,t.fillRect(0,0,e,n),t.draw&&t.draw(!0)),r&&this.drawByImage(r)}},{key:"getContentBoundingBox",value:function(t){var e=this.get("pixelRatio"),n=this.get("width"),i=this.get("height"),o=this.get("el"),r="CANVAS"===o.nodeName,a=r?n:o.width,s=r?i:o.height;e=r?1:e;var u=function(n){for(var i=a,o=s,r=0,u=0,h=0;n.length>h;h+=4){if(n[h+3]>0){var c=h/4%a,l=Math.floor(h/4/a);i=Math.min(i,c),o=Math.min(o,l),r=Math.max(r,c),u=Math.max(u,l)}}var v={width:(r-i+1)/e,height:(u-o+1)/e,startX:i/e,startY:o/e};return t&&t(v),v};if("CANVAS"===o.nodeName){var h=document.createElement("canvas");h.width=n,h.height=i;var c=h.getContext("2d");c.drawImage(o,0,0,n,i);var l=c.getImageData(0,0,n,i).data;return u(l)}var f,d=this.get("context").getImageData(0,0,a,s);return v(f=d)&&g(f.then)&&g(f.catch)?(d.then((function(t){return u(t.data)})),null):u(d.data)}},{key:"remove",value:function(){var t=this;this.canvas.off("touchstart",(function(e){return t.onDrawStart(e)})),this.canvas.off("touchmove",(function(e){return t.onDrawMove(e)})),this.canvas.off("touchend",(function(e){return t.onDrawEnd(e)}))}},{key:"disableScroll",value:function(t){t.preventDefault&&this.get("options").disableScroll&&t.preventDefault()}},{key:"onDrawStart",value:function(t){this.disableScroll(t);var e=t.points;if(this.active){this.canAddHistory=!0,this.get("context").strokeStyle=this.get("options").penColor;var n=e[0];this.initPoint(n.x,n.y)}}},{key:"onDrawMove",value:function(t){if(this.disableScroll(t),this.active){var e=t.points[0];this.initPoint(e.x,e.y),this.onDraw()}}},{key:"onDrawEnd",value:function(t){this.active&&(this.addHistory(),this.canAddHistory=!0,this.points=[])}},{key:"onDraw",value:function(){var t=this,e=this.get("context");if(this.points.length>=2){e.lineWidth=this.get("options").penSize||2;var n=this.points.slice(-1)[0],i=this.points.slice(-2,-1)[0],o=function(){t._isEmpty=!1,t.get("options").openSmooth?t.drawSmoothLine(i,n):t.drawNoSmoothLine(i,n)},r=this.get("el").canvas;r&&r.requestAnimationFrame?r.requestAnimationFrame((function(){return o()})):"function"==typeof requestAnimationFrame?requestAnimationFrame((function(){return o()})):o()}}},{key:"getMaxLineWidth",value:function(){var t=this.get("options");return Math.min(t.penSize,t.maxLineWidth)}},{key:"initPoint",value:function(t,e){var n={x:t,y:e,t:Date.now()},i=this.points.slice(-1)[0];if(!i||i.t!==n.t&&(i.x!==t||i.y!==e)){if(this.get("options").openSmooth&&i){var o=this.points.slice(-2,-1)[0];if(n.distance=Math.sqrt(Math.pow(n.x-i.x,2)+Math.pow(n.y-i.y,2)),n.speed=n.distance/(n.t-i.t||.1),n.lineWidth=this.getLineWidth(n.speed),o&&o.lineWidth&&i.lineWidth){var r=(n.lineWidth-i.lineWidth)/i.lineWidth,a=this.get("options").maxWidthDiffRate/100;if(a=a>1?1:.01>a?.01:a,Math.abs(r)>a)n.lineWidth=i.lineWidth*(1+(r>0?a:-a))}}this.points.push(n),this.points=this.points.slice(-3)}}}]),t}(),W=function(){function t(e){i(this,t),this.canvas=void 0,this._ee=void 0,this.pen=void 0;var n=new T(e);n.set("parent",this),this.canvas=n,this._ee=new m,this.pen=new O(n),this.init()}return r(t,[{key:"init",value:function(){this.pen.active=!0}},{key:"destroy",value:function(){this.canvas.destroy()}},{key:"clear",value:function(){this.pen.clear()}},{key:"undo",value:function(){this.pen.undo()}},{key:"save",value:function(){}},{key:"getContentBoundingBox",value:function(t){return this.pen.getContentBoundingBox(t)}},{key:"isEmpty",value:function(){return this.pen.isEmpty()}},{key:"on",value:function(t,e){this._ee.on(t,e)}},{key:"emit",value:function(t,e){this._ee.emit(t,e)}},{key:"off",value:function(t,e){this._ee.off(t,e)}}]),t}();export default W;export{W as Signature};
@@ -0,0 +1,161 @@
1
+ export function compareVersion(v1, v2) {
2
+ v1 = v1.split('.')
3
+ v2 = v2.split('.')
4
+ const len = Math.max(v1.length, v2.length)
5
+ while (v1.length < len) {
6
+ v1.push('0')
7
+ }
8
+ while (v2.length < len) {
9
+ v2.push('0')
10
+ }
11
+ for (let i = 0; i < len; i++) {
12
+ const num1 = parseInt(v1[i], 10)
13
+ const num2 = parseInt(v2[i], 10)
14
+
15
+ if (num1 > num2) {
16
+ return 1
17
+ } else if (num1 < num2) {
18
+ return -1
19
+ }
20
+ }
21
+ return 0
22
+ }
23
+ let {platform, SDKVersion} = uni.getSystemInfoSync()
24
+ function gte(version) {
25
+ // #ifdef MP-ALIPAY
26
+ SDKVersion = my.SDKVersion
27
+ // #endif
28
+ return compareVersion(SDKVersion, version) >= 0;
29
+ }
30
+
31
+ export const isPC = /windows|mac/.test(platform)
32
+ export function canIUseCanvas2d() {
33
+ // #ifdef MP-WEIXIN
34
+ return gte('2.9.0');
35
+ // #endif
36
+ // #ifdef MP-ALIPAY
37
+ return gte('2.7.0');
38
+ // #endif
39
+ // #ifdef MP-TOUTIAO
40
+ return gte('1.78.0');
41
+ // #endif
42
+ return false
43
+ }
44
+
45
+
46
+ export const wrapEvent = (e) => {
47
+ if (!e) return;
48
+ if (!e.preventDefault) {
49
+ e.preventDefault = function() {};
50
+ }
51
+ return e;
52
+ }
53
+
54
+ export const requestAnimationFrame = (cb) => {
55
+ setTimeout(cb, 30)
56
+ }
57
+
58
+ // #ifdef MP
59
+ export const prefix = () => {
60
+ // #ifdef MP-TOUTIAO
61
+ return tt
62
+ // #endif
63
+ // #ifdef MP-WEIXIN
64
+ return wx
65
+ // #endif
66
+ // #ifdef MP-BAIDU
67
+ return swan
68
+ // #endif
69
+ // #ifdef MP-ALIPAY
70
+ return my
71
+ // #endif
72
+ // #ifdef MP-QQ
73
+ return qq
74
+ // #endif
75
+ // #ifdef MP-360
76
+ return qh
77
+ // #endif
78
+ }
79
+ // #endif
80
+
81
+ /**
82
+ * base64转路径
83
+ * @param {Object} base64
84
+ */
85
+ export function base64ToPath(base64) {
86
+ const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
87
+ return new Promise((resolve, reject) => {
88
+ // #ifdef MP
89
+ const p = prefix()
90
+ const fs = p.getFileSystemManager()
91
+ //自定义文件名
92
+ if (!format) {
93
+ reject(new Error('ERROR_BASE64SRC_PARSE'))
94
+ }
95
+ const time = new Date().getTime();
96
+ const filePath = `${p.env.USER_DATA_PATH}/${time}.${format}`;
97
+ fs.writeFile({
98
+ filePath,
99
+ data: base64.split(',')[1],
100
+ encoding: 'base64',
101
+ success() {
102
+ resolve(filePath)
103
+ },
104
+ fail(err) {
105
+ reject(err)
106
+ }
107
+ })
108
+ // #endif
109
+ // #ifdef APP-PLUS
110
+ const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
111
+ bitmap.loadBase64Data(base64, () => {
112
+ if (!format) {
113
+ reject(new Error('ERROR_BASE64SRC_PARSE'))
114
+ }
115
+ const time = new Date().getTime();
116
+ const filePath = `_doc/uniapp_temp/${time}.${format}`
117
+ bitmap.save(filePath, {},
118
+ () => {
119
+ bitmap.clear()
120
+ resolve(filePath)
121
+ },
122
+ (error) => {
123
+ bitmap.clear()
124
+ reject(error)
125
+ })
126
+ }, (error) => {
127
+ bitmap.clear()
128
+ reject(error)
129
+ })
130
+ // #endif
131
+ })
132
+ }
133
+
134
+
135
+ export function sleep(delay) {
136
+ return new Promise(resolve => setTimeout(resolve, delay))
137
+ }
138
+
139
+ export function getRect(selector, options = {}) {
140
+ const typeDefault = 'boundingClientRect'
141
+ const { context, type = typeDefault} = options
142
+ return new Promise((resolve, reject) => {
143
+ const dom = uni.createSelectorQuery().in(context).select(selector);
144
+ const result = (rect) => {
145
+ if(rect) {
146
+ resolve(rect)
147
+ } else {
148
+ reject()
149
+ }
150
+ }
151
+ if(type == typeDefault) {
152
+ dom[type](result).exec()
153
+ } else {
154
+ dom[type]({
155
+ node: true,
156
+ size: true,
157
+ rect: true
158
+ }, result).exec()
159
+ }
160
+ });
161
+ };