hy-app 0.4.13 → 0.5.0

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.
Files changed (211) hide show
  1. package/components/hy-action-sheet/hy-action-sheet.vue +155 -238
  2. package/components/hy-action-sheet/props.ts +68 -15
  3. package/components/hy-action-sheet/typing.d.ts +115 -115
  4. package/components/hy-address-picker/hy-address-picker.vue +185 -289
  5. package/components/hy-address-picker/props.ts +97 -21
  6. package/components/hy-address-picker/typing.d.ts +90 -89
  7. package/components/hy-avatar/hy-avatar.vue +121 -204
  8. package/components/hy-avatar/props.ts +76 -18
  9. package/components/hy-avatar/typing.d.ts +63 -62
  10. package/components/hy-back-top/hy-back-top.vue +65 -120
  11. package/components/hy-back-top/props.ts +57 -16
  12. package/components/hy-back-top/typing.d.ts +43 -42
  13. package/components/hy-badge/hy-badge.vue +66 -138
  14. package/components/hy-badge/props.ts +73 -17
  15. package/components/hy-badge/typing.d.ts +59 -58
  16. package/components/hy-button/hy-button.vue +226 -375
  17. package/components/hy-button/props.ts +129 -158
  18. package/components/hy-calendar/header.vue +48 -64
  19. package/components/hy-calendar/hy-calendar.vue +274 -438
  20. package/components/hy-calendar/month.vue +508 -516
  21. package/components/hy-calendar/props.ts +157 -35
  22. package/components/hy-calendar/typing.d.ts +129 -128
  23. package/components/hy-card/hy-card.vue +118 -240
  24. package/components/hy-card/index.scss +1 -2
  25. package/components/hy-card/props.ts +122 -27
  26. package/components/hy-card/typing.d.ts +119 -118
  27. package/components/hy-cell/hy-cell.vue +176 -258
  28. package/components/hy-cell/props.ts +71 -17
  29. package/components/hy-cell/typing.d.ts +87 -86
  30. package/components/hy-check-button/hy-check-button.vue +69 -139
  31. package/components/hy-check-button/props.ts +72 -18
  32. package/components/hy-check-button/typing.d.ts +74 -73
  33. package/components/hy-checkbox/hy-checkbox.vue +170 -263
  34. package/components/hy-checkbox/props.ts +94 -24
  35. package/components/hy-checkbox/typing.d.ts +72 -72
  36. package/components/hy-checkbox-group/hy-checkbox-group.vue +25 -100
  37. package/components/hy-checkbox-group/props.ts +80 -0
  38. package/components/hy-checkbox-group/typing.d.ts +65 -65
  39. package/components/hy-checkbox-item/hy-checkbox-item.vue +140 -177
  40. package/components/hy-checkbox-item/props.ts +24 -0
  41. package/components/hy-checkbox-item/typing.d.ts +4 -3
  42. package/components/hy-code-input/hy-code-input.vue +179 -262
  43. package/components/hy-code-input/props.ts +84 -18
  44. package/components/hy-code-input/typing.d.ts +71 -71
  45. package/components/hy-config-provider/hy-config-provider.vue +28 -50
  46. package/components/hy-config-provider/props.ts +26 -11
  47. package/components/hy-config-provider/typing.d.ts +20 -20
  48. package/components/hy-count-down/hy-count-down.vue +103 -131
  49. package/components/hy-count-down/props.ts +30 -8
  50. package/components/hy-count-down/typing.d.ts +25 -25
  51. package/components/hy-count-to/hy-count-to.vue +148 -213
  52. package/components/hy-count-to/props.ts +60 -15
  53. package/components/hy-count-to/typing.d.ts +46 -46
  54. package/components/hy-coupon/README.md +133 -0
  55. package/components/hy-coupon/hy-coupon.vue +180 -0
  56. package/components/hy-coupon/index.scss +553 -0
  57. package/components/hy-coupon/props.ts +129 -0
  58. package/components/hy-coupon/typing.d.ts +146 -0
  59. package/components/hy-datetime-picker/hy-datetime-picker.vue +415 -580
  60. package/components/hy-datetime-picker/props.ts +142 -32
  61. package/components/hy-datetime-picker/typing.d.ts +132 -132
  62. package/components/hy-divider/hy-divider.vue +90 -169
  63. package/components/hy-divider/props.ts +78 -19
  64. package/components/hy-divider/typing.d.ts +60 -60
  65. package/components/hy-dropdown/hy-dropdown.vue +37 -71
  66. package/components/hy-dropdown/props.ts +38 -15
  67. package/components/hy-dropdown/typing.d.ts +44 -44
  68. package/components/hy-dropdown-item/hy-dropdown-item.vue +141 -173
  69. package/components/hy-dropdown-item/props.ts +19 -8
  70. package/components/hy-empty/hy-empty.vue +75 -129
  71. package/components/hy-empty/props.ts +57 -15
  72. package/components/hy-empty/typing.d.ts +84 -84
  73. package/components/hy-flex/hy-flex.vue +33 -88
  74. package/components/hy-flex/props.ts +58 -0
  75. package/components/hy-flex/typing.d.ts +14 -16
  76. package/components/hy-float-button/hy-float-button.vue +289 -406
  77. package/components/hy-float-button/props.ts +109 -25
  78. package/components/hy-folding-panel/hy-folding-panel.vue +86 -374
  79. package/components/hy-folding-panel/props.ts +40 -15
  80. package/components/hy-folding-panel/typing.d.ts +52 -63
  81. package/components/hy-folding-panel-item/hy-folding-panel-item.vue +186 -228
  82. package/components/hy-folding-panel-item/index.scss +87 -0
  83. package/components/hy-folding-panel-item/props.ts +81 -0
  84. package/components/hy-folding-panel-item/typing.d.ts +23 -0
  85. package/components/hy-form/hy-form.vue +172 -212
  86. package/components/hy-form/props.ts +37 -0
  87. package/components/hy-form/typing.d.ts +68 -61
  88. package/components/hy-form-group/typing.d.ts +74 -74
  89. package/components/hy-form-item/hy-form-item.vue +100 -129
  90. package/components/hy-form-item/props.ts +25 -0
  91. package/components/hy-form-item/typing.d.ts +40 -37
  92. package/components/hy-grid/hy-grid.vue +76 -132
  93. package/components/hy-grid/props.ts +58 -16
  94. package/components/hy-grid/typing.d.ts +66 -66
  95. package/components/hy-icon/hy-icon.vue +84 -161
  96. package/components/hy-icon/props.ts +76 -22
  97. package/components/hy-icon/typing.d.ts +83 -82
  98. package/components/hy-image/hy-image.vue +142 -272
  99. package/components/hy-image/props.ts +105 -23
  100. package/components/hy-image/typing.d.ts +84 -87
  101. package/components/hy-input/hy-input.vue +230 -421
  102. package/components/hy-input/props.ts +183 -35
  103. package/components/hy-input/typing.d.ts +169 -169
  104. package/components/hy-line/hy-line.vue +34 -72
  105. package/components/hy-line/props.ts +41 -10
  106. package/components/hy-line/typing.d.ts +29 -29
  107. package/components/hy-line-progress/hy-line-progress.vue +66 -101
  108. package/components/hy-line-progress/props.ts +31 -10
  109. package/components/hy-line-progress/typing.d.ts +29 -29
  110. package/components/hy-list/hy-list.vue +151 -220
  111. package/components/hy-list/props.ts +67 -16
  112. package/components/hy-list/typing.d.ts +52 -52
  113. package/components/hy-loading/hy-loading.vue +63 -119
  114. package/components/hy-loading/props.ts +63 -15
  115. package/components/hy-loading/typing.d.ts +49 -49
  116. package/components/hy-menu/hy-menu.vue +124 -166
  117. package/components/hy-menu/props.ts +42 -10
  118. package/components/hy-menu/typing.d.ts +60 -60
  119. package/components/hy-modal/hy-modal.vue +127 -218
  120. package/components/hy-modal/props.ts +89 -24
  121. package/components/hy-navbar/hy-navbar.vue +104 -177
  122. package/components/hy-navbar/props.ts +76 -22
  123. package/components/hy-navbar/typing.d.ts +81 -81
  124. package/components/hy-notice-bar/hy-notice-bar.vue +67 -144
  125. package/components/hy-notice-bar/props.ts +80 -19
  126. package/components/hy-notice-bar/typing.d.ts +62 -62
  127. package/components/hy-notify/hy-notify.vue +128 -177
  128. package/components/hy-notify/props.ts +49 -12
  129. package/components/hy-notify/typing.d.ts +45 -41
  130. package/components/hy-number-step/hy-number-step.vue +281 -394
  131. package/components/hy-number-step/props.ts +110 -27
  132. package/components/hy-number-step/typing.d.ts +120 -120
  133. package/components/hy-overlay/hy-overlay.vue +39 -66
  134. package/components/hy-overlay/props.ts +31 -8
  135. package/components/hy-pagination/hy-pagination.vue +100 -155
  136. package/components/hy-pagination/props.ts +53 -13
  137. package/components/hy-picker/hy-picker.vue +309 -430
  138. package/components/hy-picker/index.scss +8 -12
  139. package/components/hy-picker/props.ts +110 -26
  140. package/components/hy-popover/hy-popover.vue +190 -252
  141. package/components/hy-popover/props.ts +48 -10
  142. package/components/hy-popup/hy-popup.vue +162 -248
  143. package/components/hy-popup/props.ts +82 -18
  144. package/components/hy-price/hy-price.vue +45 -104
  145. package/components/hy-price/props.ts +52 -12
  146. package/components/hy-price/typing.d.ts +41 -36
  147. package/components/hy-qrcode/hy-qrcode.vue +115 -185
  148. package/components/hy-qrcode/props.ts +68 -18
  149. package/components/hy-qrcode/typing.d.ts +67 -66
  150. package/components/hy-radio/hy-radio.vue +161 -259
  151. package/components/hy-radio/props.ts +95 -25
  152. package/components/hy-radio/typing.d.ts +85 -84
  153. package/components/hy-rate/hy-rate.vue +185 -270
  154. package/components/hy-rate/props.ts +76 -18
  155. package/components/hy-rate/typing.d.ts +61 -60
  156. package/components/hy-read-more/hy-read-more.vue +93 -136
  157. package/components/hy-read-more/props.ts +43 -13
  158. package/components/hy-scroll-list/hy-scroll-list.vue +81 -102
  159. package/components/hy-scroll-list/props.ts +22 -11
  160. package/components/hy-search/hy-search.vue +155 -284
  161. package/components/hy-search/props.ts +130 -25
  162. package/components/hy-signature/hy-signature.vue +491 -635
  163. package/components/hy-signature/props.ts +115 -26
  164. package/components/hy-signature/typing.d.ts +138 -138
  165. package/components/hy-slider/hy-slider.vue +388 -477
  166. package/components/hy-slider/props.ts +75 -19
  167. package/components/hy-steps/hy-steps.vue +212 -279
  168. package/components/hy-steps/props.ts +47 -13
  169. package/components/hy-submit-bar/hy-submit-bar.vue +137 -222
  170. package/components/hy-submit-bar/props.ts +89 -20
  171. package/components/hy-submit-bar/typing.d.ts +86 -85
  172. package/components/hy-subsection/hy-subsection.vue +132 -185
  173. package/components/hy-subsection/props.ts +50 -17
  174. package/components/hy-subsection/typing.d.ts +52 -52
  175. package/components/hy-swipe-action/hy-swipe-action.vue +228 -283
  176. package/components/hy-swipe-action/props.ts +43 -18
  177. package/components/hy-swipe-action/typing.d.ts +46 -46
  178. package/components/hy-swiper/hy-swiper.vue +159 -286
  179. package/components/hy-swiper/props.ts +126 -28
  180. package/components/hy-swiper/typing.d.ts +115 -115
  181. package/components/hy-switch/hy-switch.vue +112 -176
  182. package/components/hy-switch/props.ts +60 -15
  183. package/components/hy-switch/typing.d.ts +63 -63
  184. package/components/hy-tabBar/hy-tabBar.vue +64 -60
  185. package/components/hy-tabs/hy-tabs.vue +277 -380
  186. package/components/hy-tabs/props.ts +75 -18
  187. package/components/hy-tag/hy-tag.vue +111 -204
  188. package/components/hy-tag/props.ts +81 -19
  189. package/components/hy-text/hy-text.vue +200 -322
  190. package/components/hy-text/props.ts +107 -28
  191. package/components/hy-textarea/hy-textarea.vue +147 -256
  192. package/components/hy-textarea/props.ts +112 -25
  193. package/components/hy-textarea/typing.d.ts +42 -42
  194. package/components/hy-toast/hy-toast.vue +135 -143
  195. package/components/hy-tooltip/hy-tooltip.vue +220 -306
  196. package/components/hy-tooltip/props.ts +79 -15
  197. package/components/hy-transition/hy-transition.vue +111 -138
  198. package/components/hy-transition/props.ts +30 -8
  199. package/components/hy-upload/hy-upload.vue +320 -469
  200. package/components/hy-upload/props.ts +130 -27
  201. package/components/hy-warn/hy-warn.vue +80 -129
  202. package/components/hy-warn/props.ts +47 -12
  203. package/components/hy-waterfall/hy-waterfall.vue +139 -163
  204. package/components/hy-waterfall/props.ts +19 -7
  205. package/components/hy-watermark/hy-watermark.vue +762 -870
  206. package/components/hy-watermark/props.ts +103 -22
  207. package/global.d.ts +2 -0
  208. package/libs/css/theme.scss +3 -3
  209. package/package.json +2 -2
  210. package/web-types.json +1 -1
  211. package/components/hy-folding-panel/index.scss +0 -9
