sard-uniapp 1.11.2 → 1.12.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 (194) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +3 -2
  3. package/components/action-sheet/action-sheet.vue +8 -2
  4. package/components/action-sheet/index.scss +1 -1
  5. package/components/back-top/back-top.d.ts +1 -1
  6. package/components/badge/badge.vue +1 -1
  7. package/components/button/button.d.ts +1 -0
  8. package/components/button/button.vue +2 -0
  9. package/components/button/common.d.ts +2 -0
  10. package/components/button/index.scss +6 -1
  11. package/components/calendar/calendar.d.ts +1 -1
  12. package/components/calendar/calendar.vue +49 -22
  13. package/components/calendar/index.scss +5 -5
  14. package/components/calendar/variables.scss +1 -1
  15. package/components/calendar-input/calendar-input.d.ts +1 -1
  16. package/components/calendar-month/index.scss +1 -0
  17. package/components/cascader/cascader.d.ts +6 -6
  18. package/components/cascader/cascader.vue +9 -4
  19. package/components/cascader/common.d.ts +3 -3
  20. package/components/cascader/index.scss +1 -0
  21. package/components/checkbox-input/checkbox-input.vue +59 -32
  22. package/components/checkbox-input/index.scss +4 -0
  23. package/components/config/index.d.ts +23 -0
  24. package/components/config/index.js +47 -18
  25. package/components/crop-image/common.d.ts +32 -0
  26. package/components/crop-image/common.js +2 -0
  27. package/components/crop-image/crop-image.d.ts +19 -0
  28. package/components/crop-image/crop-image.vue +671 -0
  29. package/components/crop-image/index.d.ts +1 -0
  30. package/components/crop-image/index.scss +81 -0
  31. package/components/crop-image-agent/common.d.ts +19 -0
  32. package/components/crop-image-agent/common.js +16 -0
  33. package/components/crop-image-agent/crop-image-agent.d.ts +9 -0
  34. package/components/crop-image-agent/crop-image-agent.vue +70 -0
  35. package/components/crop-image-agent/index.d.ts +1 -0
  36. package/components/crop-image-agent/index.js +1 -0
  37. package/components/datetime-picker-input/datetime-picker-input.vue +4 -4
  38. package/components/datetime-range-picker/datetime-range-picker.vue +4 -3
  39. package/components/datetime-range-picker-input/datetime-range-picker-input.vue +4 -4
  40. package/components/dialog/common.d.ts +2 -3
  41. package/components/dialog/dialog.d.ts +6 -13
  42. package/components/dialog/dialog.vue +15 -4
  43. package/components/dialog-agent/dialog-agent.d.ts +1 -1
  44. package/components/dropdown-item/dropdown-item.vue +6 -6
  45. package/components/fab/fab.d.ts +1 -1
  46. package/components/floating-bubble/floating-bubble.vue +14 -19
  47. package/components/form-item/form-item.vue +4 -3
  48. package/components/grid/common.d.ts +4 -0
  49. package/components/grid-item/grid-item.vue +33 -18
  50. package/components/grid-item/index.scss +12 -4
  51. package/components/icon/index.scss +1 -0
  52. package/components/icon/sari.scss +9 -1
  53. package/components/indexes/common.d.ts +3 -5
  54. package/components/indexes/indexes.d.ts +2 -0
  55. package/components/indexes/indexes.vue +45 -109
  56. package/components/indexes-anchor/indexes-anchor.vue +9 -9
  57. package/components/indexes-nav/indexes-nav.vue +26 -22
  58. package/components/input/input.d.ts +4 -4
  59. package/components/loading/index.scss +1 -1
  60. package/components/locale/lang/en-US.d.ts +9 -0
  61. package/components/locale/lang/en-US.js +9 -0
  62. package/components/locale/lang/zh-CN.d.ts +9 -0
  63. package/components/locale/lang/zh-CN.js +9 -0
  64. package/components/navbar/common.d.ts +12 -0
  65. package/components/navbar/index.scss +17 -10
  66. package/components/navbar/navbar.d.ts +5 -1
  67. package/components/navbar/navbar.vue +45 -15
  68. package/components/navbar/variables.scss +4 -1
  69. package/components/navbar-item/index.scss +10 -0
  70. package/components/navbar-item/navbar-item.vue +27 -4
  71. package/components/navbar-pit/navbar-pit.d.ts +2 -0
  72. package/components/navbar-pit/navbar-pit.vue +22 -0
  73. package/components/notify/common.d.ts +1 -0
  74. package/components/notify/index.scss +12 -7
  75. package/components/notify/notify.vue +9 -3
  76. package/components/notify-agent/notify-agent.vue +9 -11
  77. package/components/pagination/pagination.d.ts +1 -1
  78. package/components/picker-input/picker-input.vue +4 -4
  79. package/components/popout/common.d.ts +2 -3
  80. package/components/popout/popout.d.ts +5 -12
  81. package/components/popout/popout.vue +16 -5
  82. package/components/popover/utils.js +2 -4
  83. package/components/popover-reference/popover-reference.vue +3 -3
  84. package/components/popup/common.d.ts +5 -3
  85. package/components/popup/index.scss +25 -3
  86. package/components/popup/popup.d.ts +1 -1
  87. package/components/pull-down-refresh/pull-down-refresh.d.ts +1 -1
  88. package/components/qrcode/qrcode.d.ts +1 -1
  89. package/components/qrcode/qrcode.vue +4 -7
  90. package/components/radio-input/index.scss +5 -1
  91. package/components/radio-input/radio-input.vue +59 -32
  92. package/components/scroll-spy/common.d.ts +29 -0
  93. package/components/scroll-spy/common.js +1 -0
  94. package/components/scroll-spy/index.d.ts +1 -0
  95. package/components/scroll-spy/index.js +1 -0
  96. package/components/scroll-spy/scroll-spy.d.ts +28 -0
  97. package/components/scroll-spy/scroll-spy.vue +120 -0
  98. package/components/scroll-spy-anchor/common.d.ts +13 -0
  99. package/components/scroll-spy-anchor/index.d.ts +1 -0
  100. package/components/scroll-spy-anchor/index.js +1 -0
  101. package/components/scroll-spy-anchor/scroll-spy-anchor.d.ts +10 -0
  102. package/components/scroll-spy-anchor/scroll-spy-anchor.vue +50 -0
  103. package/components/search/search.vue +2 -0
  104. package/components/share-sheet/share-sheet.vue +3 -2
  105. package/components/sidebar/common.d.ts +28 -0
  106. package/components/sidebar/common.js +1 -0
  107. package/components/sidebar/index.d.ts +1 -0
  108. package/components/sidebar/index.js +1 -0
  109. package/components/sidebar/index.scss +15 -0
  110. package/components/sidebar/sidebar.d.ts +16 -0
  111. package/components/sidebar/sidebar.vue +136 -0
  112. package/components/sidebar/variables.scss +20 -0
  113. package/components/sidebar-item/common.d.ts +16 -0
  114. package/components/sidebar-item/common.js +1 -0
  115. package/components/sidebar-item/index.d.ts +1 -0
  116. package/components/sidebar-item/index.js +1 -0
  117. package/components/sidebar-item/index.scss +70 -0
  118. package/components/sidebar-item/sidebar-item.d.ts +14 -0
  119. package/components/sidebar-item/sidebar-item.vue +111 -0
  120. package/components/signature/common.d.ts +41 -0
  121. package/components/signature/common.js +2 -0
  122. package/components/signature/index.d.ts +1 -0
  123. package/components/signature/index.js +1 -0
  124. package/components/signature/index.scss +109 -0
  125. package/components/signature/signature.d.ts +32 -0
  126. package/components/signature/signature.vue +580 -0
  127. package/components/signature/variables-dark.scss +7 -0
  128. package/components/signature/variables.scss +9 -0
  129. package/components/status-bar/common.d.ts +17 -0
  130. package/components/status-bar/common.js +2 -0
  131. package/components/status-bar/index.d.ts +1 -0
  132. package/components/status-bar/index.js +1 -0
  133. package/components/status-bar/index.scss +7 -0
  134. package/components/status-bar/status-bar.d.ts +12 -0
  135. package/components/status-bar/status-bar.vue +56 -0
  136. package/components/style/mixins/ellipsis.scss +7 -0
  137. package/components/style/mixins/scroll-shadow.scss +40 -0
  138. package/components/style/mixins.scss +1 -0
  139. package/components/style/variables.scss +3 -0
  140. package/components/swiper-dot/swiper-dot.d.ts +1 -1
  141. package/components/tab/tab.vue +4 -3
  142. package/components/tabbar/common.d.ts +1 -0
  143. package/components/tabbar/tabbar.d.ts +2 -0
  144. package/components/tabbar/tabbar.vue +2 -1
  145. package/components/table-cell/index.scss +1 -2
  146. package/components/table-fixation/table-fixation.vue +16 -8
  147. package/components/tree-node/tree-node.vue +3 -3
  148. package/components/upload/upload.vue +3 -2
  149. package/dark.scss +1 -0
  150. package/global.d.ts +9 -0
  151. package/index.d.ts +8 -0
  152. package/index.js +8 -0
  153. package/index.scss +2 -0
  154. package/package.json +28 -24
  155. package/use/index.d.ts +4 -0
  156. package/use/index.js +4 -0
  157. package/use/useDragPinch.d.ts +15 -0
  158. package/use/useDragPinch.js +88 -0
  159. package/use/useImperative.js +1 -0
  160. package/use/useInitialVelocity.d.ts +13 -0
  161. package/use/useInitialVelocity.js +65 -0
  162. package/use/useMouseDown.js +3 -4
  163. package/use/useScrollSide.d.ts +6 -0
  164. package/use/useScrollSide.js +34 -0
  165. package/use/useScrollSpy.d.ts +19 -0
  166. package/use/useScrollSpy.js +99 -0
  167. package/use/useTimeoutLoading.d.ts +6 -0
  168. package/use/useTimeoutLoading.js +53 -0
  169. package/use/useZIndex.js +7 -3
  170. package/utils/bem.d.ts +8 -8
  171. package/utils/dom.d.ts +3 -69
  172. package/utils/dom.js +32 -109
  173. package/utils/file.d.ts +1 -0
  174. package/utils/file.js +14 -0
  175. package/utils/geometry.d.ts +67 -0
  176. package/utils/geometry.js +127 -0
  177. package/utils/index.d.ts +2 -0
  178. package/utils/index.js +2 -0
  179. package/utils/inertialAnimate.d.ts +10 -0
  180. package/utils/inertialAnimate.js +42 -0
  181. package/utils/is.d.ts +8 -0
  182. package/utils/is.js +8 -0
  183. package/utils/system.d.ts +2 -0
  184. package/utils/system.js +6 -3
  185. package/utils/utils.d.ts +7 -0
  186. package/utils/utils.js +13 -0
  187. package/components/_template/_template.d.ts +0 -16
  188. package/components/_template/_template.vue +0 -45
  189. package/components/_template/common.d.ts +0 -14
  190. package/components/_template/index.d.ts +0 -1
  191. package/components/_template/index.scss +0 -17
  192. package/components/_template/variables.scss +0 -5
  193. /package/components/{_template → crop-image}/index.js +0 -0
  194. /package/components/{_template → scroll-spy-anchor}/common.js +0 -0
