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,246 +1,141 @@
1
1
  <template>
2
- <view :class="rootClass" :style="rootStyle">
3
- <canvas
4
- v-if="!canvasOffScreenable && showCanvas"
5
- type="2d"
6
- :style="{
7
- height: canvasHeight + 'px',
8
- width: canvasWidth + 'px',
9
- visibility: 'hidden',
10
- }"
11
- :canvas-id="canvasId"
12
- :id="canvasId"
13
- />
14
- </view>
2
+ <view :class="rootClass" :style="rootStyle">
3
+ <canvas
4
+ v-if="!canvasOffScreenable && showCanvas"
5
+ type="2d"
6
+ :style="{
7
+ height: canvasHeight + 'px',
8
+ width: canvasWidth + 'px',
9
+ visibility: 'hidden'
10
+ }"
11
+ :canvas-id="canvasId"
12
+ :id="canvasId"
13
+ />
14
+ </view>
15
15
  </template>
16
16
 
17
17
  <script lang="ts">
18
18
  export default {
19
- name: "hy-watermark",
20
- options: {
21
- addGlobalClass: true,
22
- virtualHost: true,
23
- styleIsolation: "shared",
24
- },
25
- };
19
+ name: 'hy-watermark',
20
+ options: {
21
+ addGlobalClass: true,
22
+ virtualHost: true,
23
+ styleIsolation: 'shared'
24
+ }
25
+ }
26
26
  </script>
27
27
 
28
28
  <script lang="ts" setup>
29
- import { computed, onMounted, ref, watch, nextTick } from "vue";
30
- import type { CSSProperties } from "vue";
31
- import { addUnit, guid } from "../../libs";
29
+ import { computed, onMounted, ref, watch, nextTick } from 'vue'
30
+ import type { CSSProperties } from 'vue'
31
+ import { addUnit, guid } from '../../libs'
32
+ import watermarkProps from './props'
32
33
 
33
34
  /**
34
35
  * 在页面或组件上添加指定的图片或文字,可用于版权保护、品牌宣传等场景。
35
36
  * @displayName hy-watermark
36
37
  */
37
- defineOptions({});
38
-
39
- // const props = withDefaults(defineProps<IProps>(), defaultProps)
40
- const props = defineProps({
41
- /** 显示主标题 */
42
- title: {
43
- type: String,
44
- default: "",
45
- },
46
- /** 主标题颜色 */
47
- titleColor: {
48
- type: String,
49
- default: "",
50
- },
51
- /** 主标题字体大小,单位px */
52
- titleSize: {
53
- type: Number,
54
- default: 0,
55
- },
56
- /** 显示副标题内容 */
57
- content: {
58
- type: String,
59
- default: "",
60
- },
61
- /** 显示图片的地址,支持网络图片和base64(钉钉小程序仅支持网络图片) */
62
- image: {
63
- type: String,
64
- default: "",
65
- },
66
- /** 图片高度 */
67
- imageHeight: {
68
- type: Number,
69
- default: 50,
70
- },
71
- /** 图片宽度 */
72
- imageWidth: {
73
- type: Number,
74
- default: 70,
75
- },
76
- /** X轴间距,单位px */
77
- gutterX: {
78
- type: Number,
79
- default: 0,
80
- },
81
- /** Y轴间距,单位px */
82
- gutterY: {
83
- type: Number,
84
- default: 0,
85
- },
86
- /** canvas画布宽度,单位px */
87
- width: {
88
- type: Number,
89
- default: 100,
90
- },
91
- /** canvas画布高度,单位px */
92
- height: {
93
- type: Number,
94
- default: 100,
95
- },
96
- /** 是否为全屏水印 */
97
- fullScreen: {
98
- type: Boolean,
99
- default: true,
100
- },
101
- /** 水印字体颜色 */
102
- color: {
103
- type: String,
104
- default: "#8c8c8c",
105
- },
106
- /** 水印字体大小,单位px */
107
- size: {
108
- type: Number,
109
- default: 14,
110
- },
111
- /** 水印字体样式(仅微信和h5支持) */
112
- fontStyle: {
113
- type: String,
114
- default: "",
115
- },
116
- /** 水印字体的粗细 */
117
- fontWeight: {
118
- type: String,
119
- default: "",
120
- },
121
- /** 水印字体系列(仅微信和h5支持) */
122
- fontFamily: {
123
- type: String,
124
- default: "PingFang SC",
125
- },
126
- /** 水印旋转角度 */
127
- rotate: {
128
- type: Number,
129
- default: -25,
130
- },
131
- /** 自定义层级 */
132
- zIndex: {
133
- type: Number,
134
- default: 10086,
135
- },
136
- /** 自定义透明度,取值 0~1 */
137
- opacity: {
138
- type: Number,
139
- default: 0.5,
140
- },
141
- });
38
+ defineOptions({})
39
+
40
+ const props = defineProps(watermarkProps)
142
41
 
143
42
  watch(
144
- () => props,
145
- () => {
146
- doReset();
147
- },
148
- { deep: true },
149
- );
150
-
151
- const canvasId = ref<string>(`watermark--${guid()}`); // canvas 组件的唯一标识符
152
- const waterMarkUrl = ref<string>(""); // canvas生成base64水印
43
+ () => props,
44
+ () => {
45
+ doReset()
46
+ },
47
+ { deep: true }
48
+ )
49
+
50
+ const canvasId = ref<string>(`watermark--${guid()}`) // canvas 组件的唯一标识符
51
+ const waterMarkUrl = ref<string>('') // canvas生成base64水印
153
52
  const canvasOffScreenable = ref<boolean>(
154
- uni.canIUse("createOffscreenCanvas") && Boolean(uni.createOffscreenCanvas),
155
- ); // 是否可以使用离屏canvas
156
- const pixelRatio = ref<number>(uni.getSystemInfoSync().pixelRatio); // 像素比
157
- const canvasHeight = ref<number>(
158
- (props.height + props.gutterY) * pixelRatio.value,
159
- ); // canvas画布高度
160
- const canvasWidth = ref<number>(
161
- (props.width + props.gutterX) * pixelRatio.value,
162
- ); // canvas画布宽度
163
- const showCanvas = ref<boolean>(true); // 是否展示canvas
53
+ uni.canIUse('createOffscreenCanvas') && Boolean(uni.createOffscreenCanvas)
54
+ ) // 是否可以使用离屏canvas
55
+ const pixelRatio = ref<number>(uni.getSystemInfoSync().pixelRatio) // 像素比
56
+ const canvasHeight = ref<number>((props.height + props.gutterY) * pixelRatio.value) // canvas画布高度
57
+ const canvasWidth = ref<number>((props.width + props.gutterX) * pixelRatio.value) // canvas画布宽度
58
+ const showCanvas = ref<boolean>(true) // 是否展示canvas
164
59
 
165
60
  /**
166
61
  * @description 水印css类
167
62
  */
168
63
  const rootClass = computed(() => {
169
- const classes: string[] = ["hy-watermark"];
170
- if (props.fullScreen) {
171
- classes.push("is-fullscreen");
172
- }
173
- return classes;
174
- });
64
+ const classes: string[] = ['hy-watermark']
65
+ if (props.fullScreen) {
66
+ classes.push('is-fullscreen')
67
+ }
68
+ return classes
69
+ })
175
70
 