@@ -1,781 +1,637 @@
1
1
  <template>
2
- <view :class="['hy-signature', customClass]" :style="customStyle">
3
- <view
4
- class="hy-signature__content"
5
- :style="{ borderRadius: addUnit(round) }"
6
- >
7
- <!-- #ifdef MP-WEIXIN -->
8
- <canvas
9
- class="hy-signature__content-canvas"
10
- :style="canvasStyle"
11
- :width="canvasState.canvasWidth"
12
- :height="canvasState.canvasHeight"
13
- :canvas-id="canvasId"
14
- :id="canvasId"
15
- :disable-scroll="disableScroll"
16
- @touchstart="startDrawing"
17
- @touchend="stopDrawing"
18
- @touchmove="draw"
19
- type="2d"
20
- />
21
- <!-- #endif -->
22
- <!-- #ifndef MP-WEIXIN -->
23
- <canvas
24
- class="hy-signature__content-canvas"
25
- :canvas-id="canvasId"
26
- :style="canvasStyle"
27
- :width="canvasState.canvasWidth"
28
- :height="canvasState.canvasHeight"
29
- :id="canvasId"
30
- :disable-scroll="disableScroll"
31
- @touchstart="startDrawing"
32
- @touchend="stopDrawing"
33
- @touchmove="draw"
34
- />
35
- <!-- #endif -->
2
+ <view :class="['hy-signature', customClass]" :style="customStyle">
3
+ <view class="hy-signature__content" :style="{ borderRadius: addUnit(round) }">
4
+ <!-- #ifdef MP-WEIXIN -->
5
+ <canvas
6
+ class="hy-signature__content-canvas"
7
+ :style="canvasStyle"
8
+ :width="canvasState.canvasWidth"
9
+ :height="canvasState.canvasHeight"
10
+ :canvas-id="canvasId"
11
+ :id="canvasId"
12
+ :disable-scroll="disableScroll"
13
+ @touchstart="startDrawing"
14
+ @touchend="stopDrawing"
15
+ @touchmove="draw"
16
+ type="2d"
17
+ />
18
+ <!-- #endif -->
19
+ <!-- #ifndef MP-WEIXIN -->
20
+ <canvas
21
+ class="hy-signature__content-canvas"
22
+ :canvas-id="canvasId"
23
+ :style="canvasStyle"
24
+ :width="canvasState.canvasWidth"
25
+ :height="canvasState.canvasHeight"
26
+ :id="canvasId"
27
+ :disable-scroll="disableScroll"
28
+ @touchstart="startDrawing"
29
+ @touchend="stopDrawing"
30
+ @touchmove="draw"
31
+ />
32
+ <!-- #endif -->
33
+ </view>
34
+ <view class="hy-signature__footer">
35
+ <slot
36
+ v-if="$slots.footer"
37
+ name="footer"
38
+ :clear="clear"
39
+ :confirm="confirmSignature"
40
+ :current-step="currentStep"
41
+ :revoke="revoke"
42
+ :restore="restore"
43
+ :can-undo="lines.length > 0"
44
+ :can-redo="redoLines.length > 0"
45
+ :history-list="lines"
46
+ >
47
+ </slot>
48
+ <template v-else>
49
+ <block v-if="enableHistory">
50
+ <hy-button
51
+ size="small"
52
+ plain
53
+ shape="circle"
54
+ @click="revoke"
55
+ :disabled="lines.length <= 0"
56
+ :text="revokeText"
57
+ ></hy-button>
58
+ <hy-button
59
+ size="small"
60
+ plain
61
+ shape="circle"
62
+ @click="restore"
63
+ :disabled="redoLines.length <= 0"
64
+ :text="restoreText"
65
+ ></hy-button>
66
+ </block>
67
+ <hy-button
68
+ size="small"
69
+ plain
70
+ shape="circle"
71
+ @click="clear"
72
+ :text="clearText"
73
+ ></hy-button>
74
+ <hy-button
75
+ size="small"
76
+ shape="circle"
77
+ @click="confirmSignature"
78
+ :text="confirmText"
79
+ ></hy-button>
80
+ </template>
81
+ </view>
36
82
  </view>