@@ -0,0 +1,671 @@
1
+ <template>
2
+ <sar-popup
3
+ effect="full-fade"
4
+ :visible="visible"
5
+ :duration="duration"
6
+ :overlay="false"
7
+ @after-enter="onAfterEnter"
8
+ >
9
+ <view :class="cropImageClass" :style="cropImageStyle">
10
+ <view
11
+ :class="bem.e('sensor')"
12
+ @mousedown="onMouseDown"
13
+ @touchstart="onTouchStart"
14
+ @touchmove.stop.prevent="onTouchMove"
15
+ @touchend="onTouchEnd"
16
+ @touchcancel="onTouchEnd"
17
+ >
18
+ <view :class="bem.e('focus')" :style="focusStyle">
19
+ <view :class="bem.e('puppet')" :style="puppetStyle">
20
+ <image
21
+ v-if="imageOrigSize[0] > 0"
22
+ mode="scaleToFill"
23
+ :src="src"
24
+ :class="bem.e('image')"
25
+ :style="imageStyle"
26
+ @touchstart="onImageTouchStart"
27
+ />
28
+ </view>
29
+ </view>
30
+ </view>
31
+ <view :class="bem.e('mask')" :style="maskStyle"></view>
32
+
33
+ <view :class="bem.e('toolbar')">
34
+ <sar-button
35
+ size="small"
36
+ type="pale-text"
37
+ color="white"
38
+ block
39
+ @click="onCancel"
40
+ >
41
+ <text style="font-size: var(--sar-text-base); font-weight: bold">
42
+ {{ cancelText || t('cancel') }}
43
+ </text>
44
+ </sar-button>
45
+ <sar-button
46
+ size="small"
47
+ type="pale-text"
48
+ color="white"
49
+ block
50
+ @click="onReset"
51
+ >
52
+ <sar-icon name="undo" size="var(--sar-text-xl)" />
53
+ </sar-button>
54
+ <sar-button
55
+ size="small"
56
+ type="pale-text"
57
+ color="white"
58
+ block
59
+ @click="onRotate"
60
+ >
61
+ <sar-icon name="rotate-left" size="var(--sar-text-xl)" />
62
+ </sar-button>
63
+ <sar-button size="small" block @click="onConfirm">
64
+ <text style="font-weight: bold">
65
+ {{ confirmText || t('confirm') }}
66
+ </text>
67
+ </sar-button>
68
+ </view>
69
+ </view>
70
+
71
+ <view :class="bem.e('canvas-wrapper')">
72
+ <canvas
73
+ type="2d"
74
+ :hidpi="false"
75
+ :canvas-id="canvasId"
76
+ :id="canvasId"
77
+ :style="canvasStyle"
78
+ ></canvas>
79
+ </view>
80
+
81
+ <view v-if="isCropping" :class="bem.e('loading')">
82
+ <sar-loading />
83
+ </view>
84
+ </sar-popup>
85
+ </template>
86
+
87
+ <script>
88
+ import { mergeDefaults as _mergeDefaults, defineComponent as _defineComponent } from "vue";
89
+ import { computed, getCurrentInstance, onBeforeUnmount, ref, watch } from "vue";
90
+ import {
91
+ classNames,
92
+ stringifyStyle,
93
+ createBem,
94
+ getWindowInfo,
95
+ getAspectFillSize,
96
+ getAspectFitSize,
97
+ uniqid,
98
+ isApp,
99
+ getNode,
100
+ isWeb,
101
+ createInertialAnimate,
102
+ isAlipay,
103
+ sleep
104
+ } from "../../utils";
105
+ import {
106
+ defaultCropImageProps
107
+ } from "./common";
108
+ import { useDragPinch, useSetTimeout } from "../../use";
109
+ import { useTranslate } from "../locale";
110
+ import SarPopup from "../popup/popup.vue";
111
+ import SarIcon from "../icon/icon.vue";
112
+ import SarButton from "../button/button.vue";
113
+ import SarLoading from "../loading/loading.vue";
114
+ const minGapX = 20;
115
+ const bounceCoeff = 4;
116
+ const maxScale = 5;
117
+ export default _defineComponent({
118
+ components: {
119
+ SarPopup,
120
+ SarIcon,
121
+ SarButton,
122
+ SarLoading,
123
+ },
124
+ ...{
125
+ options: {
126
+ virtualHost: true,
127
+ styleIsolation: "shared"
128
+ }
129
+ },
130
+ __name: "crop-image",
131
+ props: _mergeDefaults({
132
+ rootStyle: { type: [Boolean, null, String, Object, Array], required: false, skipCheck: true },
133
+ rootClass: { type: String, required: false },
134
+ visible: { type: Boolean, required: false },
135
+ src: { type: String, required: false },
136
+ cropScale: { type: String, required: false },
137
+ type: { type: String, required: false },
138
+ quality: { type: Number, required: false },
139
+ duration: { type: Number, required: false },
140
+ success: { type: Function, required: false },
141
+ fail: { type: Function, required: false },
142
+ complete: { type: Function, required: false },
143
+ id: { type: String, required: false },
144
+ beforeCrop: { type: Function, required: false },
145
+ cancelText: { type: String, required: false },
146
+ confirmText: { type: String, required: false }
147
+ }, defaultCropImageProps),
148
+ emits: ["update:visible"],
149
+ setup(__props, { expose: __expose, emit: __emit }) {
150
+ const props = __props;
151
+ const emit = __emit;
152
+ const bem = createBem("crop-image");
153
+ const { t } = useTranslate("signature");
154
+ const innerVisible = ref(props.visible);
155
+ watch(
156
+ () => props.visible,
157
+ () => {
158
+ innerVisible.value = props.visible;
159
+ }
160
+ );
161
+ const close = () => {
162
+ innerVisible.value = false;
163
+ emit("update:visible", false);
164
+ };
165
+ const { windowWidth, windowHeight, pixelRatio } = getWindowInfo();
166
+ const aspectRatio = computed(() => {
167
+ const [w, h] = props.cropScale.split(":").map(Number);
168
+ return [w, h];
169
+ });
170
+ const minGapY = windowWidth / 750 * 128;
171
+ const focusRect = computed(() => {
172
+ const maxWidth = windowWidth - minGapX * 2;
173
+ const maxHeight = windowHeight - minGapY * 2;
174
+ const [width, height] = getAspectFitSize(
175
+ ...aspectRatio.value,
176
+ maxWidth,
177
+ maxHeight
178
+ );
179
+ const left = (windowWidth - width) / 2;
180
+ const top = (windowHeight - height) / 2;
181
+ return [left, top, width, height];
182
+ });
183
+ const rotate = ref(0);
184
+ const actualRotate = ref(0);
185
+ const [onRotateEnd] = useSetTimeout(() => {
186
+ actualRotate.value = rotate.value;
187
+ });
188
+ watch(rotate, () => {
189
+ onRotateEnd(150 + 100);
190
+ });
191
+ const isRotating = computed(() => rotate.value !== actualRotate.value);
192
+ const isStillRotating = ref(false);
193
+ const [stopRotateLater, cancelStopRotate] = useSetTimeout(() => {
194
+ isStillRotating.value = false;
195
+ });
196
+ watch(isRotating, () => {
197
+ cancelStopRotate();
198
+ if (isRotating.value) {
199
+ isStillRotating.value = true;
200
+ } else {
201
+ stopRotateLater(150);
202
+ }
203
+ });
204
+ const maskStyle = computed(() => {
205
+ const [left, top, width, height] = focusRect.value;
206
+ return {
207
+ left: left + "px",
208
+ top: top + "px",
209
+ width: width + "px",
210
+ height: height + "px"
211
+ };
212
+ });
213
+ const focusStyle = computed(() => {
214
+ return {
215
+ ...maskStyle.value,
216
+ transition: isRotating.value ? "" : "none",
217
+ transform: `rotate(${rotate.value - actualRotate.value}deg)`
218
+ };
219
+ });
220
+ const imageOrigSize = ref([0, 0]);
221
+ watch(
222
+ () => props.src,
223
+ () => {
224
+ imageOrigSize.value = [0, 0];
225
+ rotate.value = 0;
226
+ actualRotate.value = 0;
227
+ isStillRotating.value = false;
228
+ if (props.src) {
229
+ uni.getImageInfo({
230
+ src: props.src,
231
+ success(res) {
232
+ imageOrigSize.value = [res.width, res.height];
233
+ }
234
+ });
235
+ }
236
+ },
237
+ {
238
+ immediate: true
239
+ }
240
+ );
241
+ const imageCoverSize = ref([0, 0]);
242
+ watch(
243
+ imageOrigSize,
244
+ () => {
245
+ const [, , width, height] = focusRect.value;
246
+ imageCoverSize.value = getAspectFillSize(
247
+ ...imageOrigSize.value,
248
+ width,
249
+ height
250
+ );
251
+ },
252
+ {
253
+ immediate: true
254
+ }
255
+ );
256
+ const reversedCoverSize = computed(() => {
257
+ const size = [...imageCoverSize.value];
258
+ return actualRotate.value % 180 !== 0 ? size.reverse() : size;
259
+ });
260
+ const imgLeft = ref(0);
261
+ const imgTop = ref(0);
262
+ const imgWidth = ref(0);
263
+ const imgHeight = ref(0);
264
+ watch(
265
+ imageCoverSize,
266
+ ([width, height]) => {
267
+ imgWidth.value = width;
268
+ imgHeight.value = height;
269
+ imgLeft.value = 0;
270
+ imgTop.value = 0;
271
+ },
272
+ {
273
+ immediate: true
274
+ }
275
+ );
276
+ watch(actualRotate, (rotate2, oldRotate) => {
277
+ const oldWidth = imgWidth.value;
278
+ const oldHeight = imgHeight.value;
279
+ const oldTop = imgTop.value;
280
+ const oldLeft = imgLeft.value;
281
+ const [, , focusWidth, focusHeight] = focusRect.value;
282
+ const top = focusHeight / 2 - oldTop;
283
+ const left = focusWidth / 2 - oldLeft;
284
+ const right = oldWidth - left;
285
+ const bottom = oldHeight - top;
286
+ const r = (rotate2 - oldRotate) % 360;
287
+ let topOpposite = 0;
288
+ let leftOpposite = 0;
289
+ if (r === 0) return;
290
+ switch (r) {
291
+ case -90:
292
+ case 270:
293
+ topOpposite = right;
294
+ leftOpposite = top;
295
+ break;
296
+ case -180:
297
+ case 180:
298
+ topOpposite = bottom;
299
+ leftOpposite = right;
300
+ break;
301
+ case -270:
302
+ case 90:
303
+ topOpposite = left;
304
+ leftOpposite = bottom;
305
+ break;
306
+ }
307
+ imgTop.value = focusHeight / 2 - topOpposite;
308
+ imgLeft.value = focusWidth / 2 - leftOpposite;
309
+ if (rotate2 % 180 - oldRotate % 180 !== 0) {
310
+ const [width, height] = [oldWidth, oldHeight].reverse();
311
+ imgWidth.value = width;
312
+ imgHeight.value = height;
313
+ }
314
+ });
315
+ const isCaptured = ref(false);
316
+ const inInertia = ref(false);
317
+ const puppetStyle = computed(() => {
318
+ const [width, height] = reversedCoverSize.value;
319
+ const scale = imgWidth.value / width || 1;
320
+ const x = imgLeft.value;
321
+ const y = imgTop.value;
322
+ return {
323
+ width: width + "px",
324
+ height: height + "px",
325
+ transform: `translate3d(${x}px, ${y}px, 0) scale(${scale})`,
326
+ transition: isStillRotating.value || isCaptured.value || inInertia.value ? "none" : ""
327
+ };
328
+ });
329
+ const imageStyle = computed(() => {
330
+ const [reversedCoverWidth, reversedCoverHeight] = reversedCoverSize.value;
331
+ const r = Math.abs(actualRotate.value) % 360;
332
+ const [width, height] = r % 180 !== 0 ? [reversedCoverHeight, reversedCoverWidth] : [reversedCoverWidth, reversedCoverHeight];
333
+ return {
334
+ width: width + "px",
335
+ height: height + "px",
336
+ transform: `translate(-50%, -50%) rotate(${actualRotate.value}deg)`
337
+ };
338
+ });
339
+ const onImageTouchStart = (event) => {
340
+ if (isWeb) {
341
+ event.preventDefault();
342
+ }
343
+ };
344
+ let stopInertialAnimate = null;
345
+ onBeforeUnmount(() => {
346
+ stopInertialAnimate?.();
347
+ });
348
+ const { onMouseDown, onTouchStart, onTouchMove, onTouchEnd } = useDragPinch({
349
+ onOffset(offsetX, offsetY) {
350
+ const [, , focusWidth, focusHeight] = focusRect.value;
351
+ if (imgWidth.value !== focusWidth) {
352
+ if (imgLeft.value > 0 || imgLeft.value < focusWidth - imgWidth.value) {
353
+ offsetX /= bounceCoeff;
354
+ }
355
+ imgLeft.value += offsetX;
356
+ }
357
+ if (imgHeight.value !== focusHeight) {
358
+ if (imgTop.value > 0 || imgTop.value < focusHeight - imgHeight.value) {
359
+ offsetY /= bounceCoeff;
360
+ }
361
+ imgTop.value += offsetY;
362
+ }
363
+ },
364
+ onScale(originX, originY, scale) {
365
+ const [focusLeft, focusTop, focusWidth, focusHeight] = focusRect.value;
366
+ let offsetScaleX = imgWidth.value * scale;
367
+ let offsetScaleY = imgHeight.value * scale;
368
+ if (imgWidth.value < focusWidth || imgHeight.value < focusHeight) {
369
+ offsetScaleX /= bounceCoeff;
370
+ offsetScaleY /= bounceCoeff;
371
+ } else if (imgWidth.value > reversedCoverSize.value[0] * maxScale && offsetScaleX > 0) {
372
+ offsetScaleX = 0;
373
+ offsetScaleY = 0;
374
+ }
375
+ const nextWidth = imgWidth.value + offsetScaleX;
376
+ const nextHeight = imgHeight.value + offsetScaleY;
377
+ const originScaleX = (originX - focusLeft - imgLeft.value) / imgWidth.value;
378
+ const originScaleY = (originY - focusTop - imgTop.value) / imgHeight.value;
379
+ imgLeft.value += (imgWidth.value - nextWidth) * originScaleX;
380
+ imgTop.value += (imgHeight.value - nextHeight) * originScaleY;
381
+ imgWidth.value = nextWidth;
382
+ imgHeight.value = nextHeight;
383
+ },
384
+ onCapture() {
385
+ isCaptured.value = true;
386
+ stopInertialAnimate?.();
387
+ },
388
+ onRelease(v) {
389
+ const [, , focusWidth, focusHeight] = focusRect.value;
390
+ const currWidth = imgWidth.value;
391
+ const currHeight = imgHeight.value;
392
+ const tooSmall = currWidth < focusWidth || currHeight < focusHeight;
393
+ const tooBig = currWidth > reversedCoverSize.value[0] * maxScale;
394
+ if (tooSmall || tooBig) {
395
+ const [width, height] = tooSmall ? getAspectFillSize(currWidth, currHeight, focusWidth, focusHeight) : reversedCoverSize.value.map((item) => item * maxScale);
396
+ imgWidth.value = width;
397
+ imgHeight.value = height;
398
+ imgLeft.value += (currWidth - width) / 2;
399
+ imgTop.value += (currHeight - height) / 2;
400
+ }
401
+ const overLeft = imgLeft.value > 0;
402
+ const overRight = imgLeft.value < focusWidth - imgWidth.value;
403
+ if (overLeft) {
404
+ imgLeft.value = 0;
405
+ } else if (overRight) {
406
+ imgLeft.value = focusWidth - imgWidth.value;
407
+ }
408
+ const overTop = imgTop.value > 0;
409
+ const overBottom = imgTop.value < focusHeight - imgHeight.value;
410
+ if (overTop) {
411
+ imgTop.value = 0;
412
+ } else if (overBottom) {
413
+ imgTop.value = focusHeight - imgHeight.value;
414
+ }
415
+ isCaptured.value = false;
416
+ if (tooSmall || overLeft || overRight || overTop || overBottom) return;
417
+ if (v.x === 0 && v.y === 0) return;
418
+ inInertia.value = true;
419
+ const animateList = [
420
+ [v.x, imgLeft, focusWidth, imgWidth.value],
421
+ [v.y, imgTop, focusHeight, imgHeight.value]
422
+ ].filter(([v2]) => v2 !== 0).map(([v2, translate, boxSize, elSize]) => {
423
+ const animate = createInertialAnimate(v2, {
424
+ update(value) {
425
+ let next = translate.value + value;
426
+ const overStart = next > 0;
427
+ const overEnd = next < boxSize - elSize;
428
+ if (overStart) {
429
+ next = 0;
430
+ } else if (overEnd) {
431
+ next = boxSize - elSize;
432
+ }
433
+ translate.value = next;
434
+ if (overStart || overEnd) {
435
+ animate.stop();
436
+ tryFinish();
437
+ }
438
+ },
439
+ complete() {
440
+ tryFinish();
441
+ }
442
+ });
443
+ animate.play();
444
+ return animate;
445
+ });
446
+ const tryFinish = () => {
447
+ if (animateList.every((animate) => !animate.isAnimating())) {
448
+ inInertia.value = false;
449
+ }
450
+ };
451
+ stopInertialAnimate = () => {
452
+ animateList.forEach((animate) => {
453
+ animate.stop();
454
+ });
455
+ inInertia.value = false;
456
+ stopInertialAnimate = null;
457
+ };
458
+ }
459
+ });
460
+ const instance = getCurrentInstance();
461
+ const canvasId = uniqid();
462
+ let context;
463
+ let canvas;
464
+ const getCanvas = async () => {
465
+ if (isApp) {
466
+ context = uni.createCanvasContext(canvasId, instance);
467
+ } else {
468
+ canvas = await getNode(`#${canvasId}`, instance);
469
+ context = canvas.getContext("2d");
470
+ }
471
+ };
472
+ const onAfterEnter = () => {
473
+ getCanvas();
474
+ };
475
+ const canvasWidth = ref(0);
476
+ const canvasHeight = ref(0);
477
+ const canvasStyle = computed(() => {
478
+ return {
479
+ width: canvasWidth.value + "px",
480
+ height: canvasHeight.value + "px"
481
+ };
482
+ });
483
+ const cropImage = async () => {
484
+ return new Promise((resolve, reject) => {
485
+ const [imgOrigW, imgOrigH] = imageOrigSize.value;
486
+ const [, , focusWidth, focusHeight] = focusRect.value;
487
+ const rotate2 = actualRotate.value % 360;
488
+ let scale = (rotate2 % 180 !== 0 ? imgOrigH : imgOrigW) / imgWidth.value;
489
+ let canvasW = focusWidth * scale;
490
+ let canvasH = focusHeight * scale;
491
+ let customScale = 1;
492
+ if (props.beforeCrop) {
493
+ customScale = props.beforeCrop(canvasW, canvasH);
494
+ }
495
+ canvasW *= customScale;
496
+ canvasH *= customScale;
497
+ scale *= customScale;
498
+ const imgL = imgLeft.value * scale;
499
+ const imgT = imgTop.value * scale;
500
+ const imgW = imgOrigW * customScale;
501
+ const imgH = imgOrigH * customScale;
502
+ let tx = 0;
503
+ let ty = 0;
504
+ switch (rotate2) {
505
+ case 0:
506
+ tx = imgL;
507
+ ty = imgT;
508
+ break;
509
+ case -90:
510
+ tx = (imgW + imgT) * -1;
511
+ ty = imgL;
512
+ break;
513
+ case -180:
514
+ tx = (imgW + imgL) * -1;
515
+ ty = (imgH + imgT) * -1;
516
+ break;
517
+ case -270:
518
+ tx = imgT;
519
+ ty = (imgH + imgL) * -1;
520
+ break;
521
+ }
522
+ canvasWidth.value = canvasW;
523
+ canvasHeight.value = canvasH;
524
+ if (!isApp) {
525
+ canvas.width = canvasW;
526
+ canvas.height = canvasH;
527
+ }
528
+ const canvasToTempFilePath = () => {
529
+ let width = canvasWidth.value;
530
+ let height = canvasHeight.value;
531
+ if (isWeb || isApp) {
532
+ width /= pixelRatio;
533
+ height /= pixelRatio;
534
+ }
535
+ const options = {
536
+ x: 0,
537
+ y: 0,
538
+ width,
539
+ height,
540
+ destWidth: canvasWidth.value,
541
+ destHeight: canvasHeight.value,
542
+ canvasId,
543
+ canvas,
544
+ fileType: props.type,
545
+ quality: props.quality,
546
+ success(res) {
547
+ resolve(res.tempFilePath);
548
+ },
549
+ fail(err) {
550
+ reject(err);
551
+ }
552
+ };
553
+ if (isAlipay) {
554
+ ;
555
+ canvas.toTempFilePath(options);
556
+ } else {
557
+ uni.canvasToTempFilePath(options);
558
+ }
559
+ };
560
+ const drawCanvas = (imgOrUrl) => {
561
+ context.clearRect(0, 0, canvasW, canvasH);
562
+ context.save();
563
+ context.rotate(rotate2 * (Math.PI / 180));
564
+ context.translate(tx, ty);
565
+ context.scale(customScale, customScale);
566
+ context.drawImage(
567
+ imgOrUrl,
568
+ 0,
569
+ 0,
570
+ imgOrigW,
571
+ imgOrigH,
572
+ 0,
573
+ 0,
574
+ imgOrigW,
575
+ imgOrigH
576
+ );
577
+ context.restore();
578
+ if (isApp) {
579
+ ;
580
+ context.draw(false, () => {
581
+ canvasToTempFilePath();
582
+ });
583
+ } else {
584
+ canvasToTempFilePath();
585
+ }
586
+ };
587
+ if (isApp) {
588
+ uni.getImageInfo({
589
+ src: props.src,
590
+ success(res) {
591
+ setTimeout(() => {
592
+ drawCanvas(res.path);
593
+ }, 50);
594
+ },
595
+ fail(err) {
596
+ reject(err);
597
+ }
598
+ });
599
+ } else {
600
+ const image = canvas.createImage ? canvas.createImage() : new Image();
601
+ image.src = props.src;
602
+ image.onload = async () => {
603
+ await sleep(50);
604
+ drawCanvas(image);
605
+ };
606
+ image.onerror = (err) => {
607
+ reject(err);
608
+ };
609
+ }
610
+ });
611
+ };
612
+ const onCancel = () => {
613
+ close();
614
+ };
615
+ const onReset = () => {
616
+ const current = Math.abs(rotate.value);
617
+ const integer = Math.floor(current / 360) * 360;
618
+ rotate.value = (integer + (current % 360 > 180 ? 360 : 0)) * -1;
619
+ };
620
+ const onRotate = () => {
621
+ rotate.value -= 90;
622
+ };
623
+ const isCropping = ref(false);
624
+ const onConfirm = () => {
625
+ if (isCropping.value) {
626
+ return;
627
+ }
628
+ isCropping.value = true;
629
+ cropImage().then((filePath) => {
630
+ close();
631
+ props.success?.(filePath);
632
+ }).catch((err) => {
633
+ uni.showToast({
634
+ icon: "none",
635
+ title: "\u9519\u8BEF" + err,
636
+ duration: 99999
637
+ });
638
+ props.fail?.(err);
639
+ }).finally(() => {
640
+ isCropping.value = false;
641
+ props.complete?.();
642
+ });
643
+ };
644
+ const cropImageClass = computed(() => {
645
+ return classNames(bem.b(), props.rootClass);
646
+ });
647
+ const cropImageStyle = computed(() => {
648
+ return stringifyStyle(props.rootStyle);
649
+ });
650
+ __expose({});
651
+ const __returned__ = { props, emit, bem, t, innerVisible, close, windowWidth, windowHeight, pixelRatio, aspectRatio, minGapY, minGapX, focusRect, rotate, actualRotate, onRotateEnd, isRotating, isStillRotating, stopRotateLater, cancelStopRotate, maskStyle, focusStyle, imageOrigSize, imageCoverSize, reversedCoverSize, imgLeft, imgTop, imgWidth, imgHeight, isCaptured, inInertia, puppetStyle, imageStyle, onImageTouchStart, bounceCoeff, maxScale, get stopInertialAnimate() {
652
+ return stopInertialAnimate;
653
+ }, set stopInertialAnimate(v) {
654
+ stopInertialAnimate = v;
655
+ }, onMouseDown, onTouchStart, onTouchMove, onTouchEnd, instance, canvasId, get context() {
656
+ return context;
657
+ }, set context(v) {
658
+ context = v;
659
+ }, get canvas() {
660
+ return canvas;
661
+ }, set canvas(v) {
662
+ canvas = v;
663
+ }, getCanvas, onAfterEnter, canvasWidth, canvasHeight, canvasStyle, cropImage, onCancel, onReset, onRotate, isCropping, onConfirm, cropImageClass, cropImageStyle, SarPopup, SarIcon, SarButton, SarLoading };
664
+ return __returned__;
665
+ }
666
+ });
667
+ </script>
668
+
669
+ <style lang="scss">
670
+ @import './index.scss';
671
+ </style>
@@ -0,0 +1 @@
1
+ export type { CropImageProps, CropImageSlots, CropImageEmits, CropImageExpose, } from './common';