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