37
- <view class="hy-signature__footer">
38
- <slot
39
- name="footer"
40
- :clear="clear"
41
- :confirm="confirmSignature"
42
- :current-step="currentStep"
43
- :revoke="revoke"
44
- :restore="restore"
45
- :can-undo="lines.length > 0"
46
- :can-redo="redoLines.length > 0"
47
- :history-list="lines"
48
- >
49
- <block v-if="enableHistory">
50
- <hy-button
51
- size="small"
52
- plain
53
- shape="circle"
54
- @click="revoke"
55
- :disabled="lines.length <= 0"
56
- :text="revokeText"
57
- ></hy-button>
58
- <hy-button
59
- size="small"
60
- plain
61
- shape="circle"
62
- @click="restore"
63
- :disabled="redoLines.length <= 0"
64
- :text="restoreText"
65
- ></hy-button>
66
- </block>
67
- <hy-button
68
- size="small"
69
- plain
70
- shape="circle"
71
- @click="clear"
72
- :text="clearText"
73
- ></hy-button>
74
- <hy-button
75
- size="small"
76
- shape="circle"
77
- @click="confirmSignature"
78
- :text="confirmText"
79
- ></hy-button>
80
- </slot>
81
- </view>
82
- </view>
83
83
  </template>
84
84
 
85
85
  <script lang="ts">
86
86
  export default {
87
- name: "hy-signature",
88
- options: {
89
- addGlobalClass: true,
90
- virtualHost: true,
91
- styleIsolation: "shared",
92
- },
93
- };
87
+ name: 'hy-signature',
88
+ options: {
89
+ addGlobalClass: true,
90
+ virtualHost: true,
91
+ styleIsolation: 'shared'
92
+ }
93
+ }
94
94
  </script>
95
95
 
96
96
  <script lang="ts" setup>
97
- import {
98
- computed,
99
- getCurrentInstance,
100
- onBeforeMount,
101
- onMounted,
102
- reactive,
103
- ref,
104
- watch,
105
- } from "vue";
106
- import type { CSSProperties, PropType } from "vue";
107
- import { addUnit, getRect, guid } from "../../libs";
108
- import type {
109
- SignatureExpose,
110
- SignatureResult,
111
- Point,
112
- Line,
113
- ISignatureEmits,
114
- } from "./typing";
97
+ import { computed, getCurrentInstance, onBeforeMount, onMounted, reactive, ref, watch } from 'vue'
98
+ import type { CSSProperties } from 'vue'
99
+ import { addUnit, getRect, guid } from '../../libs'
100
+ import type { SignatureExpose, SignatureResult, Point, Line, ISignatureEmits } from './typing'
115
101
  // #ifdef MP-WEIXIN
116
- import { canvas2dAdapter } from "./canvasHelper";
102
+ import { canvas2dAdapter } from './canvasHelper'
117
103
  // #endif
104
+ import signatureProps from './props'
118
105
 
119
106
  // 组件
120
- import HyButton from "../hy-button/hy-button.vue";
107
+ import HyButton from '../hy-button/hy-button.vue'
121
108
 
122
109
  /**
123
110
  * 用于签名场景,基于 Canvas 实现的签名组件。提供了基础签名、历史记录、笔锋效果等功能。
124
111
  * @displayName hy-signature
125
112
  */