176
71
  /**
177
72
  * @description 水印样式
178
73
  */
179
74
  const rootStyle = computed(() => {
180
- const style: CSSProperties = {
181
- opacity: props.opacity,
182
- backgroundSize: addUnit(props.width + props.gutterX),
183
- };
184
- if (waterMarkUrl.value) {
185
- style["backgroundImage"] = `url('${waterMarkUrl.value}')`;
186
- }
187
- return style;
188
- });
75
+ const style: CSSProperties = {
76
+ opacity: props.opacity,
77
+ backgroundSize: addUnit(props.width + props.gutterX)
78
+ }
79
+ if (waterMarkUrl.value) {
80
+ style['backgroundImage'] = `url('${waterMarkUrl.value}')`
81
+ }
82
+ return style
83
+ })
189
84
 
190
85
  onMounted(() => {
191
- doInit();
192
- });
86
+ doInit()
87
+ })
193
88
 
194
89
  function doReset() {
195
- showCanvas.value = true;
196
- canvasHeight.value = (props.height + props.gutterY) * pixelRatio.value;
197
- canvasWidth.value = (props.width + props.gutterX) * pixelRatio.value;
198
- nextTick(() => {
199
- doInit();
200
- });
90
+ showCanvas.value = true
91
+ canvasHeight.value = (props.height + props.gutterY) * pixelRatio.value
92
+ canvasWidth.value = (props.width + props.gutterX) * pixelRatio.value
93
+ nextTick(() => {
94
+ doInit()
95
+ })
201
96
  }
202
97
 
203
98
  function doInit() {
204
- // #ifdef H5
205
- // h5使用document.createElement创建canvas,不用展示canvas标签
206
- showCanvas.value = false;
207
- // #endif
208
- const {
209
- width,
210
- height,
211
- color,
212
- size,
213
- fontStyle,
214
- fontWeight,
215
- fontFamily,
216
- content,
217
- rotate,
218
- gutterX,
219
- gutterY,
220
- image,
221
- imageHeight,
222
- imageWidth,
223
- title
224
- } = props;
225
-
226
- // 创建水印
227
- createWaterMark(
228
- width,
229
- height,
230
- color,
231
- size,
232
- fontStyle,
233
- fontWeight,
234
- fontFamily,
235
- content,
236
- rotate,
237
- gutterX,
238
- gutterY,
239
- image,
240
- imageHeight,
241
- imageWidth,
242
- title
243
- );
99
+ // #ifdef H5
100
+ // h5使用document.createElement创建canvas,不用展示canvas标签
101
+ showCanvas.value = false
102
+ // #endif
103
+ const {
104
+ width,
105
+ height,
106
+ color,
107
+ size,
108
+ fontStyle,
109
+ fontWeight,
110
+ fontFamily,
111
+ content,
112
+ rotate,
113
+ gutterX,
114
+ gutterY,
115
+ image,
116
+ imageHeight,
117
+ imageWidth,
118
+ title
119
+ } = props
120
+
121
+ // 创建水印
122
+ createWaterMark(
123
+ width,
124
+ height,
125
+ color,
126
+ size,
127
+ fontStyle,
128
+ fontWeight,
129
+ fontFamily,
130
+ content,
131
+ rotate,
132
+ gutterX,
133
+ gutterY,
134
+ image,
135
+ imageHeight,
136
+ imageWidth,
137
+ title
138
+ )
244
139
  }
245
140
 
246
141
  /**
@@ -262,86 +157,86 @@ function doInit() {
262
157
  * @param title 标题
263
158
  */
264
159
  function createWaterMark(
265
- width: number,
266
- height: number,
267
- color: string,
268
- size: number,
269
- fontStyle: string,
270
- fontWeight: number | string,
271
- fontFamily: string,
272
- content: string,
273
- rotate: number,
274
- gutterX: number,
275
- gutterY: number,
276
- image: string,
277
- imageHeight: number,
278
- imageWidth: number,
279
- title: string,
160
+ width: number,
161
+ height: number,
162
+ color: string,
163
+ size: number,
164
+ fontStyle: string,
165
+ fontWeight: number | string,
166
+ fontFamily: string,
167
+ content: string,
168
+ rotate: number,
169
+ gutterX: number,
170
+ gutterY: number,
171
+ image: string,
172
+ imageHeight: number,
173
+ imageWidth: number,
174
+ title: string
280
175
  ) {
281
- const canvasHeight = (height + gutterY) * pixelRatio.value;
282
- const canvasWidth = (width + gutterX) * pixelRatio.value;
283
- const contentWidth = width * pixelRatio.value;
284
- const contentHeight = height * pixelRatio.value;
285
- const fontSize = size * pixelRatio.value;
286
- // 标题字体大小:如果设置了titleSize则使用titleSize,否则使用size的1.2倍
287
- const titleFontSize = props.titleSize > 0 ? props.titleSize * pixelRatio.value : fontSize * 1.2;
288
-
289
- // #ifndef H5
290
- if (canvasOffScreenable.value) {
291
- createOffscreenCanvas(
292
- canvasHeight,
293
- canvasWidth,
294
- contentWidth,
295
- contentHeight,
296
- rotate,
297
- fontSize,
298
- fontFamily,
299
- fontStyle,
300
- fontWeight,
301
- color,
302
- content,
303
- image,
304
- imageHeight,
305
- imageWidth,
306
- title,
307
- titleFontSize
308
- );
309
- } else {
310
- createCanvas(
311
- canvasHeight,
312
- contentWidth,
313
- rotate,
314
- fontSize,
315
- color,
316
- content,
317
- image,
318
- imageHeight,
319
- imageWidth,
320
- title,
321
- titleFontSize
322
- );
323
- }
324
- // #endif
325
- // #ifdef H5
326
- createH5Canvas(
327
- canvasHeight,
328
- canvasWidth,
329
- contentWidth,
330
- contentHeight,
331
- rotate,
332
- fontSize,
333
- fontFamily,
334
- fontStyle,
335
- fontWeight,
336
- color,
337
- content,
338
- image,
339
- imageHeight,
340
- imageWidth,
341
- title,
342
- titleFontSize
343
- );
344
- // #endif
176
+ const canvasHeight = (height + gutterY) * pixelRatio.value
177
+ const canvasWidth = (width + gutterX) * pixelRatio.value
178
+ const contentWidth = width * pixelRatio.value
179
+ const contentHeight = height * pixelRatio.value
180
+ const fontSize = size * pixelRatio.value
181
+ // 标题字体大小:如果设置了titleSize则使用titleSize,否则使用size的1.2倍
182
+ const titleFontSize = props.titleSize > 0 ? props.titleSize * pixelRatio.value : fontSize * 1.2
183
+
184
+ // #ifndef H5
185
+ if (canvasOffScreenable.value) {
186
+ createOffscreenCanvas(
187
+ canvasHeight,
188
+ canvasWidth,
189
+ contentWidth,
190
+ contentHeight,
191
+ rotate,
192
+ fontSize,
193
+ fontFamily,
194
+ fontStyle,
195
+ fontWeight,
196
+ color,
197
+ content,
198
+ image,
199
+ imageHeight,
200
+ imageWidth,
201
+ title,
202
+ titleFontSize
203
+ )
204
+ } else {
205
+ createCanvas(
206
+ canvasHeight,
207
+ contentWidth,
208
+ rotate,
209
+ fontSize,
210
+ color,
211
+ content,
212
+ image,
213
+ imageHeight,
214
+ imageWidth,
215
+ title,
216
+ titleFontSize
217
+ )
218
+ }
219
+ // #endif
220
+ // #ifdef H5
221
+ createH5Canvas(
222
+ canvasHeight,
223
+ canvasWidth,
224
+ contentWidth,
225
+ contentHeight,
226
+ rotate,
227
+ fontSize,
228
+ fontFamily,
229
+ fontStyle,
230
+ fontWeight,
231
+ color,
232
+ content,
233
+ image,
234
+ imageHeight,
235
+ imageWidth,
236
+ title,
237
+ titleFontSize
238
+ )
239
+ // #endif
345
240
  }