126
- defineOptions({});
127
-
128
- // const props = withDefaults(defineProps<IProps>(), defaultProps);
129
- const props = defineProps({
130
- /** 签名笔颜色 */
131
- penColor: {
132
- type: String,
133
- default: "#000",
134
- },
135
- /** 签名笔宽度 */
136
- lineWidth: {
137
- type: Number,
138
- default: 3,
139
- },
140
- /** 清空按钮的文本 */
141
- clearText: {
142
- type: String,
143
- default: "清空",
144
- },
145
- /** 撤回按钮的文本 */
146
- revokeText: {
147
- type: String,
148
- default: "撤销",
149
- },
150
- /** 恢复按钮的文本 */
151
- restoreText: {
152
- type: String,
153
- default: "恢复",
154
- },
155
- /** 确认按钮的文本 */
156
- confirmText: {
157
- type: String,
158
- default: "确认",
159
- },
160
- /** 目标文件的类型 */
161
- fileType: {
162
- type: String,
163
- default: "png",
164
- },
165
- /** 签名笔颜色 */
166
- quality: {
167
- type: Number,
168
- default: 1,
169
- },
170
- /** 目标文件的质量 */
171
- exportScale: {
172
- type: Number,
173
- default: 1,
174
- },
175
- /** 是否禁用签名板 */
176
- disabled: {
177
- type: Boolean,
178
- default: false,
179
- },
180
- /** 画布的高度 */
181
- height: {
182
- type: Number,
183
- default: 1,
184
- },
185
- /** 画布的宽度 */
186
- width: {
187
- type: Number,
188
- default: 1,
189
- },
190
- /** 边框圆角 */
191
- round: {
192
- type: String,
193
- default: "10rpx",
194
- },
195
- /** 画板的背景色 */
196
- backgroundColor: String,
197
- /** 是否禁用画布滚动 */
198
- disableScroll: {
199
- type: Boolean,
200
- default: true,
201
- },
202
- /** 是否开启历史记录 */
203
- enableHistory: {
204
- type: Boolean,
205
- default: false,
206
- },
207
- /** 撤回和恢复的步长 */
208
- step: {
209
- type: Number,
210
- default: 1,
211
- },
212
- /** 撤回按钮的文本 */
213
- undoText: String,
214
- /** 恢复按钮的文本 */
215
- redoText: String,
216
- /** 是否启用压感模式 */
217
- pressure: {
218
- type: Boolean,
219
- default: false,
220
- },
221
- /** 压感模式下笔画最小宽度 */
222
- minWidth: {
223
- type: Number,
224
- default: 2,
225
- },
226
- /** 压感模式下笔画最大宽度 */
227
- maxWidth: {
228
- type: Number,
229
- default: 6,
230
- },
231
- /** 最小速度阈值,影响压感模式下的笔画宽度变化 */
232
- minSpeed: {
233
- type: Number,
234
- default: 1.5,
235
- },
236
- /** 定义需要用到的外部样式 */
237
- customStyle: {
238
- type: Object as PropType<CSSProperties>,
239
- },
240
- /** 自定义外部类名 */
241
- customClass: String,
242
- });
243
- const emit = defineEmits<ISignatureEmits>();
244
- const instance = getCurrentInstance() as any;
245
- const canvasId = ref<string>(`signature${guid()}`); // canvas 组件的唯一标识符
246
- let canvas: null = null; //canvas对象 微信小程序生成图片必须传入
247
- const drawing = ref<boolean>(false); // 是否正在绘制
248
- const pixelRatio = ref<number>(1); // 像素比
113
+ defineOptions({})
114
+
115
+ const props = defineProps(signatureProps)
116
+ const emit = defineEmits<ISignatureEmits>()
117
+ const instance = getCurrentInstance() as any
118
+ const canvasId = ref<string>(`signature${guid()}`) // canvas 组件的唯一标识符
119
+ let canvas: null = null //canvas对象 微信小程序生成图片必须传入
120
+ const drawing = ref<boolean>(false) // 是否正在绘制
121
+ const pixelRatio = ref<number>(1) // 像素比
249
122
 
250
123
  const canvasState = reactive({
251
- canvasWidth: 0,
252
- canvasHeight: 0,
253
- ctx: null as UniApp.CanvasContext | null, // canvas上下文
254
- });
124
+ canvasWidth: 0,
125
+ canvasHeight: 0,
126
+ ctx: null as UniApp.CanvasContext | null // canvas上下文
127
+ })
255
128
 
256
129
  watch(
257
- () => props.penColor,
258
- () => {
259
- setLine();
260
- },
261
- );
130
+ () => props.penColor,
131
+ () => {
132
+ setLine()
133
+ }
134
+ )
262
135
 
263
136
  watch(
264
- () => props.lineWidth,
265
- () => {
266
- setLine();
267
- },
268
- );
137
+ () => props.lineWidth,
138
+ () => {
139
+ setLine()
140
+ }
141
+ )
269
142
 
270
143
  const canvasStyle = computed(() => {
271
- const style: CSSProperties = {};
272
- if (props.width) {
273
- style.width = addUnit(props.width);
274
- }
144
+ const style: CSSProperties = {}
145
+ if (props.width) {
146
+ style.width = addUnit(props.width)
147
+ }
275
148
 
276
- if (props.height) {
277
- style.height = addUnit(props.height);
278
- }
149
+ if (props.height) {
150
+ style.height = addUnit(props.height)
151
+ }
279
152
 
280
- return `${style}`;
281
- });
153
+ return `${style}`
154
+ })
282
155
 
283
- const disableScroll = computed(() => props.disableScroll);
284
- const enableHistory = computed(() => props.enableHistory);
156
+ const disableScroll = computed(() => props.disableScroll)
157
+ const enableHistory = computed(() => props.enableHistory)
285
158
 
286
- const lines = ref<Line[]>([]); // 保存所有线条
287
- const redoLines = ref<Line[]>([]); // 保存撤销的线条
288
- const currentLine = ref<Line>(); // 当前正在绘制的线
289
- const currentStep = ref(0); // 当前步骤
159
+ const lines = ref<Line[]>([]) // 保存所有线条
160
+ const redoLines = ref<Line[]>([]) // 保存撤销的线条
161
+ const currentLine = ref<Line>() // 当前正在绘制的线
162
+ const currentStep = ref(0) // 当前步骤
290
163
 
291
164
  /**
292
165
  * @description 添加计算笔画宽度的方法
293
166
  * */
294
167
  function calculateLineWidth(speed: number): number {
295
- if (!props.pressure) return props.lineWidth;
296
-
297
- const minSpeed = props.minSpeed || 1.5;
298
- const limitedSpeed = Math.min(minSpeed * 10, Math.max(minSpeed, speed));
299
- const addWidth =
300
- ((props.maxWidth - props.minWidth) * (limitedSpeed - minSpeed)) / minSpeed;
301
- const lineWidth = Math.max(props.maxWidth - addWidth, props.minWidth);
302
- return Math.min(lineWidth, props.maxWidth);
168
+ if (!props.pressure) return props.lineWidth
169
+
170
+ const minSpeed = props.minSpeed || 1.5
171
+ const limitedSpeed = Math.min(minSpeed * 10, Math.max(minSpeed, speed))
172
+ const addWidth = ((props.maxWidth - props.minWidth) * (limitedSpeed - minSpeed)) / minSpeed
173
+ const lineWidth = Math.max(props.maxWidth - addWidth, props.minWidth)
174
+ return Math.min(lineWidth, props.maxWidth)
303
175
  }
304
176
 
305
177
  /**
306
178
  * @description 获取默认笔画宽度
307
179
  * */
308
180
  const getDefaultLineWidth = () => {
309
- if (props.pressure) {
310
- // 在压感模式下,使用最大和最小宽度的平均值作为默认值
311
- return (props.maxWidth + props.minWidth) / 2;
312
- }
313
- return props.lineWidth;
314
- };
181
+ if (props.pressure) {
182
+ // 在压感模式下,使用最大和最小宽度的平均值作为默认值
183
+ return (props.maxWidth + props.minWidth) / 2
184
+ }
185
+ return props.lineWidth
186
+ }
315
187
 
316
188
  /**
317
189
  * @description 开始画线
318
190
  * */
319
191
  const startDrawing = (e: any) => {
320
- e.preventDefault();
321
- drawing.value = true;
322
- setLine();
323
- emit("start", e);
324
-
325
- // 创建新线条,同时保存当前的所有绘制参数
326
- const { x, y } = e.touches[0];
327
- currentLine.value = {
328
- points: [
329
- {
330
- x,
331
- y,
332
- t: Date.now(), // 使用 t 替换 width
333
- },
334
- ],
335
- color: props.penColor,
336
- width: getDefaultLineWidth(),
337
- backgroundColor: props.backgroundColor,
338
- isPressure: props.pressure, // 添加笔锋模式标记
339
- };
340
-
341
- // 清空重做记录
342
- redoLines.value = [];
343
- draw(e);
344
- };
192
+ e.preventDefault()
193
+ drawing.value = true
194
+ setLine()
195
+ emit('start', e)
196
+
197
+ // 创建新线条,同时保存当前的所有绘制参数
198
+ const { x, y } = e.touches[0]
199
+ currentLine.value = {
200
+ points: [
201
+ {
202
+ x,
203
+ y,
204
+ t: Date.now() // 使用 t 替换 width
205
+ }
206
+ ],
207
+ color: props.penColor,
208
+ width: getDefaultLineWidth(),
209
+ backgroundColor: props.backgroundColor,
210
+ isPressure: props.pressure // 添加笔锋模式标记
211
+ }
212
+
213
+ // 清空重做记录
214
+ redoLines.value = []
215
+ draw(e)
216
+ }
345
217
 
346
218
  /**
347
219
  * @description 结束画线
348
220
  * */
349
221
  const stopDrawing = (e: TouchEvent) => {
350
- e.preventDefault();
351
- drawing.value = false;
352
- if (currentLine.value) {
353
- // 保存完整的线条信息,包括所有点的参数
354
- lines.value.push({
355
- ...currentLine.value,
356
- points: currentLine.value.points.map((point) => ({
357
- ...point,
358
- t: point.t,
359
- speed: point.speed,
360
- distance: point.distance,
361
- lineWidth: point.lineWidth,
362
- lastX1: point.lastX1,
363
- lastY1: point.lastY1,
364
- lastX2: point.lastX2,
365
- lastY2: point.lastY2,
366
- isFirstPoint: point.isFirstPoint,
367
- })),
368
- });
369
- currentStep.value = lines.value.length;
370
- }
371
- currentLine.value = undefined;
372
- const { ctx } = canvasState;
373
- if (ctx) ctx.beginPath();
374
- emit("end", e);
375
- };
222
+ e.preventDefault()
223
+ drawing.value = false
224
+ if (currentLine.value) {
225
+ // 保存完整的线条信息,包括所有点的参数
226
+ lines.value.push({
227
+ ...currentLine.value,
228
+ points: currentLine.value.points.map((point) => ({
229
+ ...point,
230
+ t: point.t,
231
+ speed: point.speed,
232
+ distance: point.distance,
233
+ lineWidth: point.lineWidth,
234
+ lastX1: point.lastX1,
235
+ lastY1: point.lastY1,
236
+ lastX2: point.lastX2,
237
+ lastY2: point.lastY2,
238
+ isFirstPoint: point.isFirstPoint
239
+ }))
240
+ })
241
+ currentStep.value = lines.value.length
242
+ }
243
+ currentLine.value = undefined
244
+ const { ctx } = canvasState
245
+ if (ctx) ctx.beginPath()
246
+ emit('end', e)
247
+ }
376
248
 
377
249
  /**
378
250
  * @description 初始化 canvas
379
251
  * @param forceUpdate 是否强制更新
380
252
  */
381
253
  const initCanvas = (forceUpdate: boolean = false) => {
382
- // 如果不是强制更新,且已经初始化过 canvas,则不再重复初始化
383
- if (!forceUpdate && canvasState.canvasHeight && canvasState.canvasWidth) {
384
- return;
385
- }
386
- getContext().then(() => {
387
- const { ctx } = canvasState;
388
- if (ctx && props.backgroundColor) {
389
- ctx.setFillStyle(props.backgroundColor);
390
- ctx.fillRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight);
391
- ctx.draw();
254
+ // 如果不是强制更新,且已经初始化过 canvas,则不再重复初始化
255
+ if (!forceUpdate && canvasState.canvasHeight && canvasState.canvasWidth) {
256
+ return
392
257
  }
393
- });
394
- };
258
+ getContext().then(() => {
259
+ const { ctx } = canvasState
260
+ if (ctx && props.backgroundColor) {
261
+ ctx.setFillStyle(props.backgroundColor)
262
+ ctx.fillRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight)
263
+ ctx.draw()
264
+ }
265
+ })
266
+ }
395
267
 
396
268
  /**
397
269
  * @description 清空 canvas
398
270
  * */
399
271
  const clear = () => {
400
- lines.value = [];
401
- redoLines.value = [];
402
- currentStep.value = 0;
403
- clearCanvas();
404
- emit("clear");
405
- };
272
+ lines.value = []
273
+ redoLines.value = []
274
+ currentStep.value = 0
275
+ clearCanvas()
276
+ emit('clear')
277
+ }
406
278
 
407
279
  // 确认签名
408
280
  const confirmSignature = () => {
409
- canvasToImage();
410
- };
281
+ canvasToImage()
282
+ }
411
283
 
412
284
  /**
413
285
  * @description canvas划线
414
286
  * */