346
241
 
347
242
  /**
@@ -362,86 +257,86 @@ function createWaterMark(
362
257
  * @param imageWidth canvas图片宽度
363
258
  */
364
259
  function createOffscreenCanvas(
365
- canvasHeight: number,
366
- canvasWidth: number,
367
- contentWidth: number,
368
- contentHeight: number,
369
- rotate: number,
370
- fontSize: number,
371
- fontFamily: string,
372
- fontStyle: string,
373
- fontWeight: string | number,
374
- color: string,
375
- content: string,
376
- image: string,
377
- imageHeight: number,
378
- imageWidth: number,
379
- title: string,
380
- titleFontSize: number
260
+ canvasHeight: number,
261
+ canvasWidth: number,
262
+ contentWidth: number,
263
+ contentHeight: number,
264
+ rotate: number,
265
+ fontSize: number,
266
+ fontFamily: string,
267
+ fontStyle: string,
268
+ fontWeight: string | number,
269
+ color: string,
270
+ content: string,
271
+ image: string,
272
+ imageHeight: number,
273
+ imageWidth: number,
274
+ title: string,
275
+ titleFontSize: number
381
276
  ) {
382
- // 创建离屏canvas
383
- const canvas: any = uni.createOffscreenCanvas({
384
- height: canvasHeight,
385
- width: canvasWidth,
386
- type: "2d",
387
- });
388
- const ctx: any = canvas.getContext("2d");
389
- if (ctx) {
390
- if (image && (title || content)) {
391
- // 图片和文字同时显示
392
- const img = canvas.createImage() as HTMLImageElement;
393
- drawImageAndTextOffScreen(
394
- ctx,
395
- img,
396
- image,
397
- imageHeight,
398
- imageWidth,
399
- title,
400
- content,
401
- rotate,
402
- contentWidth,
403
- contentHeight,
404
- fontSize,
405
- titleFontSize,
406
- fontFamily,
407
- fontStyle,
408
- fontWeight,
409
- color,
410
- canvas,
411
- );
412
- } else if (image) {
413
- const img = canvas.createImage() as HTMLImageElement;
414
- drawImageOffScreen(
415
- ctx,
416
- img,
417
- image,
418
- imageHeight,
419
- imageWidth,
420
- rotate,
421
- contentWidth,
422
- contentHeight,
423
- canvas,
424
- );
277
+ // 创建离屏canvas
278
+ const canvas: any = uni.createOffscreenCanvas({
279
+ height: canvasHeight,
280
+ width: canvasWidth,
281
+ type: '2d'
282
+ })
283
+ const ctx: any = canvas.getContext('2d')
284
+ if (ctx) {
285
+ if (image && (title || content)) {
286
+ // 图片和文字同时显示
287
+ const img = canvas.createImage() as HTMLImageElement
288
+ drawImageAndTextOffScreen(
289
+ ctx,
290
+ img,
291
+ image,
292
+ imageHeight,
293
+ imageWidth,
294
+ title,
295
+ content,
296
+ rotate,
297
+ contentWidth,
298
+ contentHeight,
299
+ fontSize,
300
+ titleFontSize,
301
+ fontFamily,
302
+ fontStyle,
303
+ fontWeight,
304
+ color,
305
+ canvas
306
+ )
307
+ } else if (image) {
308
+ const img = canvas.createImage() as HTMLImageElement
309
+ drawImageOffScreen(
310
+ ctx,
311
+ img,
312
+ image,
313
+ imageHeight,
314
+ imageWidth,
315
+ rotate,
316
+ contentWidth,
317
+ contentHeight,
318
+ canvas
319
+ )
320
+ } else {
321
+ drawTextOffScreen(
322
+ ctx,
323
+ title,
324
+ contentWidth,
325
+ contentHeight,
326
+ rotate,
327
+ fontSize,
328
+ fontFamily,
329
+ fontStyle,
330
+ fontWeight,
331
+ color,
332
+ canvas,
333
+ content,
334
+ titleFontSize
335
+ )
336
+ }
425
337
  } else {
426
- drawTextOffScreen(
427
- ctx,
428
- title,
429
- contentWidth,
430
- contentHeight,
431
- rotate,
432
- fontSize,
433
- fontFamily,
434
- fontStyle,
435
- fontWeight,
436
- color,
437
- canvas,
438
- content,
439
- titleFontSize
440
- );
338
+ console.error('无法获取canvas上下文,请确认当前环境是否支持canvas')
441
339
  }
442
- } else {
443
- console.error("无法获取canvas上下文,请确认当前环境是否支持canvas");
444
- }
445
340
  }
446
341
 
447
342
  /**
@@ -458,52 +353,61 @@ function createOffscreenCanvas(
458
353
  * @param imageWidth canvas图片宽度
459
354
  */
460
355
  function createCanvas(
461
- contentHeight: number,
462
- contentWidth: number,
463
- rotate: number,
464
- fontSize: number,
465
- color: string,
466
- content: string,
467
- image: string,
468
- imageHeight: number,
469
- imageWidth: number,
470
- title: string,
471
- titleFontSize: number
356
+ contentHeight: number,
357
+ contentWidth: number,
358
+ rotate: number,
359
+ fontSize: number,
360
+ color: string,
361
+ content: string,
362
+ image: string,
363
+ imageHeight: number,
364
+ imageWidth: number,
365
+ title: string,
366
+ titleFontSize: number
472
367
  ) {
473
- const ctx = uni.createCanvasContext(canvasId.value);
474
- if (ctx) {
475
- if (image && (title || content)) {
476
- // 图片和文字同时显示
477
- drawImageAndTextOnScreen(
478
- ctx,
479
- image,
480
- imageHeight,
481
- imageWidth,
482
- title,
483
- content,
484
- rotate,
485
- contentWidth,
486
- contentHeight,
487
- fontSize,
488
- titleFontSize,
489
- color
490
- );
491
- } else if (image) {
492
- drawImageOnScreen(
493
- ctx,
494
- image,
495
- imageHeight,
496
- imageWidth,
497
- rotate,
498
- contentWidth,
499
- contentHeight,
500
- );
368
+ const ctx = uni.createCanvasContext(canvasId.value)
369
+ if (ctx) {
370
+ if (image && (title || content)) {
371
+ // 图片和文字同时显示
372
+ drawImageAndTextOnScreen(
373
+ ctx,
374
+ image,
375
+ imageHeight,
376
+ imageWidth,
377
+ title,
378
+ content,
379
+ rotate,
380
+ contentWidth,
381
+ contentHeight,
382
+ fontSize,
383
+ titleFontSize,
384
+ color
385
+ )
386
+ } else if (image) {
387
+ drawImageOnScreen(
388
+ ctx,
389
+ image,
390
+ imageHeight,
391
+ imageWidth,
392
+ rotate,
393
+ contentWidth,
394
+ contentHeight
395
+ )
396
+ } else {
397
+ drawTextOnScreen(
398
+ ctx,
399
+ title,
400
+ contentWidth,
401
+ rotate,
402
+ fontSize,
403
+ color,
404
+ content,
405
+ titleFontSize
406
+ )
407
+ }
501
408
  } else {
502
- drawTextOnScreen(ctx, title, contentWidth, rotate, fontSize, color, content, titleFontSize);
409
+ console.error('无法获取canvas上下文,请确认当前环境是否支持canvas')
503
410
  }
504
- } else {
505
- console.error("无法获取canvas上下文,请确认当前环境是否支持canvas");
506
- }
507
411
  }
508
412
 
509
413
  /**
@@ -524,83 +428,83 @@ function createCanvas(
524
428
  * @param imageWidth canvas图片宽度
525
429
  */
526
430
  function createH5Canvas(
527
- canvasHeight: number,
528
- canvasWidth: number,
529
- contentWidth: number,
530
- contentHeight: number,
531
- rotate: number,
532
- fontSize: number,
533
- fontFamily: string,
534
- fontStyle: string,
535
- fontWeight: string | number,
536
- color: string,
537
- content: string,
538
- image: string,
539
- imageHeight: number,
540
- imageWidth: number,
541
- title: string,
542
- titleFontSize: number
431
+ canvasHeight: number,
432
+ canvasWidth: number,
433
+ contentWidth: number,
434
+ contentHeight: number,
435
+ rotate: number,
436
+ fontSize: number,
437
+ fontFamily: string,
438
+ fontStyle: string,
439
+ fontWeight: string | number,
440
+ color: string,
441
+ content: string,
442
+ image: string,
443
+ imageHeight: number,
444
+ imageWidth: number,
445
+ title: string,
446
+ titleFontSize: number
543
447
  ) {
544
- const canvas = document.createElement("canvas");
545
- const ctx = canvas.getContext("2d");
546
- canvas.setAttribute("width", `${canvasWidth}px`);
547
- canvas.setAttribute("height", `${canvasHeight}px`);
548
- if (ctx) {
549
- if (image && (title || content)) {
550
- // 图片和文字同时显示
551
- const img = new Image();
552
- drawImageAndTextOffScreen(
553
- ctx,
554
- img,
555
- image,
556
- imageHeight,
557
- imageWidth,
558
- title,
559
- content,
560
- rotate,
561
- contentWidth,
562
- contentHeight,
563
- fontSize,
564
- titleFontSize,
565
- fontFamily,
566
- fontStyle,
567
- fontWeight,
568
- color,
569
- canvas,
570
- );
571
- } else if (image) {
572
- const img = new Image();
573
- drawImageOffScreen(
574
- ctx,
575
- img,
576
- image,
577
- imageHeight,
578
- imageWidth,
579
- rotate,
580
- contentWidth,
581
- contentHeight,
582
- canvas,
583
- );
448
+ const canvas = document.createElement('canvas')
449
+ const ctx = canvas.getContext('2d')
450
+ canvas.setAttribute('width', `${canvasWidth}px`)
451
+ canvas.setAttribute('height', `${canvasHeight}px`)
452
+ if (ctx) {
453
+ if (image && (title || content)) {
454
+ // 图片和文字同时显示
455
+ const img = new Image()
456
+ drawImageAndTextOffScreen(
457
+ ctx,
458
+ img,
459
+ image,
460
+ imageHeight,
461
+ imageWidth,
462
+ title,
463
+ content,
464
+ rotate,
465
+ contentWidth,
466
+ contentHeight,
467
+ fontSize,
468
+ titleFontSize,
469
+ fontFamily,
470
+ fontStyle,
471
+ fontWeight,
472
+ color,
473
+ canvas
474
+ )
475
+ } else if (image) {
476
+ const img = new Image()
477
+ drawImageOffScreen(
478
+ ctx,
479
+ img,
480
+ image,
481
+ imageHeight,
482
+ imageWidth,
483
+ rotate,
484
+ contentWidth,
485
+ contentHeight,
486
+ canvas
487
+ )
488
+ } else {
489
+ drawTextOffScreen(
490
+ ctx,
491
+ title,
492
+ contentWidth,
493
+ contentHeight,
494
+ rotate,
495
+ fontSize,
496
+ fontFamily,
497
+ fontStyle,
498
+ fontWeight,
499
+ color,
500
+ canvas,
501
+ content,
502
+ titleFontSize
503
+ )
504
+ }
584
505
  } else {
585
- drawTextOffScreen(
586
- ctx,
587
- title,
588
- contentWidth,
589
- contentHeight,
590
- rotate,
591
- fontSize,
592
- fontFamily,
593
- fontStyle,
594
- fontWeight,
595
- color,
596
- canvas,
597
- content,
598
- titleFontSize
599
- );
506
+ console.error('无法获取canvas上下文,请确认当前环境是否支持canvas')
600
507
  }
601
- } else {
602
- console.error("无法获取canvas上下文,请确认当前环境是否支持canvas");
603
- }
604
508
  }
605
509
 
606
510
  /**
@@ -619,85 +523,85 @@ function createH5Canvas(
619
523
  */
620
524
  // 测量文本宽度并自动换行
621
525
  function wrapText(ctx: CanvasRenderingContext2D, text: string, maxWidth: number, fontSize: number) {
622
- const words = text.split('');
623
- const lines: string[] = [];
624
- let currentLine = '';
625
-
626
- for (let i = 0; i < words.length; i++) {
627
- const testLine = currentLine + words[i];
628
- const metrics = ctx.measureText(testLine);
629
- const testWidth = metrics.width;
630
-
631
- // 当文字宽度超过容器宽度的80%时换行
632
- if (testWidth > maxWidth * 0.8 && currentLine !== '') {
633
- lines.push(currentLine);
634
- currentLine = words[i];
635
- } else {
636
- currentLine = testLine;
526
+ const words = text.split('')
527
+ const lines: string[] = []
528
+ let currentLine = ''
529
+
530
+ for (let i = 0; i < words.length; i++) {
531
+ const testLine = currentLine + words[i]
532
+ const metrics = ctx.measureText(testLine)
533
+ const testWidth = metrics.width
534
+
535
+ // 当文字宽度超过容器宽度的80%时换行
536
+ if (testWidth > maxWidth * 0.8 && currentLine !== '') {
537
+ lines.push(currentLine)
538
+ currentLine = words[i]
539
+ } else {
540
+ currentLine = testLine
541
+ }
637
542
  }
638
- }
639
- lines.push(currentLine);
640
- return lines;
543
+ lines.push(currentLine)
544
+ return lines
641
545
  }
642
546
 
643
547
  function drawTextOffScreen(
644
- ctx: CanvasRenderingContext2D,
645
- title: string,
646
- contentWidth: number,
647
- contentHeight: number,
648
- rotate: number,
649
- fontSize: number,
650
- fontFamily: string,
651
- fontStyle: string,
652
- fontWeight: string | number,
653
- color: string,
654
- canvas: HTMLCanvasElement,
655
- content: string = '',
656
- titleFontSize: number = 0
548
+ ctx: CanvasRenderingContext2D,
549
+ title: string,
550
+ contentWidth: number,
551
+ contentHeight: number,
552
+ rotate: number,
553
+ fontSize: number,
554
+ fontFamily: string,
555
+ fontStyle: string,
556
+ fontWeight: string | number,
557
+ color: string,
558
+ canvas: HTMLCanvasElement,
559
+ content: string = '',
560
+ titleFontSize: number = 0
657
561
  ) {
658
- ctx.textBaseline = "middle";
659
- ctx.textAlign = "center";
660
- ctx.translate(contentWidth / 2, contentHeight / 2);
661
- ctx.rotate((Math.PI / 180) * rotate);
662
-
663
- // 计算总高度
664
- let totalTextHeight = titleFontSize;
665
- if (content) {
666
- totalTextHeight += fontSize + 5; // 标题和副标题之间的间距
667
- }
668
-
669
- // 起始Y坐标
670
- let startY = -totalTextHeight / 2;
671
-
672
- // 绘制主标题(支持自动换行)
673
- if (title) {
674
- ctx.font = `${fontStyle} normal ${fontWeight} ${titleFontSize}px/${contentHeight}px ${fontFamily}`;
675
- // 使用titleColor或默认color
676
- ctx.fillStyle = props.titleColor || color;
677
- const titleLines = wrapText(ctx, title, contentWidth, titleFontSize);
678
- const titleLineHeight = titleFontSize * 1.2;
679
-
680
- for (let i = 0; i < titleLines.length; i++) {
681
- ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
562
+ ctx.textBaseline = 'middle'
563
+ ctx.textAlign = 'center'
564
+ ctx.translate(contentWidth / 2, contentHeight / 2)
565
+ ctx.rotate((Math.PI / 180) * rotate)
566
+
567
+ // 计算总高度
568
+ let totalTextHeight = titleFontSize
569
+ if (content) {
570
+ totalTextHeight += fontSize + 5 // 标题和副标题之间的间距
682
571
  }
683
-
684
- startY += titleLines.length * titleLineHeight + 5;
685
- }
686
-
687
- // 绘制副标题(支持自动换行)
688
- if (content) {
689
- ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px/${contentHeight}px ${fontFamily}`;
690
- ctx.fillStyle = color;
691
- const contentLines = wrapText(ctx, content, contentWidth, fontSize);
692
- const contentLineHeight = fontSize * 1.2;
693
-
694
- for (let i = 0; i < contentLines.length; i++) {
695
- ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
572
+
573
+ // 起始Y坐标
574
+ let startY = -totalTextHeight / 2
575
+
576
+ // 绘制主标题(支持自动换行)
577
+ if (title) {
578
+ ctx.font = `${fontStyle} normal ${fontWeight} ${titleFontSize}px/${contentHeight}px ${fontFamily}`
579
+ // 使用titleColor或默认color
580
+ ctx.fillStyle = props.titleColor || color
581
+ const titleLines = wrapText(ctx, title, contentWidth, titleFontSize)
582
+ const titleLineHeight = titleFontSize * 1.2
583
+
584
+ for (let i = 0; i < titleLines.length; i++) {
585
+ ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight)
586
+ }
587
+
588
+ startY += titleLines.length * titleLineHeight + 5
696
589
  }
697
- }
698
-
699
- ctx.restore();
700
- waterMarkUrl.value = canvas.toDataURL();
590
+
591
+ // 绘制副标题(支持自动换行)
592
+ if (content) {
593
+ ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px/${contentHeight}px ${fontFamily}`
594
+ ctx.fillStyle = color
595
+ const contentLines = wrapText(ctx, content, contentWidth, fontSize)
596
+ const contentLineHeight = fontSize * 1.2
597
+
598
+ for (let i = 0; i < contentLines.length; i++) {
599
+ ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight)
600
+ }
601
+ }
602
+
603
+ ctx.restore()
604
+ waterMarkUrl.value = canvas.toDataURL()
701
605
  }
702
606
 
703
607
  /**
@@ -711,97 +615,97 @@ function drawTextOffScreen(
711
615
  */
712
616
  // 简化版本的文字换行(UniApp CanvasContext不支持measureText)
713
617
  function simpleWrapText(text: string, maxLength: number) {
714
- const lines: string[] = [];
715
- let currentLine = '';
716
-
717
- // 基于字符数估算换行(适用于UniApp CanvasContext)
718
- for (let i = 0; i < text.length; i++) {
719
- currentLine += text[i];
720
- if (currentLine.length >= maxLength) {
721
- lines.push(currentLine);
722
- currentLine = '';
618
+ const lines: string[] = []
619
+ let currentLine = ''
620
+
621
+ // 基于字符数估算换行(适用于UniApp CanvasContext)
622
+ for (let i = 0; i < text.length; i++) {
623
+ currentLine += text[i]
624
+ if (currentLine.length >= maxLength) {
625
+ lines.push(currentLine)
626
+ currentLine = ''
627
+ }
628
+ }
629
+ if (currentLine) {
630
+ lines.push(currentLine)
723
631
  }
724
- }
725
- if (currentLine) {
726
- lines.push(currentLine);
727
- }
728
- return lines;
632
+ return lines
729
633
  }
730
634
 
731
635
  function drawTextOnScreen(
732
- ctx: UniApp.CanvasContext,
733
- title: string,
734
- contentWidth: number,
735
- rotate: number,
736
- fontSize: number,
737
- color: string,
738
- content: string = '',
739
- titleFontSize: number = 0
636
+ ctx: UniApp.CanvasContext,
637
+ title: string,
638
+ contentWidth: number,
639
+ rotate: number,
640
+ fontSize: number,
641
+ color: string,
642
+ content: string = '',
643
+ titleFontSize: number = 0
740
644
  ) {
741
- ctx.setTextBaseline("middle");
742
- ctx.setTextAlign("center");
743
- ctx.translate(contentWidth / 2, contentWidth / 2);
744
- ctx.rotate((Math.PI / 180) * rotate);
745
-
746
- // 估算每行最大字符数
747
- const maxChars = Math.floor(contentWidth / (fontSize * 0.5));
748
-
749
- // 计算总高度
750
- let totalTextHeight = titleFontSize;
751
- if (content) {
752
- totalTextHeight += fontSize + 5;
753
- }
754
-
755
- // 起始Y坐标
756
- let startY = -totalTextHeight / 2;
757
-
758
- // 绘制主标题(支持自动换行)
759
- if (title) {
760
- // 使用titleColor或默认color
761
- ctx.setFillStyle(props.titleColor || color);
762
- ctx.setFontSize(titleFontSize);
763
- const titleLines = simpleWrapText(title, maxChars);
764
- const titleLineHeight = titleFontSize * 1.2;
765
-
766
- for (let i = 0; i < titleLines.length; i++) {
767
- ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
645
+ ctx.setTextBaseline('middle')
646
+ ctx.setTextAlign('center')
647
+ ctx.translate(contentWidth / 2, contentWidth / 2)
648
+ ctx.rotate((Math.PI / 180) * rotate)
649
+
650
+ // 估算每行最大字符数
651
+ const maxChars = Math.floor(contentWidth / (fontSize * 0.5))
652
+
653
+ // 计算总高度
654
+ let totalTextHeight = titleFontSize
655
+ if (content) {
656
+ totalTextHeight += fontSize + 5
768
657
  }
769
-
770
- startY += titleLines.length * titleLineHeight + 5;
771
- }
772
-
773
- // 绘制副标题(支持自动换行)
774
- if (content) {
775
- ctx.setFillStyle(color);
776
- ctx.setFontSize(fontSize);
777
- const contentLines = simpleWrapText(content, maxChars);
778
- const contentLineHeight = fontSize * 1.2;
779
-
780
- for (let i = 0; i < contentLines.length; i++) {
781
- ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
658
+
659
+ // 起始Y坐标
660
+ let startY = -totalTextHeight / 2
661
+
662
+ // 绘制主标题(支持自动换行)
663
+ if (title) {
664
+ // 使用titleColor或默认color
665
+ ctx.setFillStyle(props.titleColor || color)
666
+ ctx.setFontSize(titleFontSize)
667
+ const titleLines = simpleWrapText(title, maxChars)
668
+ const titleLineHeight = titleFontSize * 1.2
669
+
670
+ for (let i = 0; i < titleLines.length; i++) {
671
+ ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight)
672
+ }
673
+
674
+ startY += titleLines.length * titleLineHeight + 5
782
675
  }
783
- }
784
-
785
- ctx.restore();
786
- ctx.draw();
787
- // #ifdef MP-DINGTALK
788
- // 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
789
- (ctx as any).toTempFilePath({
790
- success(res: any) {
791
- showCanvas.value = false;
792
- waterMarkUrl.value = res.filePath;
793
- },
794
- });
795
- // #endif
796
- // #ifndef MP-DINGTALK
797
- uni.canvasToTempFilePath({
798
- canvasId: canvasId.value,
799
- success: (res) => {
800
- showCanvas.value = false;
801
- waterMarkUrl.value = res.tempFilePath;
802
- },
803
- });
804
- // #endif
676
+
677
+ // 绘制副标题(支持自动换行)
678
+ if (content) {
679
+ ctx.setFillStyle(color)
680
+ ctx.setFontSize(fontSize)
681
+ const contentLines = simpleWrapText(content, maxChars)
682
+ const contentLineHeight = fontSize * 1.2
683
+
684
+ for (let i = 0; i < contentLines.length; i++) {
685
+ ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight)
686
+ }
687
+ }
688
+
689
+ ctx.restore()
690
+ ctx.draw()
691
+ // #ifdef MP-DINGTALK
692
+ // 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
693
+ ;(ctx as any).toTempFilePath({
694
+ success(res: any) {
695
+ showCanvas.value = false
696
+ waterMarkUrl.value = res.filePath
697
+ }
698
+ })
699
+ // #endif
700
+ // #ifndef MP-DINGTALK
701
+ uni.canvasToTempFilePath({
702
+ canvasId: canvasId.value,
703
+ success: (res) => {
704
+ showCanvas.value = false
705
+ waterMarkUrl.value = res.tempFilePath
706
+ }
707
+ })
708
+ // #endif
805
709
  }
806
710
 
807
711
  /**
@@ -817,215 +721,203 @@ function drawTextOnScreen(
817
721
  * @param canvas canvas实例
818
722
  */
819
723
  async function drawImageOffScreen(
820
- ctx: CanvasRenderingContext2D,
821
- img: HTMLImageElement,
822
- image: string,
823
- imageHeight: number,
824
- imageWidth: number,
825
- rotate: number,
826
- contentWidth: number,
827
- contentHeight: number,
828
- canvas: HTMLCanvasElement,
724
+ ctx: CanvasRenderingContext2D,
725
+ img: HTMLImageElement,
726
+ image: string,
727
+ imageHeight: number,
728
+ imageWidth: number,
729
+ rotate: number,
730
+ contentWidth: number,
731
+ contentHeight: number,
732
+ canvas: HTMLCanvasElement
829
733
  ) {
830
- ctx.translate(contentWidth / 2, contentHeight / 2);
831
- ctx.rotate((Math.PI / 180) * Number(rotate));
832
- img.crossOrigin = "anonymous";
833
- img.referrerPolicy = "no-referrer";
734
+ ctx.translate(contentWidth / 2, contentHeight / 2)
735
+ ctx.rotate((Math.PI / 180) * Number(rotate))
736
+ img.crossOrigin = 'anonymous'
737
+ img.referrerPolicy = 'no-referrer'
834
738
 
835
- img.src = image;
836
- img.onload = () => {
837
- ctx.drawImage(
838
- img,
839
- (-imageWidth * pixelRatio.value) / 2,
840
- (-imageHeight * pixelRatio.value) / 2,
841
- imageWidth * pixelRatio.value,
842
- imageHeight * pixelRatio.value,
843
- );
844
- ctx.restore();
845
- waterMarkUrl.value = canvas.toDataURL();
846
- };
739
+ img.src = image
740
+ img.onload = () => {
741
+ ctx.drawImage(
742
+ img,
743
+ (-imageWidth * pixelRatio.value) / 2,
744
+ (-imageHeight * pixelRatio.value) / 2,
745
+ imageWidth * pixelRatio.value,
746
+ imageHeight * pixelRatio.value
747
+ )
748
+ ctx.restore()
749
+ waterMarkUrl.value = canvas.toDataURL()
750
+ }
847
751
  }
848
752
 
849
753
  // 绘制图片和文字(离屏)
850
754
  async function drawImageAndTextOffScreen(
851
- ctx: CanvasRenderingContext2D,
852
- img: HTMLImageElement,
853
- image: string,
854
- imageHeight: number,
855
- imageWidth: number,
856
- title: string,
857
- content: string,
858
- rotate: number,
859
- contentWidth: number,
860
- contentHeight: number,
861
- fontSize: number,
862
- titleFontSize: number,
863
- fontFamily: string,
864
- fontStyle: string,
865
- fontWeight: string | number,
866
- color: string,
867
- canvas: HTMLCanvasElement,
755
+ ctx: CanvasRenderingContext2D,
756
+ img: HTMLImageElement,
757
+ image: string,
758
+ imageHeight: number,
759
+ imageWidth: number,
760
+ title: string,
761
+ content: string,
762
+ rotate: number,
763
+ contentWidth: number,
764
+ contentHeight: number,
765
+ fontSize: number,
766
+ titleFontSize: number,
767
+ fontFamily: string,
768
+ fontStyle: string,
769
+ fontWeight: string | number,
770
+ color: string,
771
+ canvas: HTMLCanvasElement
868
772
  ) {
869
- ctx.translate(contentWidth / 2, contentHeight / 2);
870
- ctx.rotate((Math.PI / 180) * Number(rotate));
871
- img.crossOrigin = "anonymous";
872
- img.referrerPolicy = "no-referrer";
873
-
874
- const imgHeight = imageHeight * pixelRatio.value;
875
- const imgWidth = imageWidth * pixelRatio.value;
876
-
877
- img.src = image;
878
- img.onload = () => {
773
+ ctx.translate(contentWidth / 2, contentHeight / 2)
774
+ ctx.rotate((Math.PI / 180) * Number(rotate))
775
+ img.crossOrigin = 'anonymous'
776
+ img.referrerPolicy = 'no-referrer'
777
+
778
+ const imgHeight = imageHeight * pixelRatio.value
779
+ const imgWidth = imageWidth * pixelRatio.value
780
+
781
+ img.src = image
782
+ img.onload = () => {
783
+ // 计算总高度
784
+ let totalHeight = imgHeight
785
+ const textSpacing = 10
786
+
787
+ if (title) totalHeight += textSpacing + titleFontSize
788
+ if (content) totalHeight += fontSize
789
+
790
+ // 起始Y坐标
791
+ let startY = -totalHeight / 2
792
+
793
+ // 绘制图片
794
+ ctx.drawImage(img, -imgWidth / 2, startY, imgWidth, imgHeight)
795
+
796
+ startY += imgHeight + textSpacing
797
+
798
+ // 设置文字样式
799
+ ctx.textBaseline = 'top'
800
+ ctx.textAlign = 'center'
801
+
802
+ // 绘制主标题
803
+ if (title) {
804
+ ctx.font = `${fontStyle} normal ${fontWeight} ${titleFontSize}px/${contentHeight}px ${fontFamily}`
805
+ // 使用titleColor或默认color
806
+ ctx.fillStyle = props.titleColor || color
807
+ const titleLines = wrapText(ctx, title, contentWidth * 0.9, titleFontSize)
808
+ const titleLineHeight = titleFontSize * 1.2
809
+
810
+ for (let i = 0; i < titleLines.length; i++) {
811
+ ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight)
812
+ }
813
+
814
+ startY += titleLines.length * titleLineHeight + 5
815
+ }
816
+
817
+ // 绘制副标题
818
+ if (content) {
819
+ ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px/${contentHeight}px ${fontFamily}`
820
+ ctx.fillStyle = color
821
+ const contentLines = wrapText(ctx, content, contentWidth * 0.9, fontSize)
822
+ const contentLineHeight = fontSize * 1.2
823
+
824
+ for (let i = 0; i < contentLines.length; i++) {
825
+ ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight)
826
+ }
827
+ }
828
+
829
+ ctx.restore()
830
+ waterMarkUrl.value = canvas.toDataURL()
831
+ }
832
+ }
833
+
834
+ // 绘制图片和文字(在屏)
835
+ function drawImageAndTextOnScreen(
836
+ ctx: UniApp.CanvasContext,
837
+ image: string,
838
+ imageHeight: number,
839
+ imageWidth: number,
840
+ title: string,
841
+ content: string,
842
+ rotate: number,
843
+ contentWidth: number,
844
+ contentHeight: number,
845
+ fontSize: number,
846
+ titleFontSize: number,
847
+ color: string
848
+ ) {
849
+ ctx.setTextBaseline('top')
850
+ ctx.setTextAlign('center')
851
+ ctx.translate(contentWidth / 2, contentWidth / 2)
852
+ ctx.rotate((Math.PI / 180) * Number(rotate))
853
+
854
+ const imgHeight = imageHeight * pixelRatio.value
855
+ const imgWidth = imageWidth * pixelRatio.value
856
+ const maxChars = Math.floor(contentWidth / (fontSize * 0.5))
857
+
879
858
  // 计算总高度
880
- let totalHeight = imgHeight;
881
- const textSpacing = 10;
882
-
883
- if (title) totalHeight += textSpacing + titleFontSize;
884
- if (content) totalHeight += fontSize;
885
-
859
+ let totalHeight = imgHeight
860
+ const textSpacing = 10
861
+
862
+ if (title) totalHeight += textSpacing + titleFontSize
863
+ if (content) totalHeight += fontSize
864
+
886
865
  // 起始Y坐标
887
- let startY = -totalHeight / 2;
888
-
866
+ let startY = -totalHeight / 2
867
+
889
868
  // 绘制图片
890
- ctx.drawImage(
891
- img,
892
- -imgWidth / 2,
893
- startY,
894
- imgWidth,
895
- imgHeight,
896
- );
897
-
898
- startY += imgHeight + textSpacing;
899
-
900
- // 设置文字样式
901
- ctx.textBaseline = "top";
902
- ctx.textAlign = "center";
903
-
869
+ ctx.drawImage(image, -imgWidth / 2, startY, imgWidth, imgHeight)
870
+
871
+ startY += imgHeight + textSpacing
872
+
904
873
  // 绘制主标题
905
874
  if (title) {
906
- ctx.font = `${fontStyle} normal ${fontWeight} ${titleFontSize}px/${contentHeight}px ${fontFamily}`;
907
- // 使用titleColor或默认color
908
- ctx.fillStyle = props.titleColor || color;
909
- const titleLines = wrapText(ctx, title, contentWidth * 0.9, titleFontSize);
910
- const titleLineHeight = titleFontSize * 1.2;
911
-
912
- for (let i = 0; i < titleLines.length; i++) {
913
- ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
914
- }
915
-
916
- startY += titleLines.length * titleLineHeight + 5;
875
+ // 使用titleColor或默认color
876
+ ctx.setFillStyle(props.titleColor || color)
877
+ ctx.setFontSize(titleFontSize)
878
+ const titleLines = simpleWrapText(title, maxChars)
879
+ const titleLineHeight = titleFontSize * 1.2
880
+
881
+ for (let i = 0; i < titleLines.length; i++) {
882
+ ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight)
883
+ }
884
+
885
+ startY += titleLines.length * titleLineHeight + 5
917
886
  }
918
-
887
+
919
888
  // 绘制副标题
920
889
  if (content) {
921
- ctx.font = `${fontStyle} normal ${fontWeight} ${fontSize}px/${contentHeight}px ${fontFamily}`;
922
- ctx.fillStyle = color;
923
- const contentLines = wrapText(ctx, content, contentWidth * 0.9, fontSize);
924
- const contentLineHeight = fontSize * 1.2;
925
-
926
- for (let i = 0; i < contentLines.length; i++) {
927
- ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
928
- }
929
- }
930
-
931
- ctx.restore();
932
- waterMarkUrl.value = canvas.toDataURL();
933
- };
934
- }
890
+ ctx.setFillStyle(color)
891
+ ctx.setFontSize(fontSize)
892
+ const contentLines = simpleWrapText(content, maxChars)
893
+ const contentLineHeight = fontSize * 1.2
935
894
 
936
- // 绘制图片和文字(在屏)
937
- function drawImageAndTextOnScreen(
938
- ctx: UniApp.CanvasContext,
939
- image: string,
940
- imageHeight: number,
941
- imageWidth: number,
942
- title: string,
943
- content: string,
944
- rotate: number,
945
- contentWidth: number,
946
- contentHeight: number,
947
- fontSize: number,
948
- titleFontSize: number,
949
- color: string
950
- ) {
951
- ctx.setTextBaseline("top");
952
- ctx.setTextAlign("center");
953
- ctx.translate(contentWidth / 2, contentWidth / 2);
954
- ctx.rotate((Math.PI / 180) * Number(rotate));
955
-
956
- const imgHeight = imageHeight * pixelRatio.value;
957
- const imgWidth = imageWidth * pixelRatio.value;
958
- const maxChars = Math.floor(contentWidth / (fontSize * 0.5));
959
-
960
- // 计算总高度
961
- let totalHeight = imgHeight;
962
- const textSpacing = 10;
963
-
964
- if (title) totalHeight += textSpacing + titleFontSize;
965
- if (content) totalHeight += fontSize;
966
-
967
- // 起始Y坐标
968
- let startY = -totalHeight / 2;
969
-
970
- // 绘制图片
971
- ctx.drawImage(
972
- image,
973
- -imgWidth / 2,
974
- startY,
975
- imgWidth,
976
- imgHeight,
977
- );
978
-
979
- startY += imgHeight + textSpacing;
980
-
981
- // 绘制主标题
982
- if (title) {
983
- // 使用titleColor或默认color
984
- ctx.setFillStyle(props.titleColor || color);
985
- ctx.setFontSize(titleFontSize);
986
- const titleLines = simpleWrapText(title, maxChars);
987
- const titleLineHeight = titleFontSize * 1.2;
988
-
989
- for (let i = 0; i < titleLines.length; i++) {
990
- ctx.fillText(titleLines[i], 0, startY + i * titleLineHeight);
991
- }
992
-
993
- startY += titleLines.length * titleLineHeight + 5;
994
- }
995
-
996
- // 绘制副标题
997
- if (content) {
998
- ctx.setFillStyle(color);
999
- ctx.setFontSize(fontSize);
1000
- const contentLines = simpleWrapText(content, maxChars);
1001
- const contentLineHeight = fontSize * 1.2;
1002
-
1003
- for (let i = 0; i < contentLines.length; i++) {
1004
- ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight);
895
+ for (let i = 0; i < contentLines.length; i++) {
896
+ ctx.fillText(contentLines[i], 0, startY + i * contentLineHeight)
897
+ }
1005
898
  }
1006
- }
1007
-
1008
- ctx.restore();
1009
- ctx.draw(false, () => {
1010
- // #ifdef MP-DINGTALK
1011
- // 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
1012
- (ctx as any).toTempFilePath({
1013
- success(res: any) {
1014
- showCanvas.value = false;
1015
- waterMarkUrl.value = res.filePath;
1016
- },
1017
- });
1018
- // #endif
1019
- // #ifndef MP-DINGTALK
1020
- uni.canvasToTempFilePath({
1021
- canvasId: canvasId.value,
1022
- success: (res) => {
1023
- showCanvas.value = false;
1024
- waterMarkUrl.value = res.tempFilePath;
1025
- },
1026
- });
1027
- // #endif
1028
- });
899
+
900
+ ctx.restore()
901
+ ctx.draw(false, () => {
902
+ // #ifdef MP-DINGTALK
903
+ // 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
904
+ ;(ctx as any).toTempFilePath({
905
+ success(res: any) {
906
+ showCanvas.value = false
907
+ waterMarkUrl.value = res.filePath
908
+ }
909
+ })
910
+ // #endif
911
+ // #ifndef MP-DINGTALK
912
+ uni.canvasToTempFilePath({
913
+ canvasId: canvasId.value,
914
+ success: (res) => {
915
+ showCanvas.value = false
916
+ waterMarkUrl.value = res.tempFilePath
917
+ }
918
+ })
919
+ // #endif
920
+ })
1029
921
  }
1030
922
 
1031
923
  /**
@@ -1039,48 +931,48 @@ function drawImageAndTextOnScreen(
1039
931
  * @param contentHeight 水印高度
1040
932
  */
1041
933
  function drawImageOnScreen(
1042
- ctx: UniApp.CanvasContext,
1043
- image: string,
1044
- imageHeight: number,
1045
- imageWidth: number,
1046
- rotate: number,
1047
- contentWidth: number,
1048
- contentHeight: number,
934
+ ctx: UniApp.CanvasContext,
935
+ image: string,
936
+ imageHeight: number,
937
+ imageWidth: number,
938
+ rotate: number,
939
+ contentWidth: number,
940
+ contentHeight: number
1049
941
  ) {
1050
- ctx.translate(contentWidth / 2, contentHeight / 2);
1051
- ctx.rotate((Math.PI / 180) * Number(rotate));
1052
-
1053
- ctx.drawImage(
1054
- image,
1055
- (-imageWidth * pixelRatio.value) / 2,
1056
- (-imageHeight * pixelRatio.value) / 2,
1057
- imageWidth * pixelRatio.value,
1058
- imageHeight * pixelRatio.value,
1059
- );
1060
- ctx.restore();
1061
- ctx.draw(false, () => {
1062
- // #ifdef MP-DINGTALK
1063
- // 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
1064
- (ctx as any).toTempFilePath({
1065
- success(res: any) {
1066
- showCanvas.value = false;
1067
- waterMarkUrl.value = res.filePath;
1068
- },
1069
- });
1070
- // #endif
1071
- // #ifndef MP-DINGTALK
1072
- uni.canvasToTempFilePath({
1073
- canvasId: canvasId.value,
1074
- success: (res) => {
1075
- showCanvas.value = false;
1076
- waterMarkUrl.value = res.tempFilePath;
1077
- },
1078
- });
1079
- // #endif
1080
- });
942
+ ctx.translate(contentWidth / 2, contentHeight / 2)
943
+ ctx.rotate((Math.PI / 180) * Number(rotate))
944
+
945
+ ctx.drawImage(
946
+ image,
947
+ (-imageWidth * pixelRatio.value) / 2,
948
+ (-imageHeight * pixelRatio.value) / 2,
949
+ imageWidth * pixelRatio.value,
950
+ imageHeight * pixelRatio.value
951
+ )
952
+ ctx.restore()
953
+ ctx.draw(false, () => {
954
+ // #ifdef MP-DINGTALK
955
+ // 钉钉小程序的canvasToTempFilePath接口与其他平台不一样
956
+ ;(ctx as any).toTempFilePath({
957
+ success(res: any) {
958
+ showCanvas.value = false
959
+ waterMarkUrl.value = res.filePath
960
+ }
961
+ })
962
+ // #endif
963
+ // #ifndef MP-DINGTALK
964
+ uni.canvasToTempFilePath({
965
+ canvasId: canvasId.value,
966
+ success: (res) => {
967
+ showCanvas.value = false
968
+ waterMarkUrl.value = res.tempFilePath
969
+ }
970
+ })
971
+ // #endif
972
+ })
1081
973
  }
1082
974
  </script>
1083
975
 
1084
976
  <style lang="scss" scoped>
1085
- @import "./index.scss";
977
+ @import './index.scss';
1086
978
  </style>