415
287
  const draw = (e: any) => {
416
- e.preventDefault();
417
- const { ctx } = canvasState;
418
-
419
- if (!drawing.value || props.disabled || !ctx) return;
420
- const { x, y } = e.touches[0];
288
+ e.preventDefault()
289
+ const { ctx } = canvasState
421
290
 
422
- const point: Point = {
423
- x,
424
- y,
425
- t: Date.now(),
426
- };
291
+ if (!drawing.value || props.disabled || !ctx) return
292
+ const { x, y } = e.touches[0]
427
293
 
428
- if (currentLine.value) {
429
- const points = currentLine.value.points;
430
- const prePoint = points[points.length - 1];
431
-
432
- if (prePoint.t === point.t || (prePoint.x === x && prePoint.y === y)) {
433
- return;
294
+ const point: Point = {
295
+ x,
296
+ y,
297
+ t: Date.now()
434
298
  }
435
299
 
436
- // 计算点的速度和距离
437
- point.distance = Math.sqrt(
438
- Math.pow(point.x - prePoint.x, 2) + Math.pow(point.y - prePoint.y, 2),
439
- );
440
- point.speed = point.distance / (point.t - prePoint.t || 0.1);
300
+ if (currentLine.value) {
301
+ const points = currentLine.value.points
302
+ const prePoint = points[points.length - 1]
441
303
 
442
- if (props.pressure) {
443
- point.lineWidth = calculateLineWidth(point.speed);
444
- // 处理线宽变化率限制
445
- if (points.length >= 2) {
446
- const prePoint2 = points[points.length - 2];
447
- if (prePoint2.lineWidth && prePoint.lineWidth) {
448
- const rate =
449
- (point.lineWidth - prePoint.lineWidth) / prePoint.lineWidth;
450
- const maxRate = 0.2; // 最大变化率20%
451
- if (Math.abs(rate) > maxRate) {
452
- const per = rate > 0 ? maxRate : -maxRate;
453
- point.lineWidth = prePoint.lineWidth * (1 + per);
454
- }
304
+ if (prePoint.t === point.t || (prePoint.x === x && prePoint.y === y)) {
305
+ return
306
+ }
307
+
308
+ // 计算点的速度和距离
309
+ point.distance = Math.sqrt(
310
+ Math.pow(point.x - prePoint.x, 2) + Math.pow(point.y - prePoint.y, 2)
311
+ )
312
+ point.speed = point.distance / (point.t - prePoint.t || 0.1)
313
+
314
+ if (props.pressure) {
315
+ point.lineWidth = calculateLineWidth(point.speed)
316
+ // 处理线宽变化率限制
317
+ if (points.length >= 2) {
318
+ const prePoint2 = points[points.length - 2]
319
+ if (prePoint2.lineWidth && prePoint.lineWidth) {
320
+ const rate = (point.lineWidth - prePoint.lineWidth) / prePoint.lineWidth
321
+ const maxRate = 0.2 // 最大变化率20%
322
+ if (Math.abs(rate) > maxRate) {
323
+ const per = rate > 0 ? maxRate : -maxRate
324
+ point.lineWidth = prePoint.lineWidth * (1 + per)
325
+ }
326
+ }
327
+ }
455
328
  }
456
- }
457
- }
458
329
 
459
- points.push(point);
460
-
461
- // 非笔锋模式直接使用线段连接
462
- if (!props.pressure) {
463
- ctx.beginPath();
464
- ctx.moveTo(prePoint.x, prePoint.y);
465
- ctx.lineTo(point.x, point.y);
466
- ctx.stroke();
467
- ctx.draw(true);
468
- } else if (points.length >= 2) {
469
- // 笔锋模式使用贝塞尔曲线
470
- drawSmoothLine(prePoint, point);
330
+ points.push(point)
331
+
332
+ // 非笔锋模式直接使用线段连接
333
+ if (!props.pressure) {
334
+ ctx.beginPath()
335
+ ctx.moveTo(prePoint.x, prePoint.y)
336
+ ctx.lineTo(point.x, point.y)
337
+ ctx.stroke()
338
+ ctx.draw(true)
339
+ } else if (points.length >= 2) {
340
+ // 笔锋模式使用贝塞尔曲线
341
+ drawSmoothLine(prePoint, point)
342
+ }
471
343
  }
472
- }
473
344
 
474
- emit("signing", e);
475
- };
345
+ emit('signing', e)
346
+ }
476
347
 
477
348
  /**
478
349
  * @description 重绘整个画布
479
350
  * */
480
351
  const redrawCanvas = () => {
481
- const { ctx } = canvasState;
482
- if (!ctx) return;
483
-
484
- // 清除画布并设置背景
485
- if (props.backgroundColor) {
486
- ctx.setFillStyle(props.backgroundColor);
487
- ctx.fillRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight);
488
- } else {
489
- ctx.clearRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight);
490
- }
491
-
492
- // 如果没有线条,只需要清空画布
493
- if (lines.value.length === 0) {
494
- ctx.draw();
495
- return;
496
- }
497
-
498
- // 收集所有绘制操作,最后一次性 draw
499
- lines.value.forEach((line) => {
500
- if (!line.points.length) return;
501
-
502
- ctx.setStrokeStyle(line.color);
503
- ctx.setLineJoin("round");
504
- ctx.setLineCap("round");
505
-
506
- if (line.isPressure && props.pressure) {
507
- // 笔锋模式的重绘
508
- line.points.forEach((point, index) => {
509
- if (index === 0) return;
510
- const prePoint = line.points[index - 1];
511
- const dis_x = point.x - prePoint.x;
512
- const dis_y = point.y - prePoint.y;
513
- const distance = Math.sqrt(dis_x * dis_x + dis_y * dis_y);
514
-
515
- if (distance <= 2) {
516
- point.lastX1 = point.lastX2 = prePoint.x + dis_x * 0.5;
517
- point.lastY1 = point.lastY2 = prePoint.y + dis_y * 0.5;
518
- } else {
519
- const speed = point.speed || 0;
520
- const minSpeed = props.minSpeed || 1.5;
521
- const speedFactor = Math.max(
522
- 0.1,
523
- Math.min(0.9, speed / (minSpeed * 10)),
524
- );
525
-
526
- point.lastX1 = prePoint.x + dis_x * (0.2 + speedFactor * 0.3);
527
- point.lastY1 = prePoint.y + dis_y * (0.2 + speedFactor * 0.3);
528
- point.lastX2 = prePoint.x + dis_x * (0.8 - speedFactor * 0.3);
529
- point.lastY2 = prePoint.y + dis_y * (0.8 - speedFactor * 0.3);
530
- }
352
+ const { ctx } = canvasState
353
+ if (!ctx) return
531
354
 
532
- const lineWidth = point.lineWidth || line.width;
533
- point.isFirstPoint = true;
534
- });
355
+ // 清除画布并设置背景
356
+ if (props.backgroundColor) {
357
+ ctx.setFillStyle(props.backgroundColor)
358
+ ctx.fillRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight)
535
359
  } else {
536
- // 非笔锋模式的重绘
537
- ctx.setLineWidth(line.width);
538
- line.points.forEach((point, index) => {
539
- if (index === 0) return;
540
- const prePoint = line.points[index - 1];
541
- ctx.beginPath();
542
- ctx.moveTo(prePoint.x, prePoint.y);
543
- ctx.lineTo(point.x, point.y);
544
- ctx.stroke();
545
- });
360
+ ctx.clearRect(0, 0, canvasState.canvasWidth, canvasState.canvasHeight)
361
+ }
362
+
363
+ // 如果没有线条,只需要清空画布
364
+ if (lines.value.length === 0) {
365
+ ctx.draw()
366
+ return
546
367
  }
547
- });
548
368
 
549
- // 所有线条绘制完成后,一次性更新画布
550
- ctx.draw();
551
- };
369
+ // 收集所有绘制操作,最后一次性 draw
370
+ lines.value.forEach((line) => {
371
+ if (!line.points.length) return
372
+
373
+ ctx.setStrokeStyle(line.color)
374
+ ctx.setLineJoin('round')
375
+ ctx.setLineCap('round')
376
+
377
+ if (line.isPressure && props.pressure) {
378
+ // 笔锋模式的重绘
379
+ line.points.forEach((point, index) => {
380
+ if (index === 0) return
381
+ const prePoint = line.points[index - 1]
382
+ const dis_x = point.x - prePoint.x
383
+ const dis_y = point.y - prePoint.y
384
+ const distance = Math.sqrt(dis_x * dis_x + dis_y * dis_y)
385
+
386
+ if (distance <= 2) {
387
+ point.lastX1 = point.lastX2 = prePoint.x + dis_x * 0.5
388
+ point.lastY1 = point.lastY2 = prePoint.y + dis_y * 0.5
389
+ } else {
390
+ const speed = point.speed || 0
391
+ const minSpeed = props.minSpeed || 1.5
392
+ const speedFactor = Math.max(0.1, Math.min(0.9, speed / (minSpeed * 10)))
393
+
394
+ point.lastX1 = prePoint.x + dis_x * (0.2 + speedFactor * 0.3)
395
+ point.lastY1 = prePoint.y + dis_y * (0.2 + speedFactor * 0.3)
396
+ point.lastX2 = prePoint.x + dis_x * (0.8 - speedFactor * 0.3)
397
+ point.lastY2 = prePoint.y + dis_y * (0.8 - speedFactor * 0.3)
398
+ }
399
+
400
+ const lineWidth = point.lineWidth || line.width
401
+ point.isFirstPoint = true
402
+ })
403
+ } else {
404
+ // 非笔锋模式的重绘
405
+ ctx.setLineWidth(line.width)
406
+ line.points.forEach((point, index) => {
407
+ if (index === 0) return
408
+ const prePoint = line.points[index - 1]
409
+ ctx.beginPath()
410
+ ctx.moveTo(prePoint.x, prePoint.y)
411
+ ctx.lineTo(point.x, point.y)
412
+ ctx.stroke()
413
+ })
414
+ }
415
+ })
416
+
417
+ // 所有线条绘制完成后,一次性更新画布
418
+ ctx.draw()
419
+ }
552
420
 
553
421
  /**
554
422
  * @description 修改撤销功能
555
423
  * */
556
424
  const revoke = () => {
557
- if (!lines.value.length) return;
558
- const step = Math.min(props.step, lines.value.length);
559
- const removedLines = lines.value.splice(lines.value.length - step);
560
- redoLines.value.push(...removedLines);
561
- currentStep.value = Math.max(0, currentStep.value - step);
562
- redrawCanvas();
563
- };
425
+ if (!lines.value.length) return
426
+ const step = Math.min(props.step, lines.value.length)
427
+ const removedLines = lines.value.splice(lines.value.length - step)
428
+ redoLines.value.push(...removedLines)
429
+ currentStep.value = Math.max(0, currentStep.value - step)
430
+ redrawCanvas()
431
+ }
564
432
 
565
433
  /**
566
434
  * @description 修改恢复功能
567
435
  * */
568
436
  const restore = () => {
569
- if (!redoLines.value.length) return;
570
- const step = Math.min(props.step, redoLines.value.length);
571
- const restoredLines = redoLines.value.splice(redoLines.value.length - step);
572
- lines.value.push(...restoredLines);
573
- currentStep.value = Math.min(lines.value.length, currentStep.value + step);
574
- redrawCanvas();
575
- };
437
+ if (!redoLines.value.length) return
438
+ const step = Math.min(props.step, redoLines.value.length)
439
+ const restoredLines = redoLines.value.splice(redoLines.value.length - step)
440
+ lines.value.push(...restoredLines)
441
+ currentStep.value = Math.min(lines.value.length, currentStep.value + step)
442
+ redrawCanvas()
443
+ }
576
444
 
577
445
  /**
578
446
  * @description 添加平滑线条绘制方法
579
447
  * */
580
448
  function drawSmoothLine(prePoint: Point, point: Point) {
581
- const { ctx } = canvasState;
582
- if (!ctx) return;
583
-
584
- // 计算两点间距离
585
- const dis_x = point.x - prePoint.x;
586
- const dis_y = point.y - prePoint.y;
587
- const distance = Math.sqrt(dis_x * dis_x + dis_y * dis_y);
588
-
589
- if (distance <= 2) {
590
- // 对于非常近的点,直接使用中点
591
- point.lastX1 = point.lastX2 = prePoint.x + dis_x * 0.5;
592
- point.lastY1 = point.lastY2 = prePoint.y + dis_y * 0.5;
593
- } else {
594
- // 根据点的速度计算控制点的偏移程度
595
- const speed = point.speed || 0;
596
- const minSpeed = props.minSpeed || 1.5;
597
- const speedFactor = Math.max(0.1, Math.min(0.9, speed / (minSpeed * 10)));
598
-
599
- // 计算控制点
600
- point.lastX1 = prePoint.x + dis_x * (0.2 + speedFactor * 0.3);
601
- point.lastY1 = prePoint.y + dis_y * (0.2 + speedFactor * 0.3);
602
- point.lastX2 = prePoint.x + dis_x * (0.8 - speedFactor * 0.3);
603
- point.lastY2 = prePoint.y + dis_y * (0.8 - speedFactor * 0.3);
604
- }
605
-
606
- // 计算线宽
607
- const lineWidth = point.lineWidth || props.lineWidth;
608
-
609
- // 绘制贝塞尔曲线
610
- if (typeof prePoint.lastX1 === "number") {
611
- // 设置线宽
612
- ctx.setLineWidth(lineWidth);
613
- // 绘制第一段曲线
614
- ctx.beginPath();
615
- ctx.moveTo(prePoint.lastX2!, prePoint.lastY2!);
616
- ctx.quadraticCurveTo(prePoint.x, prePoint.y, point.lastX1, point.lastY1);
617
- ctx.stroke();
618
-
619
- if (!prePoint.isFirstPoint) {
620
- // 绘制连接段曲线
621
- ctx.beginPath();
622
- ctx.moveTo(prePoint.lastX1!, prePoint.lastY1!);
623
- ctx.quadraticCurveTo(
624
- prePoint.x,
625
- prePoint.y,
626
- prePoint.lastX2!,
627
- prePoint.lastY2!,
628
- );
629
- ctx.stroke();
449
+ const { ctx } = canvasState
450
+ if (!ctx) return
451
+
452
+ // 计算两点间距离
453
+ const dis_x = point.x - prePoint.x
454
+ const dis_y = point.y - prePoint.y
455
+ const distance = Math.sqrt(dis_x * dis_x + dis_y * dis_y)
456
+
457
+ if (distance <= 2) {
458
+ // 对于非常近的点,直接使用中点
459
+ point.lastX1 = point.lastX2 = prePoint.x + dis_x * 0.5
460
+ point.lastY1 = point.lastY2 = prePoint.y + dis_y * 0.5
461
+ } else {
462
+ // 根据点的速度计算控制点的偏移程度
463
+ const speed = point.speed || 0
464
+ const minSpeed = props.minSpeed || 1.5
465
+ const speedFactor = Math.max(0.1, Math.min(0.9, speed / (minSpeed * 10)))
466
+
467
+ // 计算控制点
468
+ point.lastX1 = prePoint.x + dis_x * (0.2 + speedFactor * 0.3)
469
+ point.lastY1 = prePoint.y + dis_y * (0.2 + speedFactor * 0.3)
470
+ point.lastX2 = prePoint.x + dis_x * (0.8 - speedFactor * 0.3)
471
+ point.lastY2 = prePoint.y + dis_y * (0.8 - speedFactor * 0.3)
630
472
  }
631
473
 
632
- // 批量更新绘制内容
633
- ctx.draw(true);
634
- } else {
635
- point.isFirstPoint = true;
636
- }
474
+ // 计算线宽
475
+ const lineWidth = point.lineWidth || props.lineWidth
476
+
477
+ // 绘制贝塞尔曲线
478
+ if (typeof prePoint.lastX1 === 'number') {
479
+ // 设置线宽
480
+ ctx.setLineWidth(lineWidth)
481
+ // 绘制第一段曲线
482
+ ctx.beginPath()
483
+ ctx.moveTo(prePoint.lastX2!, prePoint.lastY2!)
484
+ ctx.quadraticCurveTo(prePoint.x, prePoint.y, point.lastX1, point.lastY1)
485
+ ctx.stroke()
486
+
487
+ if (!prePoint.isFirstPoint) {
488
+ // 绘制连接段曲线
489
+ ctx.beginPath()
490
+ ctx.moveTo(prePoint.lastX1!, prePoint.lastY1!)
491
+ ctx.quadraticCurveTo(prePoint.x, prePoint.y, prePoint.lastX2!, prePoint.lastY2!)
492
+ ctx.stroke()
493
+ }
494
+
495
+ // 批量更新绘制内容
496
+ ctx.draw(true)
497
+ } else {
498
+ point.isFirstPoint = true
499
+ }
637
500
  }
638
501
 
639
502
  onMounted(() => {
640
- initCanvas();
641
- });
503
+ initCanvas()
504
+ })
642
505
 
643
506
  onBeforeMount(() => {
644
- // #ifdef MP
645
- pixelRatio.value = uni.getSystemInfoSync().pixelRatio;
646
- // #endif
647
- });
507
+ // #ifdef MP
508
+ pixelRatio.value = uni.getSystemInfoSync().pixelRatio
509
+ // #endif
510
+ })
648
511
 
649
512
  /**
650
513
  * @description 获取canvas上下文
651
514
  */
652
515
  function getContext() {
653
- return new Promise<UniApp.CanvasContext>((resolve) => {
654
- const { ctx } = canvasState;
516
+ return new Promise<UniApp.CanvasContext>((resolve) => {
517
+ const { ctx } = canvasState
655
518
 
656
- if (ctx) {
657
- return resolve(ctx);
658
- }
659
- // #ifndef MP-WEIXIN
660
- getRect(`#${canvasId.value}`, false, instance).then((canvasRect) => {
661
- setCanvasState(canvasRect.width!, canvasRect.height!);
662
- canvasState.ctx = uni.createCanvasContext(canvasId.value, instance.proxy);
663
- if (canvasState.ctx) {
664
- canvasState.ctx.scale(pixelRatio.value, pixelRatio.value);
665
- }
666
- resolve(canvasState.ctx);
667
- });
668
- // #endif
669
- // #ifdef MP-WEIXIN
670
-
671
- getRect(`#${canvasId.value}`, false, instance, true).then(
672
- (canvasRect: any) => {
673
- if (
674
- canvasRect &&
675
- canvasRect.node &&
676
- canvasRect.width &&
677
- canvasRect.height
678
- ) {
679
- const canvasInstance = canvasRect.node;
680
- canvasState.ctx = canvas2dAdapter(
681
- canvasInstance.getContext("2d") as CanvasRenderingContext2D,
682
- );
683
- canvasInstance.width = canvasRect.width * pixelRatio.value;
684
- canvasInstance.height = canvasRect.height * pixelRatio.value;
685
- canvasState.ctx.scale(pixelRatio.value, pixelRatio.value);
686
- canvas = canvasInstance;
687
- setCanvasState(canvasRect.width, canvasRect.height);
688
- resolve(canvasState.ctx);
519
+ if (ctx) {
520
+ return resolve(ctx)
689
521
  }
690
- },
691
- );
692
- // #endif
693
- });
522
+ // #ifndef MP-WEIXIN
523
+ getRect(`#${canvasId.value}`, false, instance).then((canvasRect) => {
524
+ setCanvasState(canvasRect.width!, canvasRect.height!)
525
+ canvasState.ctx = uni.createCanvasContext(canvasId.value, instance.proxy)
526
+ if (canvasState.ctx) {
527
+ canvasState.ctx.scale(pixelRatio.value, pixelRatio.value)
528
+ }
529
+ resolve(canvasState.ctx)
530
+ })
531
+ // #endif
532
+ // #ifdef MP-WEIXIN
533
+
534
+ getRect(`#${canvasId.value}`, false, instance, true).then((canvasRect: any) => {
535
+ if (canvasRect && canvasRect.node && canvasRect.width && canvasRect.height) {
536
+ const canvasInstance = canvasRect.node
537
+ canvasState.ctx = canvas2dAdapter(
538
+ canvasInstance.getContext('2d') as CanvasRenderingContext2D
539
+ )
540
+ canvasInstance.width = canvasRect.width * pixelRatio.value
541
+ canvasInstance.height = canvasRect.height * pixelRatio.value
542
+ canvasState.ctx.scale(pixelRatio.value, pixelRatio.value)
543
+ canvas = canvasInstance
544
+ setCanvasState(canvasRect.width, canvasRect.height)
545
+ resolve(canvasState.ctx)
546
+ }
547
+ })
548
+ // #endif
549
+ })
694
550
  }
695
551
 
696
552
  /**
697
553
  * @description 设置 canvasState
698
554
  */
699
555
  function setCanvasState(width: number, height: number) {
700
- canvasState.canvasHeight = height * pixelRatio.value;
701
- canvasState.canvasWidth = width * pixelRatio.value;
556
+ canvasState.canvasHeight = height * pixelRatio.value
557
+ canvasState.canvasWidth = width * pixelRatio.value
702
558
  }
703
559
 
704
560
  /**
705
561
  * @description 设置线段
706
562
  * */
707
563
  function setLine() {
708
- const { ctx } = canvasState;
709
- if (ctx) {
710
- ctx.setLineWidth(getDefaultLineWidth()); // 使用新的默认宽度
711
- ctx.setStrokeStyle(props.penColor);
712
- ctx.setLineJoin("round");
713
- ctx.setLineCap("round");
714
- }
564
+ const { ctx } = canvasState
565
+ if (ctx) {
566
+ ctx.setLineWidth(getDefaultLineWidth()) // 使用新的默认宽度
567
+ ctx.setStrokeStyle(props.penColor)
568
+ ctx.setLineJoin('round')
569
+ ctx.setLineCap('round')
570
+ }
715
571
  }
716
572
 
717
573
  /**
718
574
  * @description canvas 绘制图片输出成文件类型
719
575
  */
720
576
  function canvasToImage() {
721
- const { fileType, quality, exportScale } = props;
722
- const { canvasWidth, canvasHeight } = canvasState;
723
- uni.canvasToTempFilePath(
724
- {
725
- width: canvasWidth * exportScale,
726
- height: canvasHeight * exportScale,
727
- destWidth: canvasWidth * exportScale,
728
- destHeight: canvasHeight * exportScale,
729
- fileType,
730
- quality,
731
- canvasId: canvasId.value,
732
- canvas: canvas,
733
- success: (res) => {
734
- const result: SignatureResult = {
735
- tempFilePath: res.tempFilePath,
736
- width: (canvasWidth * exportScale) / pixelRatio.value,
737
- height: (canvasHeight * exportScale) / pixelRatio.value,
738
- success: true,
739
- };
740
- // #ifdef MP-DINGTALK
741
- result.tempFilePath = (res as any).filePath;
742
- // #endif
743
- emit("confirm", result);
744
- },
745
- fail: () => {
746
- const result: SignatureResult = {
747
- tempFilePath: "",
748
- width: (canvasWidth * exportScale) / pixelRatio.value,
749
- height: (canvasHeight * exportScale) / pixelRatio.value,
750
- success: false,
751
- };
752
- emit("confirm", result);
753
- },
754
- },
755
- instance.proxy,
756
- );
577
+ const { fileType, quality, exportScale } = props
578
+ const { canvasWidth, canvasHeight } = canvasState
579
+ uni.canvasToTempFilePath(
580
+ {
581
+ width: canvasWidth * exportScale,
582
+ height: canvasHeight * exportScale,
583
+ destWidth: canvasWidth * exportScale,
584
+ destHeight: canvasHeight * exportScale,
585
+ fileType,
586
+ quality,
587
+ canvasId: canvasId.value,
588
+ canvas: canvas,
589
+ success: (res) => {
590
+ const result: SignatureResult = {
591
+ tempFilePath: res.tempFilePath,
592
+ width: (canvasWidth * exportScale) / pixelRatio.value,
593
+ height: (canvasHeight * exportScale) / pixelRatio.value,
594
+ success: true
595
+ }
596
+ // #ifdef MP-DINGTALK
597
+ result.tempFilePath = (res as any).filePath
598
+ // #endif
599
+ emit('confirm', result)
600
+ },
601
+ fail: () => {
602
+ const result: SignatureResult = {
603
+ tempFilePath: '',
604
+ width: (canvasWidth * exportScale) / pixelRatio.value,
605
+ height: (canvasHeight * exportScale) / pixelRatio.value,
606
+ success: false
607
+ }
608
+ emit('confirm', result)
609
+ }
610
+ },
611
+ instance.proxy
612
+ )
757
613
  }
758
614
 
759
615
  function clearCanvas() {
760
- const { canvasWidth, canvasHeight, ctx } = canvasState;
761
- if (ctx) {
762
- ctx.clearRect(0, 0, canvasWidth, canvasHeight);
763
- if (props.backgroundColor) {
764
- ctx.setFillStyle(props.backgroundColor);
765
- ctx.fillRect(0, 0, canvasWidth, canvasHeight);
616
+ const { canvasWidth, canvasHeight, ctx } = canvasState
617
+ if (ctx) {
618
+ ctx.clearRect(0, 0, canvasWidth, canvasHeight)
619
+ if (props.backgroundColor) {
620
+ ctx.setFillStyle(props.backgroundColor)
621
+ ctx.fillRect(0, 0, canvasWidth, canvasHeight)
622
+ }
623
+ ctx.draw()
766
624
  }
767
- ctx.draw();
768
- }
769
625
  }
770
626
 
771
627
  defineExpose<SignatureExpose>({
772
- init: initCanvas,
773
- clear,
774
- confirm: confirmSignature,
775
- restore,
776
- revoke,
777
- });
628
+ init: initCanvas,
629
+ clear,
630
+ confirm: confirmSignature,
631
+ restore,
632
+ revoke
633
+ })
778
634
  </script>
779
635
  <style scoped lang="scss">
780
- @import "./index.scss";
636
+ @import './index.scss';
781
637
  </style>