@didaoktv/didaoui-uniapp 1.0.0 → 1.2.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 (114) hide show
  1. package/README.md +16 -7
  2. package/components/dd-action-sheet/dd-action-sheet.vue +3 -3
  3. package/components/dd-album/album.js +19 -0
  4. package/components/dd-album/dd-album.vue +345 -0
  5. package/components/dd-album/props.js +89 -0
  6. package/components/dd-avatar/avatar.js +19 -0
  7. package/components/dd-avatar/dd-avatar.vue +172 -160
  8. package/components/dd-avatar/props.js +84 -0
  9. package/components/dd-avatar-group/avatarGroup.js +14 -0
  10. package/components/dd-avatar-group/dd-avatar-group.vue +110 -0
  11. package/components/dd-avatar-group/props.js +57 -0
  12. package/components/dd-badge/dd-badge.vue +2 -2
  13. package/components/dd-barcode/dd-barcode.vue +1030 -0
  14. package/components/dd-bill-detail/dd-bill-detail.vue +265 -0
  15. package/components/dd-button/dd-button.vue +17 -17
  16. package/components/dd-calendar/dd-calendar.vue +357 -0
  17. package/components/dd-canvas/dd-canvas.vue +1088 -0
  18. package/components/dd-capsule-button/dd-capsule-button.vue +6 -6
  19. package/components/dd-car-keyboard/carKeyboard.js +6 -0
  20. package/components/dd-car-keyboard/dd-car-keyboard.vue +315 -0
  21. package/components/dd-car-keyboard/props.js +19 -0
  22. package/components/dd-cascader/dd-cascader.vue +405 -0
  23. package/components/dd-cell/dd-cell.vue +50 -23
  24. package/components/dd-cell-group/dd-cell-group.vue +32 -25
  25. package/components/dd-champion-card/dd-champion-card.vue +4 -4
  26. package/components/dd-checkbox/dd-checkbox.vue +30 -39
  27. package/components/dd-checkbox-group/dd-checkbox-group.vue +67 -0
  28. package/components/dd-copy/dd-copy.vue +74 -0
  29. package/components/dd-coupon/dd-coupon.vue +368 -0
  30. package/components/dd-cropper/dd-cropper.vue +1297 -0
  31. package/components/dd-dialog/dd-dialog.vue +1 -1
  32. package/components/dd-divider/dd-divider.vue +3 -3
  33. package/components/dd-dropdown-item/dd-dropdown-item.vue +5 -5
  34. package/components/dd-empty-state/dd-empty-state.vue +1 -1
  35. package/components/dd-field/dd-field.vue +531 -106
  36. package/components/dd-form/dd-form.vue +116 -0
  37. package/components/dd-form/rules.ts +84 -0
  38. package/components/dd-goods-sku/dd-goods-sku.vue +434 -0
  39. package/components/dd-icon/dd-icon.vue +2 -2
  40. package/components/dd-image/dd-image.vue +4 -4
  41. package/components/dd-input/dd-input.vue +5 -5
  42. package/components/dd-keyboard/dd-keyboard.vue +178 -0
  43. package/components/dd-keyboard/keyboard.js +22 -0
  44. package/components/dd-keyboard/props.js +89 -0
  45. package/components/dd-link/dd-link.vue +87 -0
  46. package/components/dd-link/link.js +18 -0
  47. package/components/dd-link/props.js +44 -0
  48. package/components/dd-list-cell/dd-list-cell.vue +4 -4
  49. package/components/dd-loading/dd-loading.vue +1 -1
  50. package/components/dd-loadmore/dd-loadmore.vue +2 -2
  51. package/components/dd-markdown/dd-markdown.vue +344 -0
  52. package/components/dd-markdown/marked.esm.mjs +7 -0
  53. package/components/dd-mini-program-navbar/dd-mini-program-navbar.vue +9 -9
  54. package/components/dd-navigation/dd-navigation.vue +5 -5
  55. package/components/dd-number-keyboard/dd-number-keyboard.vue +200 -0
  56. package/components/dd-number-keyboard/numberKeyboard.js +8 -0
  57. package/components/dd-number-keyboard/props.js +24 -0
  58. package/components/dd-parse/dd-parse.vue +534 -0
  59. package/components/dd-parse/node/handler.wxs +26 -0
  60. package/components/dd-parse/node/node.vue +603 -0
  61. package/components/dd-parse/parse.js +13 -0
  62. package/components/dd-parse/parser.js +1400 -0
  63. package/components/dd-parse/props.js +57 -0
  64. package/components/dd-popover/dd-popover.vue +10 -10
  65. package/components/dd-popover-item/dd-popover-item.vue +3 -3
  66. package/components/dd-popup/dd-popup.vue +5 -5
  67. package/components/dd-poster/dd-poster.vue +695 -0
  68. package/components/dd-progress/dd-progress.vue +3 -3
  69. package/components/dd-pull-refresh/dd-pull-refresh.vue +3 -3
  70. package/components/dd-qrcode/dd-qrcode.vue +509 -0
  71. package/components/dd-qrcode/qrcode.js +1283 -0
  72. package/components/dd-radio/dd-radio.vue +19 -20
  73. package/components/dd-radio-group/dd-radio-group.vue +53 -0
  74. package/components/dd-rate/dd-rate.vue +1 -1
  75. package/components/dd-room-card/dd-room-card.vue +3 -3
  76. package/components/dd-search-bar/dd-search-bar.vue +8 -8
  77. package/components/dd-segmented-tab/dd-segmented-tab.vue +6 -6
  78. package/components/dd-signature/dd-signature.vue +513 -0
  79. package/components/dd-skeleton/dd-skeleton.vue +1 -1
  80. package/components/dd-slider/dd-slider.vue +4 -4
  81. package/components/dd-stat-card/dd-stat-card.vue +5 -5
  82. package/components/dd-step/dd-step.vue +11 -11
  83. package/components/dd-stepper/dd-stepper.vue +6 -6
  84. package/components/dd-swipe-action/dd-swipe-action.vue +1 -1
  85. package/components/dd-swipeable-tab/dd-swipeable-tab.vue +1 -1
  86. package/components/dd-tabbar-item/dd-tabbar-item.vue +8 -8
  87. package/components/dd-tag/dd-tag.vue +17 -1
  88. package/components/dd-text/dd-text.vue +250 -0
  89. package/components/dd-text/props.js +120 -0
  90. package/components/dd-text/text.js +30 -0
  91. package/components/dd-text/value.js +87 -0
  92. package/components/dd-toast/dd-toast.vue +2 -2
  93. package/components/dd-upload/dd-upload.vue +4 -4
  94. package/components/dd-workorder-card/dd-workorder-card.vue +237 -0
  95. package/index.ts +50 -9
  96. package/libs/config/color.js +16 -0
  97. package/libs/config/config.js +25 -0
  98. package/libs/config/props.js +185 -0
  99. package/libs/config/zIndex.js +20 -0
  100. package/libs/function/digit.js +167 -0
  101. package/libs/function/index.js +932 -0
  102. package/libs/function/test.js +327 -0
  103. package/libs/i18n/index.d.ts +2 -0
  104. package/libs/i18n/index.js +89 -0
  105. package/libs/i18n/locales/zh-Hans.js +86 -0
  106. package/libs/mixin/button.js +18 -0
  107. package/libs/mixin/mixin.js +44 -0
  108. package/libs/mixin/mpMixin.js +13 -0
  109. package/libs/mixin/openType.js +27 -0
  110. package/libs/utils.ts +462 -0
  111. package/libs/vue.js +3 -0
  112. package/package.json +1 -1
  113. package/scss/_dd-shared.scss +40 -0
  114. package/scss/_variables.scss +4 -1
@@ -0,0 +1,1297 @@
1
+ <template>
2
+ <view class="dd-cropper">
3
+ <!-- <image :src="imgSrc.imgSrc" @click="select" :style="[ imgStyle ]" class="my-avatar"></image> -->
4
+ <dd-canvas ref="avatarCanvas" :canvas-id="'avatar-canvas-' + instanceId" class="my-canvas" :width="windowWidth || 0" :height="windowHeight || 0" :style="{ top: styleTop, height: cvsStyleHeight }" bg-color="transparent"></dd-canvas>
5
+ <dd-canvas ref="operCanvas" :canvas-id="'oper-canvas-' + instanceId" class="oper-canvas" :width="windowWidth || 0" :height="windowHeight || 0" :style="{ top: styleTop, height: cvsStyleHeight }" bg-color="transparent" @touchstart="start" @touchmove="move" @touchend="end"></dd-canvas>
6
+ <dd-canvas ref="prvCanvas" :canvas-id="'prv-canvas-' + instanceId" class="prv-canvas" :width="windowWidth || 0" :height="windowHeight || 0" bg-color="transparent" @touchstart="hideImg" :style="{ height: cvsStyleHeight, top: prvTop }"></dd-canvas>
7
+ <view class="oper-wrapper" :style="{ display: styleDisplay }">
8
+ <view class="oper">
9
+ <view class="btn-wrapper" v-if="showOper">
10
+ <view @click="select" hover-class="hover" :style="{ width: btnWidth }">
11
+ <text>{{ t("dd.common.re-select") }}</text>
12
+ </view>
13
+ <view @click="close" hover-class="hover" :style="{ width: btnWidth }">
14
+ <text>{{ t("dd.common.close") }}</text>
15
+ </view>
16
+ <view @click="rotate" hover-class="hover" :style="{ width: btnWidth, display: btnDsp }">
17
+ <text>{{ t("dd.common.rotate") }}</text>
18
+ </view>
19
+ <view @click="preview" hover-class="hover" :style="{ width: btnWidth }">
20
+ <text>{{ t("dd.common.preview") }}</text>
21
+ </view>
22
+ <view @click="confirm" hover-class="hover" :style="{ width: btnWidth }">
23
+ <text>{{ t("dd.common.confirm") }}</text>
24
+ </view>
25
+ </view>
26
+ <view class="clr-wrapper" v-else>
27
+ <slider class="my-slider" @change="colorChange" block-size="25" value="0" min="-100" max="100" activeColor="red" backgroundColor="green" block-color="grey" show-value></slider>
28
+ <view @click="prvUpload" hover-class="hover" :style="{ width: btnWidth }">
29
+ <text>{{ t("dd.common.confirm") }}</text>
30
+ </view>
31
+ </view>
32
+ </view>
33
+ </view>
34
+ <view @click="chooseImage(0, {})" v-if="styleDisplay == 'none'">
35
+ <slot>
36
+
37
+ </slot>
38
+ </view>
39
+ </view>
40
+ </template>
41
+
42
+ <script>
43
+ import { t } from '../../libs/i18n'
44
+ const tabHeight = 50;
45
+ export default {
46
+ name: "dd-cropper",
47
+ data() {
48
+ return {
49
+ // 添加实例ID用于区分不同实例
50
+ instanceId: Date.now() + '-' + Math.random().toString(36).substr(2, 9),
51
+ cvsStyleHeight: '0px',
52
+ styleDisplay: 'none',
53
+ styleTop: '-10000px',
54
+ prvTop: '-10000px',
55
+ imgStyle: {},
56
+ selStyle: {},
57
+ showOper: true,
58
+ imgSrc: {
59
+ imgSrc: ''
60
+ },
61
+ btnWidth: '19%',
62
+ btnDsp: 'flex',
63
+ // 裁剪区域宽度,用于设置选择区域的宽度
64
+ arWidth: '',
65
+ // 裁剪区域高度,用于设置选择区域的高度
66
+ arHeight: '',
67
+ // 导出图片宽度,用于设置最终导出图片的宽度
68
+ expWidth: '',
69
+ // 导出图片高度,用于设置最终导出图片的高度
70
+ expHeight: '',
71
+ // 是否允许调整裁剪框大小
72
+ letChangeSize: false,
73
+ // 底部安全区大小
74
+ safeAreaInsetsBottom: 0,
75
+ };
76
+ },
77
+ watch: {
78
+ avatarSrc() {
79
+ this.imgSrc.imgSrc = this.avatarSrc;
80
+ }
81
+ },
82
+ emits: ['avtinit', 'confirm'],
83
+ props: {
84
+ minScale: '',
85
+ maxScale: '',
86
+ canScale: true,
87
+ canRotate: true,
88
+ lockWidth: '',
89
+ lockHeight: '',
90
+ stretch: '',
91
+ lock: '',
92
+ noTab: true,
93
+ inner: false,
94
+ quality: '',
95
+ index: '',
96
+ canChangeSize: false,
97
+ areaWidth: '300rpx',
98
+ // 裁剪区域高度,用于设置选择区域的高度
99
+ areaHeight: '300rpx',
100
+ // 导出图片宽度,用于设置最终导出图片的宽度
101
+ exportWidth: '260rpx',
102
+ // 导出图片高度,用于设置最终导出图片的高度
103
+ exportHeight: '260rpx',
104
+ // 画布填充色,默认透明,可传 'black'、'#ffffff' 等
105
+ fillColor: {
106
+ type: String,
107
+ default: 'transparent'
108
+ },
109
+ },
110
+ created() {
111
+ this.ctxCanvas = null;
112
+ this.ctxCanvasOper = null;
113
+ this.ctxCanvasPrv = null;
114
+ this.qlty = parseInt(this.quality) || 0.9;
115
+ this.imgSrc.imgSrc = this.imageSrc;
116
+ this.letRotate = (this.canRotate === false || this.inner === true) ? 0 : 1;
117
+ this.letScale = this.canScale === false ? 0 : 1;
118
+ // 是否允许调整裁剪框大小,false表示不允许,其他值表示允许
119
+ this.letChangeSize = this.canChangeSize;
120
+ this.isin = this.inner === true ? 1 : 0;
121
+ this.indx = this.index || undefined;
122
+ this.mnScale = this.minScale || 0.3;
123
+ this.mxScale = this.maxScale || 4;
124
+ this.noBar = this.noTab === true ? 1 : 0;
125
+ this.stc = this.stretch;
126
+ this.lck = this.lock;
127
+ if (this.isin) {
128
+ this.btnWidth = '24%';
129
+ this.btnDsp = 'none';
130
+ } else {
131
+ this.btnWidth = '19%';
132
+ this.btnDsp = 'flex';
133
+ }
134
+
135
+ if (this.noBar) {
136
+ this.moreHeight = 0;
137
+ this.windowResize();
138
+ } else {
139
+ uni.showTabBar({
140
+ complete: (res) => {
141
+ this.moreHeight = (res.errMsg === 'showTabBar:ok') ? 50 : 0;
142
+ this.windowResize();
143
+ }
144
+ });
145
+ }
146
+ },
147
+ mounted() {
148
+ this.initCanvasRefs(true);
149
+ },
150
+ methods: {
151
+ t,
152
+ async initCanvasRefs(force = false) {
153
+ await this.$nextTick();
154
+ const avatarCanvas = this.$refs.avatarCanvas;
155
+ const operCanvas = this.$refs.operCanvas;
156
+ const prvCanvas = this.$refs.prvCanvas;
157
+ if (!avatarCanvas || !operCanvas || !prvCanvas) return false;
158
+ await Promise.all([
159
+ avatarCanvas.initCanvas(force),
160
+ operCanvas.initCanvas(force),
161
+ prvCanvas.initCanvas(force)
162
+ ]);
163
+ this.ctxCanvas = avatarCanvas;
164
+ this.ctxCanvasOper = operCanvas;
165
+ this.ctxCanvasPrv = prvCanvas;
166
+ return true;
167
+ },
168
+ windowResize() {
169
+ let sysInfo = uni.getSystemInfoSync();
170
+ this.platform = sysInfo.platform;
171
+ this.pixelRatio = sysInfo.pixelRatio;
172
+ this.windowWidth = sysInfo.windowWidth;
173
+ this.safeAreaInsetsBottom = sysInfo.safeAreaInsets.bottom;
174
+ // #ifdef H5
175
+ this.drawTop = sysInfo.windowTop;
176
+ this.windowHeight = sysInfo.windowHeight + sysInfo.windowBottom;
177
+ this.cvsStyleHeight = this.windowHeight - tabHeight + 'px';
178
+ // #endif
179
+ // #ifdef APP-PLUS
180
+ if (this.platform === 'android') {
181
+ this.windowHeight = sysInfo.screenHeight + sysInfo.statusBarHeight;
182
+ this.cvsStyleHeight = this.windowHeight - tabHeight + 'px';
183
+ } else {
184
+ this.windowHeight = sysInfo.windowHeight + this.moreHeight;
185
+ this.cvsStyleHeight = this.windowHeight - tabHeight - this.safeAreaInsetsBottom + 6 + 'px';
186
+ }
187
+ // #endif
188
+ // #ifdef MP
189
+ this.windowHeight = sysInfo.windowHeight + this.moreHeight;
190
+ this.cvsStyleHeight = this.windowHeight - tabHeight - this.safeAreaInsetsBottom - 2 + 'px';
191
+ // #endif
192
+ this.pxRatio = this.windowWidth / 750;
193
+
194
+ let style = this.avatarStyle;
195
+ if (style && style !== true && (style = style.trim())) {
196
+ style = style.split(';');
197
+ let obj = {};
198
+ for (let v of style) {
199
+ if (!v) continue;
200
+ v = v.trim().split(':');
201
+ if (v[1].indexOf('rpx') >= 0) {
202
+ let arr = v[1].trim().split(' ');
203
+ for (let k in arr) {
204
+ if (!arr[k]) continue;
205
+ if (arr[k].indexOf('rpx') >= 0) {
206
+ arr[k] = parseFloat(arr[k]) * this.pxRatio + 'px';
207
+ }
208
+ }
209
+ v[1] = arr.join(' ');
210
+ }
211
+ obj[v[0].trim()] = v[1].trim();
212
+ }
213
+ this.imgStyle = obj;
214
+ }
215
+
216
+ this.expWidth && (this.expWidth = this.expWidth.indexOf('rpx') >= 0 ? parseInt(this.expWidth) * this.pxRatio : parseInt(this.expWidth));
217
+ this.expHeight && (this.expHeight = this.expHeight.indexOf('rpx') >= 0 ? parseInt(this.expHeight) * this.pxRatio : parseInt(this.expHeight));
218
+
219
+ if (this.styleDisplay === 'flex') {
220
+ this.drawInit(true);
221
+ }
222
+ this.hideImg();
223
+ },
224
+ select() {
225
+ if (this.fSelecting) return;
226
+ this.fSelecting = true;
227
+ setTimeout(() => { this.fSelecting = false; }, 500);
228
+ const self = this
229
+ uni.chooseImage({
230
+ count: 1,
231
+ sizeType: ['original', 'compressed'],
232
+ sourceType: ['album', 'camera'],
233
+ success: (r) => {
234
+ uni.showLoading({ mask: true });
235
+ let path = this.imgPath = r.tempFilePaths[0];
236
+ uni.getImageInfo({
237
+ src: path,
238
+ success: r => {
239
+ this.imgWidth = r.width;
240
+ this.imgHeight = r.height;
241
+ this.path = path;
242
+ if (!this.hasSel) {
243
+ let style = this.selStyle || {};
244
+ if (this.arWidth && this.arHeight) {
245
+ let areaWidth = this.arWidth.indexOf('rpx') >= 0 ? parseInt(this.arWidth) * this.pxRatio : parseInt(this.arWidth),
246
+ areaHeight = this.arHeight.indexOf('rpx') >= 0 ? parseInt(this.arHeight) * this.pxRatio : parseInt(this.arHeight);
247
+ style.width = areaWidth + 'px';
248
+ style.height = areaHeight + 'px';
249
+ style.top = (this.windowHeight - areaHeight - tabHeight) / 2 + 'px';
250
+ style.left = (this.windowWidth - areaWidth) / 2 + 'px';
251
+ } else {
252
+ uni.showModal({
253
+ title: t("dd.cropper.emptyWidhtOrHeight"),
254
+ showCancel: false
255
+ })
256
+ return;
257
+ }
258
+ this.selStyle = style;
259
+ }
260
+
261
+ if (this.noBar) {
262
+ this.drawInit(true);
263
+ } else {
264
+ uni.hideTabBar({
265
+ complete: () => {
266
+ this.drawInit(true);
267
+ }
268
+ });
269
+ }
270
+ },
271
+ fail: () => {
272
+ uni.showToast({
273
+ title: "error3",
274
+ duration: 2000,
275
+ })
276
+ },
277
+ complete() {
278
+ uni.hideLoading();
279
+ }
280
+ });
281
+ }, fail(err) {
282
+ self.$emit('cancel')
283
+ }
284
+ })
285
+ },
286
+ async confirm() {
287
+ if (this.fUploading) return;
288
+ this.fUploading = true;
289
+ setTimeout(() => { this.fUploading = false; }, 1000)
290
+
291
+ let style = this.selStyle,
292
+ x = parseInt(style.left),
293
+ y = parseInt(style.top),
294
+ width = parseInt(style.width),
295
+ height = parseInt(style.height),
296
+ expWidth = this.expWidth || width,
297
+ expHeight = this.expHeight || height;
298
+
299
+ // #ifdef H5
300
+ // x *= this.pixelRatio;
301
+ // y *= this.pixelRatio;
302
+ expWidth = width;
303
+ expHeight = height;
304
+ // #endif
305
+
306
+ uni.showLoading({ mask: true });
307
+ this.styleDisplay = 'none';
308
+ this.styleTop = '-10000px';
309
+ this.hasSel = false;
310
+ this.hideImg();
311
+ await this.initCanvasRefs();
312
+ this.ctxCanvas.toTempFilePath({
313
+ x: x,
314
+ y: y,
315
+ width: width,
316
+ height: height,
317
+ destWidth: expWidth,
318
+ destHeight: expHeight,
319
+ fileType: 'png',
320
+ quality: this.qlty,
321
+ success: (r) => {
322
+ r = r.tempFilePath;
323
+ // #ifdef H5
324
+ this.btop(r).then(async (r) => {
325
+ if (this.expWidth && this.expHeight) {
326
+ let ctxCanvas = this.ctxCanvas;
327
+ expWidth = this.expWidth,
328
+ expHeight = this.expHeight;
329
+
330
+ await ctxCanvas.drawImage(r, 0, 0, expWidth, expHeight);
331
+ ctxCanvas.draw(false, () => {
332
+ ctxCanvas.toTempFilePath({
333
+ x: 0,
334
+ y: 0,
335
+ width: expWidth,
336
+ height: expHeight,
337
+ destWidth: expWidth,
338
+ destHeight: expHeight,
339
+ fileType: 'png',
340
+ quality: this.qlty,
341
+ success: (r) => {
342
+ r = r.tempFilePath;
343
+ this.btop(r).then((r) => {
344
+ this.$emit("confirm", { avatar: this.imgSrc, path: r, index: this.indx, data: this.rtn });
345
+ });
346
+ },
347
+ fail: () => {
348
+ uni.showToast({
349
+ title: "error0",
350
+ duration: 2000,
351
+ })
352
+ }
353
+ });
354
+ });
355
+ } else {
356
+ this.$emit("confirm", { avatar: this.imgSrc, path: r, index: this.indx, data: this.rtn });
357
+ }
358
+ })
359
+ // #endif
360
+ // #ifndef H5
361
+ this.$emit("confirm", { avatar: this.imgSrc, path: r, index: this.indx, data: this.rtn });
362
+ // #endif
363
+ },
364
+ fail: (res) => {
365
+ uni.showToast({
366
+ title: "error1",
367
+ duration: 2000,
368
+ })
369
+ },
370
+ complete: () => {
371
+ uni.hideLoading();
372
+ this.noBar || uni.showTabBar();
373
+ }
374
+ });
375
+ },
376
+ // 用户点击"预览"模式下的"确认"按钮时被调用,用于将预览的裁剪结果上传
377
+ async prvUpload() {
378
+ if (this.fPrvUploading) return;
379
+ this.fPrvUploading = true;
380
+ setTimeout(() => { this.fPrvUploading = false; }, 1000)
381
+
382
+ let style = this.selStyle,
383
+ destWidth = parseInt(style.width),
384
+ destHeight = parseInt(style.height),
385
+ prvX = this.prvX,
386
+ prvY = this.prvY,
387
+ prvWidth = this.prvWidth,
388
+ prvHeight = this.prvHeight,
389
+ expWidth = this.expWidth || prvWidth,
390
+ expHeight = this.expHeight || prvHeight;
391
+
392
+ // #ifdef H5
393
+ // prvX *= this.pixelRatio;
394
+ // prvY *= this.pixelRatio;
395
+ expWidth = prvWidth;
396
+ expHeight = prvHeight;
397
+ // #endif
398
+
399
+ uni.showLoading({ mask: true });
400
+
401
+ this.styleDisplay = 'none';
402
+ this.styleTop = '-10000px';
403
+ this.hasSel = false;
404
+ this.hideImg();
405
+ await this.initCanvasRefs();
406
+ this.ctxCanvasPrv.toTempFilePath({
407
+ x: prvX,
408
+ y: prvY,
409
+ width: prvWidth,
410
+ height: prvHeight,
411
+ destWidth: expWidth,
412
+ destHeight: expHeight,
413
+ fileType: 'png',
414
+ quality: this.qlty,
415
+ success: (r) => {
416
+ r = r.tempFilePath;
417
+ // #ifdef H5
418
+ this.btop(r).then(async (r) => {
419
+ if (this.expWidth && this.expHeight) {
420
+ let ctxCanvas = this.ctxCanvas;
421
+ expWidth = this.expWidth,
422
+ expHeight = this.expHeight;
423
+
424
+ await ctxCanvas.drawImage(r, 0, 0, expWidth, expHeight);
425
+ ctxCanvas.draw(false, () => {
426
+ ctxCanvas.toTempFilePath({
427
+ x: 0,
428
+ y: 0,
429
+ width: expWidth,
430
+ height: expHeight,
431
+ destWidth: expWidth,
432
+ destHeight: expHeight,
433
+ fileType: 'png',
434
+ quality: this.qlty,
435
+ success: (r) => {
436
+ r = r.tempFilePath;
437
+ this.btop(r).then((r) => {
438
+ this.$emit("confirm", { avatar: this.imgSrc, path: r, index: this.indx, data: this.rtn });
439
+ });
440
+ },
441
+ fail: () => {
442
+ uni.showToast({
443
+ title: "error0",
444
+ duration: 2000,
445
+ })
446
+ }
447
+ });
448
+ });
449
+ } else {
450
+ this.$emit("confirm", { avatar: this.imgSrc, path: r, index: this.indx, data: this.rtn });
451
+ }
452
+ })
453
+ // #endif
454
+ // #ifndef H5
455
+ this.$emit("confirm", { avatar: this.imgSrc, path: r, index: this.indx, data: this.rtn });
456
+ // #endif
457
+ },
458
+ fail: () => {
459
+ uni.showToast({
460
+ title: "error_prv",
461
+ duration: 2000,
462
+ })
463
+ },
464
+ complete: () => {
465
+ uni.hideLoading();
466
+ this.noBar || uni.showTabBar();
467
+ }
468
+ });
469
+ },
470
+ async drawInit(ini = false) {
471
+ await this.initCanvasRefs();
472
+ let allWidth = this.windowWidth,
473
+ allHeight = this.windowHeight,
474
+ imgWidth = this.imgWidth,
475
+ imgHeight = this.imgHeight,
476
+ imgRadio = imgWidth / imgHeight,
477
+ useWidth = allWidth - 40,
478
+ useHeight = allHeight - tabHeight - 80,
479
+ pixelRatio = this.pixelRatio,
480
+ selWidth = parseInt(this.selStyle.width),
481
+ selHeight = parseInt(this.selStyle.height);
482
+
483
+ this.fixWidth = 0;
484
+ this.fixHeight = 0;
485
+ this.lckWidth = 0;
486
+ this.lckHeight = 0;
487
+ switch (this.stc) {
488
+ case 'x': this.fixWidth = 1; break;
489
+ case 'y': this.fixHeight = 1; break;
490
+ case 'long': if (imgRadio > 1) this.fixWidth = 1; else this.fixHeight = 1; break;
491
+ case 'short': if (imgRadio > 1) this.fixHeight = 1; else this.fixWidth = 1; break;
492
+ case 'longSel': if (selWidth > selHeight) this.fixWidth = 1; else this.fixHeight = 1; break;
493
+ case 'shortSel': if (selWidth > selHeight) this.fixHeight = 1; else this.fixWidth = 1; break;
494
+ }
495
+ // lck 用于控制裁剪框的宽度和高度锁定行为
496
+ // 'x': 锁定宽度,不允许水平方向调整
497
+ // 'y': 锁定高度,不允许垂直方向调整
498
+ // 'long': 根据图片长边锁定,如果图片横向较长则锁定宽度,否则锁定高度
499
+ // 'short': 根据图片短边锁定,如果图片横向较长则锁定高度,否则锁定宽度
500
+ // 'longSel': 根据选择框的长边锁定,如果选择框宽度大于高度则锁定宽度,否则锁定高度
501
+ // 'shortSel': 根据选择框的短边锁定,如果选择框宽度大于高度则锁定高度,否则锁定宽度
502
+ switch (this.lck) {
503
+ case 'x': this.lckWidth = 1; break;
504
+ case 'y': this.lckHeight = 1; break;
505
+ case 'long': if (imgRadio > 1) this.lckWidth = 1; else this.lckHeight = 1; break;
506
+ case 'short': if (imgRadio > 1) this.lckHeight = 1; else this.lckWidth = 1; break;
507
+ case 'longSel': if (selWidth > selHeight) this.lckWidth = 1; else this.lckHeight = 1; break;
508
+ case 'shortSel': if (selWidth > selHeight) this.lckHeight = 1; else this.lckWidth = 1; break;
509
+ }
510
+ if (this.fixWidth) {
511
+ useWidth = selWidth;
512
+ useHeight = useWidth / imgRadio;
513
+ } else if (this.fixHeight) {
514
+ useHeight = selHeight;
515
+ useWidth = useHeight * imgRadio;
516
+ } else if (imgRadio < 1) {
517
+ if (imgHeight < useHeight) {
518
+ useWidth = imgWidth;
519
+ useHeight = imgHeight;
520
+ } else {
521
+ useHeight = useHeight;
522
+ useWidth = useHeight * imgRadio;
523
+ }
524
+ } else {
525
+ if (imgWidth < useWidth) {
526
+ useWidth = imgWidth;
527
+ useHeight = imgHeight;
528
+ } else {
529
+ useWidth = useWidth;
530
+ useHeight = useWidth / imgRadio;
531
+ }
532
+ }
533
+ if (this.isin) {
534
+ this.scaleWidth = 0;
535
+ this.scaleHeight = 0;
536
+ if (useWidth < selWidth) {
537
+ useWidth = selWidth;
538
+ useHeight = useWidth / imgRadio;
539
+ this.lckHeight = 0;
540
+ }
541
+ if (useHeight < selHeight) {
542
+ useHeight = selHeight;
543
+ useWidth = useHeight * imgRadio;
544
+ this.lckWidth = 0;
545
+ }
546
+ }
547
+
548
+ this.scaleSize = 1;
549
+ this.rotateDeg = 0;
550
+ this.posWidth = (allWidth - useWidth) / 2;
551
+ this.posHeight = (allHeight - useHeight - tabHeight) / 2;
552
+ this.useWidth = useWidth;
553
+ this.useHeight = useHeight;
554
+
555
+ let style = this.selStyle,
556
+ left = parseInt(style.left),
557
+ top = parseInt(style.top),
558
+ width = parseInt(style.width),
559
+ height = parseInt(style.height),
560
+ canvas = this.canvas,
561
+ canvasOper = this.canvasOper,
562
+ ctxCanvas = this.ctxCanvas,
563
+ ctxCanvasOper = this.ctxCanvasOper;
564
+
565
+ ctxCanvasOper.setLineWidth(3);
566
+ ctxCanvasOper.setStrokeStyle('grey');
567
+ ctxCanvasOper.setGlobalAlpha(0.4);
568
+ ctxCanvasOper.setFillStyle('black');
569
+ ctxCanvasOper.strokeRect(left, top, width, height);
570
+ ctxCanvasOper.fillRect(0, 0, this.windowWidth, top);
571
+ ctxCanvasOper.fillRect(0, top, left, height);
572
+ ctxCanvasOper.fillRect(0, top + height, this.windowWidth, this.windowHeight - height - top - tabHeight);
573
+ ctxCanvasOper.fillRect(left + width, top, this.windowWidth - width - left, height);
574
+ ctxCanvasOper.setStrokeStyle('red');
575
+ ctxCanvasOper.moveTo(left + 20, top); ctxCanvasOper.lineTo(left, top); ctxCanvasOper.lineTo(left, top + 20);
576
+ ctxCanvasOper.moveTo(left + width - 20, top); ctxCanvasOper.lineTo(left + width, top); ctxCanvasOper.lineTo(left + width, top + 20);
577
+ ctxCanvasOper.moveTo(left + 20, top + height); ctxCanvasOper.lineTo(left, top + height); ctxCanvasOper.lineTo(left, top + height - 20);
578
+ ctxCanvasOper.moveTo(left + width - 20, top + height); ctxCanvasOper.lineTo(left + width, top + height); ctxCanvasOper.lineTo(left + width, top + height - 20);
579
+
580
+ // 绘制控制点(四个角)
581
+ const controlPointSize = 10;
582
+ ctxCanvasOper.setFillStyle('white');
583
+ ctxCanvasOper.setStrokeStyle('grey');
584
+ ctxCanvasOper.setLineWidth(1);
585
+ // 左上角
586
+ ctxCanvasOper.fillRect(left - controlPointSize / 2, top - controlPointSize / 2, controlPointSize, controlPointSize);
587
+ ctxCanvasOper.strokeRect(left - controlPointSize / 2, top - controlPointSize / 2, controlPointSize, controlPointSize);
588
+ // 右上角
589
+ ctxCanvasOper.fillRect(left + width - controlPointSize / 2, top - controlPointSize / 2, controlPointSize, controlPointSize);
590
+ ctxCanvasOper.strokeRect(left + width - controlPointSize / 2, top - controlPointSize / 2, controlPointSize, controlPointSize);
591
+ // 左下角
592
+ ctxCanvasOper.fillRect(left - controlPointSize / 2, top + height - controlPointSize / 2, controlPointSize, controlPointSize);
593
+ ctxCanvasOper.strokeRect(left - controlPointSize / 2, top + height - controlPointSize / 2, controlPointSize, controlPointSize);
594
+ // 右下角
595
+ ctxCanvasOper.fillRect(left + width - controlPointSize / 2, top + height - controlPointSize / 2, controlPointSize, controlPointSize);
596
+ ctxCanvasOper.strokeRect(left + width - controlPointSize / 2, top + height - controlPointSize / 2, controlPointSize, controlPointSize);
597
+
598
+ ctxCanvasOper.stroke();
599
+
600
+ ctxCanvasOper.draw(false, () => {
601
+ if (ini) {
602
+ this.styleDisplay = 'flex';
603
+ // #ifdef H5
604
+ this.styleTop = this.drawTop + 'px';
605
+ // #endif
606
+ // #ifndef H5
607
+ this.styleTop = '0';
608
+ // #endif
609
+ if (this.fillColor && this.fillColor !== 'transparent') {
610
+ ctxCanvas.setFillStyle(this.fillColor);
611
+ }
612
+ this.drawImage();
613
+ }
614
+ });
615
+
616
+ this.$emit("avtinit");
617
+ },
618
+ async drawImage() {
619
+ await this.initCanvasRefs();
620
+ let tm_now = Date.now();
621
+ if (tm_now - this.drawTm < 20) return;
622
+ this.drawTm = tm_now;
623
+ let ctxCanvas = this.ctxCanvas;
624
+ if (this.fillColor && this.fillColor !== 'transparent') {
625
+ ctxCanvas.fillRect(0, 0, this.windowWidth, this.windowHeight - tabHeight);
626
+ }
627
+ ctxCanvas.save();
628
+ ctxCanvas.translate(this.posWidth + this.useWidth / 2, this.posHeight + this.useHeight / 2);
629
+ ctxCanvas.scale(this.scaleSize, this.scaleSize);
630
+ ctxCanvas.rotate(this.rotateDeg * Math.PI / 180);
631
+ await ctxCanvas.drawImage(this.imgPath, -this.useWidth / 2, -this.useHeight / 2, this.useWidth, this.useHeight);
632
+ ctxCanvas.restore();
633
+ ctxCanvas.draw(false);
634
+ },
635
+ hideImg() {
636
+ this.prvImg = '';
637
+ this.prvTop = '-10000px';
638
+ this.showOper = true;
639
+ this.prvImgData = null;
640
+ this.target = null;
641
+ },
642
+ close() {
643
+ console.log('up-cropper close');
644
+
645
+ this.styleDisplay = 'none';
646
+ this.styleTop = '-10000px';
647
+ this.hasSel = false;
648
+ this.hideImg();
649
+ this.noBar || uni.showTabBar();
650
+ this.$emit('cancel');
651
+ },
652
+ async preview() {
653
+ if (this.fPreviewing) return;
654
+ this.fPreviewing = true;
655
+ setTimeout(() => { this.fPreviewing = false; }, 1000);
656
+ let style = this.selStyle,
657
+ x = parseInt(style.left),
658
+ y = parseInt(style.top),
659
+ width = parseInt(style.width),
660
+ height = parseInt(style.height);
661
+
662
+ uni.showLoading({ mask: true });
663
+ // console.log('size', x, y, width, height)
664
+ await this.initCanvasRefs();
665
+ this.ctxCanvas.toTempFilePath({
666
+ x: x,
667
+ y: y,
668
+ width: width,
669
+ height: height,
670
+ fileType: 'png',
671
+ quality: this.qlty,
672
+ success: async (r) => {
673
+ // console.log(r)
674
+ this.prvImgTmp = r = r.tempFilePath;
675
+
676
+ let ctxCanvasPrv = this.ctxCanvasPrv,
677
+ prvX = this.windowWidth,
678
+ prvY = parseInt(this.cvsStyleHeight),
679
+ prvWidth = parseInt(this.selStyle.width),
680
+ prvHeight = parseInt(this.selStyle.height),
681
+ useWidth = prvX - 40,
682
+ useHeight = prvY - 80,
683
+ radio = useWidth / prvWidth,
684
+ rHeight = prvHeight * radio;
685
+ if (rHeight < useHeight) {
686
+ prvWidth = useWidth;
687
+ prvHeight = rHeight;
688
+ } else {
689
+ radio = useHeight / prvHeight;
690
+ prvWidth *= radio;
691
+ prvHeight = useHeight;
692
+ }
693
+ if (this.fillColor && this.fillColor !== 'transparent') {
694
+ ctxCanvasPrv.setFillStyle(this.fillColor);
695
+ ctxCanvasPrv.fillRect(0, 0, prvX, prvY);
696
+ ctxCanvasPrv.fillRect(x, y, width, height);
697
+ }
698
+ this.prvX = prvX = (prvX - prvWidth) / 2;
699
+ this.prvY = prvY = (prvY - prvHeight) / 2;
700
+ this.prvWidth = prvWidth;
701
+ this.prvHeight = prvHeight;
702
+ await ctxCanvasPrv.drawImage(r, prvX, prvY, prvWidth, prvHeight);
703
+ ctxCanvasPrv.draw(false, () => {
704
+ // #ifdef H5
705
+ this.btop(this.prvImgTmp).then((r) => {
706
+ this.showOper = false;
707
+ this.prvTop = this.drawTop + 'px';
708
+ })
709
+ // #endif
710
+ // #ifndef H5
711
+ if (this.platform != 'android') {
712
+ this.showOper = false;
713
+ }
714
+ this.prvTop = '0';
715
+ // #endif
716
+ });
717
+ },
718
+ fail: () => {
719
+ uni.showToast({
720
+ title: "error2",
721
+ duration: 2000,
722
+ })
723
+ },
724
+ complete: () => {
725
+ uni.hideLoading();
726
+ }
727
+ });
728
+ },
729
+ chooseImage(index = undefined, params = undefined, data = undefined) {
730
+ if (params) {
731
+ console.log(params)
732
+ let areaWidth = params.areaWidth || this.areaWidth,
733
+ areaHeight = params.areaHeight || this.areaHeight,
734
+ expWidth = params.exportWidth || this.exportWidth,
735
+ expHeight = params.exportHeight || this.exportHeight,
736
+ quality = params.quality,
737
+ canRotate = params.canRotate,
738
+ canScale = params.canScale,
739
+ canChangeSize = params.canChangeSize,
740
+ minScale = params.minScale,
741
+ maxScale = params.maxScale,
742
+ stretch = params.stretch,
743
+ inner = params.inner,
744
+ lock = params.lock;
745
+ console.log('areaWidth', this.areaWidth)
746
+
747
+ expWidth && (this.expWidth = expWidth.indexOf('rpx') >= 0 ? parseInt(expWidth) * this.pxRatio : parseInt(expWidth));
748
+ expHeight && (this.expHeight = expHeight.indexOf('rpx') >= 0 ? parseInt(expHeight) * this.pxRatio : parseInt(expHeight));
749
+ this.isin = inner === true ? 1 : 0;
750
+ this.letRotate = (canRotate === false || this.isin) ? 0 : 1;
751
+ this.letScale = canScale === false ? 0 : 1;
752
+ // 设置是否允许调整裁剪框大小
753
+ this.letChangeSize = canChangeSize || false;
754
+ this.qlty = parseInt(quality) || 0.9;
755
+ this.mnScale = minScale || 0.3;
756
+ this.mxScale = maxScale || 4;
757
+ this.stc = stretch;
758
+ this.lck = lock;
759
+ if (this.isin) {
760
+ this.btnWidth = '24%';
761
+ this.btnDsp = 'none';
762
+ } else {
763
+ this.btnWidth = '19%';
764
+ this.btnDsp = 'flex';
765
+ }
766
+
767
+ if (areaWidth && areaHeight) {
768
+ areaWidth = areaWidth.indexOf('rpx') >= 0 ? parseInt(areaWidth) * this.pxRatio : parseInt(areaWidth);
769
+ areaHeight = areaHeight.indexOf('rpx') >= 0 ? parseInt(areaHeight) * this.pxRatio : parseInt(areaHeight);
770
+ this.selStyle.width = areaWidth + 'px';
771
+ this.selStyle.height = areaHeight + 'px';
772
+ this.selStyle.top = (this.windowHeight - areaHeight - tabHeight) / 2 + 'px';
773
+ this.selStyle.left = (this.windowWidth - areaWidth) / 2 + 'px';
774
+ // console.log(this.selStyle);
775
+ this.hasSel = true;
776
+ }
777
+ }
778
+ this.rtn = data;
779
+ this.indx = index;
780
+ this.select();
781
+ },
782
+ rotate() {
783
+ // #ifdef APP-PLUS
784
+ if (this.platform === 'android') {
785
+ if (this.fRotateing) return;
786
+ this.fRotateing = true;
787
+ setTimeout(() => { this.fRotateing = false; }, 500);
788
+ }
789
+ // #endif
790
+
791
+ // if(this.letRotate) {
792
+ this.rotateDeg += 90 - this.rotateDeg % 90;
793
+ this.drawImage();
794
+ // }
795
+ },
796
+ start(e) {
797
+ let touches = e.touches,
798
+ touch0 = touches[0],
799
+ touch1 = touches[1];
800
+
801
+ this.touch0 = touch0;
802
+ this.touch1 = touch1;
803
+
804
+ if (touch1) {
805
+ let x = touch1.x - touch0.x,
806
+ y = touch1.y - touch0.y;
807
+ this.fgDistance = Math.sqrt(x * x + y * y);
808
+ } else {
809
+ // 只有在允许调整大小时才检查控制点
810
+ if (this.letChangeSize) {
811
+ // 检查是否点击在控制点上
812
+ const controlPointSize = 20;
813
+ const x = touch0.x;
814
+ const y = touch0.y;
815
+ const style = this.selStyle;
816
+ const left = parseInt(style.left);
817
+ const top = parseInt(style.top);
818
+ const width = parseInt(style.width);
819
+ const height = parseInt(style.height);
820
+
821
+ // 检查四个控制点
822
+ if (Math.abs(x - left) < controlPointSize && Math.abs(y - top) < controlPointSize) {
823
+ this.resizeHandle = 'top-left';
824
+ } else if (Math.abs(x - (left + width)) < controlPointSize && Math.abs(y - top) < controlPointSize) {
825
+ this.resizeHandle = 'top-right';
826
+ } else if (Math.abs(x - left) < controlPointSize && Math.abs(y - (top + height)) < controlPointSize) {
827
+ this.resizeHandle = 'bottom-left';
828
+ } else if (Math.abs(x - (left + width)) < controlPointSize && Math.abs(y - (top + height)) < controlPointSize) {
829
+ this.resizeHandle = 'bottom-right';
830
+ } else {
831
+ this.resizeHandle = null;
832
+ }
833
+ } else {
834
+ this.resizeHandle = null;
835
+ }
836
+ }
837
+ },
838
+ move(e) {
839
+ let touches = e.touches,
840
+ touch0 = touches[0],
841
+ touch1 = touches[1];
842
+
843
+ if (touch1) {
844
+ let x = touch1.x - touch0.x,
845
+ y = touch1.y - touch0.y,
846
+ fgDistance = Math.sqrt(x * x + y * y),
847
+ scaleSize = 0.005 * (fgDistance - this.fgDistance),
848
+ beScaleSize = this.scaleSize + scaleSize;
849
+
850
+ do {
851
+ if (!this.letScale) break;
852
+ if (beScaleSize < this.mnScale) break;
853
+ if (beScaleSize > this.mxScale) break;
854
+ if (this.isin) {
855
+ let imgWidth = this.useWidth * beScaleSize,
856
+ imgHeight = this.useHeight * beScaleSize,
857
+ rx0 = this.posWidth + this.useWidth / 2,
858
+ ry0 = this.posHeight + this.useHeight / 2,
859
+ l = rx0 - imgWidth / 2, t = ry0 - imgHeight / 2,
860
+ r = l + imgWidth, b = t + imgHeight,
861
+ left = parseInt(this.selStyle.left),
862
+ top = parseInt(this.selStyle.top),
863
+ width = parseInt(this.selStyle.width),
864
+ height = parseInt(this.selStyle.height);
865
+ if (left < l || left + width > r || top < t || top + height > b) break;
866
+ this.scaleWidth = (this.useWidth - imgWidth) / 2;
867
+ this.scaleHeight = (this.useHeight - imgHeight) / 2;
868
+ }
869
+
870
+ this.scaleSize = beScaleSize;
871
+ } while (0);
872
+ this.fgDistance = fgDistance;
873
+
874
+ if (touch1.x !== touch0.x && this.letRotate) {
875
+ x = (this.touch1.y - this.touch0.y) / (this.touch1.x - this.touch0.x);
876
+ y = (touch1.y - touch0.y) / (touch1.x - touch0.x);
877
+ this.rotateDeg += Math.atan((y - x) / (1 + x * y)) * 180 / Math.PI;
878
+ this.touch0 = touch0;
879
+ this.touch1 = touch1;
880
+ }
881
+
882
+ this.drawImage();
883
+ } else if (this.touch0) {
884
+ // 只有在允许调整大小时才处理裁剪框大小调整
885
+ if (this.resizeHandle && this.letChangeSize) {
886
+ const style = { ...this.selStyle };
887
+ const left = parseInt(style.left);
888
+ const top = parseInt(style.top);
889
+ const width = parseInt(style.width);
890
+ const height = parseInt(style.height);
891
+ const minWidth = 50;
892
+ const minHeight = 50;
893
+
894
+ switch (this.resizeHandle) {
895
+ case 'top-left':
896
+ style.left = touch0.x + 'px';
897
+ style.top = touch0.y + 'px';
898
+ style.width = (left + width - touch0.x) + 'px';
899
+ style.height = (top + height - touch0.y) + 'px';
900
+ break;
901
+ case 'top-right':
902
+ style.top = touch0.y + 'px';
903
+ style.width = (touch0.x - left) + 'px';
904
+ style.height = (top + height - touch0.y) + 'px';
905
+ break;
906
+ case 'bottom-left':
907
+ style.left = touch0.x + 'px';
908
+ style.width = (left + width - touch0.x) + 'px';
909
+ style.height = (touch0.y - top) + 'px';
910
+ break;
911
+ case 'bottom-right':
912
+ style.width = (touch0.x - left) + 'px';
913
+ style.height = (touch0.y - top) + 'px';
914
+ break;
915
+ }
916
+
917
+ // 约束裁剪框:最小尺寸、屏幕边界,inner 模式下再限制在图片内
918
+ let nl = parseInt(style.left);
919
+ let nt = parseInt(style.top);
920
+ let nw = parseInt(style.width);
921
+ let nh = parseInt(style.height);
922
+
923
+ // 屏幕边界
924
+ if (nl < 0) nl = 0;
925
+ if (nt < 0) nt = 0;
926
+ if (nl + nw > this.windowWidth) nw = this.windowWidth - nl;
927
+ if (nt + nh > this.windowHeight - tabHeight) nh = this.windowHeight - tabHeight - nt;
928
+
929
+ if (this.isin) {
930
+ const imgWidth = this.useWidth * this.scaleSize;
931
+ const imgHeight = this.useHeight * this.scaleSize;
932
+ const rx0 = this.posWidth + this.useWidth / 2;
933
+ const ry0 = this.posHeight + this.useHeight / 2;
934
+ const imgL = rx0 - imgWidth / 2;
935
+ const imgT = ry0 - imgHeight / 2;
936
+ const imgR = imgL + imgWidth;
937
+ const imgB = imgT + imgHeight;
938
+ if (nl < imgL) nl = imgL;
939
+ if (nt < imgT) nt = imgT;
940
+ if (nl + nw > imgR) nw = imgR - nl;
941
+ if (nt + nh > imgB) nh = imgB - nt;
942
+ }
943
+
944
+ if (nw >= minWidth && nh >= minHeight) {
945
+ style.left = nl + 'px';
946
+ style.top = nt + 'px';
947
+ style.width = nw + 'px';
948
+ style.height = nh + 'px';
949
+ this.selStyle = style;
950
+ // 重新绘制操作层
951
+ this.drawInit();
952
+ }
953
+ } else {
954
+ // 原有的移动图片逻辑
955
+ let x = touch0.x - this.touch0.x,
956
+ y = touch0.y - this.touch0.y,
957
+ beX = this.posWidth + x,
958
+ beY = this.posHeight + y;
959
+ if (this.isin) {
960
+ let imgWidth = this.useWidth * this.scaleSize,
961
+ imgHeight = this.useHeight * this.scaleSize,
962
+ rx0 = beX + this.useWidth / 2,
963
+ ry0 = beY + this.useHeight / 2,
964
+ l = rx0 - imgWidth / 2, t = ry0 - imgHeight / 2,
965
+ r = l + imgWidth, b = t + imgHeight,
966
+ left = parseInt(this.selStyle.left),
967
+ top = parseInt(this.selStyle.top),
968
+ width = parseInt(this.selStyle.width),
969
+ height = parseInt(this.selStyle.height);
970
+ if (!this.lckWidth && Math.abs(x) < 100) {
971
+ if (left >= l && left + width <= r) {
972
+ this.posWidth = beX;
973
+ } else if (left < l) {
974
+ this.posWidth = left - this.scaleWidth;
975
+ } else if (left + width > r) {
976
+ this.posWidth = left - (imgWidth - width) - this.scaleWidth;
977
+ }
978
+ }
979
+ if (!this.lckHeight && Math.abs(y) < 100) {
980
+ if (top >= t && top + height <= b) {
981
+ this.posHeight = beY;
982
+ } else if (top < t) {
983
+ this.posHeight = top - this.scaleHeight;
984
+ } else if (top + height > b) {
985
+ this.posHeight = top - (imgHeight - height) - this.scaleHeight;
986
+ }
987
+ }
988
+ } else {
989
+ if (Math.abs(x) < 100 && !this.lckWidth) this.posWidth = beX;
990
+ if (Math.abs(y) < 100 && !this.lckHeight) this.posHeight = beY;
991
+ }
992
+
993
+ this.touch0 = touch0;
994
+ this.drawImage();
995
+ }
996
+ }
997
+ },
998
+ end(e) {
999
+ let touches = e.touches,
1000
+ touch0 = touches && touches[0],
1001
+ touch1 = touches && touches[1];
1002
+ if (touch0) {
1003
+ this.touch0 = touch0;
1004
+ } else {
1005
+ this.touch0 = null;
1006
+ this.touch1 = null;
1007
+ this.resizeHandle = null; // 重置调整手柄
1008
+ }
1009
+ },
1010
+ async getImgData() {
1011
+ await this.initCanvasRefs();
1012
+ return new Promise((resolve, reject) => {
1013
+ let prvX = this.prvX,
1014
+ prvY = this.prvY,
1015
+ prvWidth = this.prvWidth,
1016
+ prvHeight = this.prvHeight;
1017
+ // #ifdef APP-PLUS||H5
1018
+ prvX *= this.pixelRatio;
1019
+ prvY *= this.pixelRatio;
1020
+ prvWidth *= this.pixelRatio;
1021
+ prvHeight *= this.pixelRatio;
1022
+ // #endif
1023
+ this.ctxCanvasPrv.getImageData({
1024
+ x: prvX,
1025
+ y: prvY,
1026
+ width: prvWidth,
1027
+ height: prvHeight,
1028
+ success(res) {
1029
+ resolve(res.data);
1030
+ },
1031
+ fail(err) {
1032
+ reject(err);
1033
+ }
1034
+ });
1035
+ });
1036
+ },
1037
+ async colorChange(e) {
1038
+ let tm_now = Date.now();
1039
+ if (tm_now - this.prvTm < 100) return;
1040
+ this.prvTm = tm_now;
1041
+
1042
+ uni.showLoading({ mask: true });
1043
+
1044
+ if (!this.prvImgData) {
1045
+ if (!(this.prvImgData = await this.getImgData().catch((res) => {
1046
+ uni.showToast({
1047
+ title: "error_read",
1048
+ duration: 2000,
1049
+ })
1050
+ }))) return;
1051
+ this.target = new Uint8ClampedArray(this.prvImgData.length);
1052
+ }
1053
+
1054
+ let data = this.prvImgData,
1055
+ target = this.target,
1056
+ i = e.detail.value,
1057
+ r, g, b, a, h, s, l, d, p, q, t, min, max, hK, tR, tG, tB;
1058
+
1059
+ if (i === 0) {
1060
+ target = data;
1061
+ } else {
1062
+ i = (i + 100) / 200;
1063
+ if (i < 0.005) i = 0;
1064
+ if (i > 0.995) i = 1;
1065
+ for (let n = data.length - 1; n >= 0; n -= 4) {
1066
+ r = data[n - 3] / 255;
1067
+ g = data[n - 2] / 255;
1068
+ b = data[n - 1] / 255;
1069
+ max = Math.max(r, g, b);
1070
+ min = Math.min(r, g, b);
1071
+ d = max - min;
1072
+ if (max === min) {
1073
+ h = 0;
1074
+ } else if (max === r && g >= b) {
1075
+ h = 60 * ((g - b) / d);
1076
+ } else if (max === r && g < b) {
1077
+ h = 60 * ((g - b) / d) + 360;
1078
+ } else if (max === g) {
1079
+ h = 60 * ((b - r) / d) + 120;
1080
+ } else if (max === b) {
1081
+ h = 60 * ((r - g) / d) + 240;
1082
+ }
1083
+ l = (max + min) / 2;
1084
+ if (l === 0 || max === min) {
1085
+ s = 0;
1086
+ } else if (0 < l && l <= 0.5) {
1087
+ s = d / (2 * l);
1088
+ } else if (l > 0.5) {
1089
+ s = d / (2 - 2 * l);
1090
+ }
1091
+ data[n] && (a = data[n]);
1092
+
1093
+ if (i < 0.5) {
1094
+ s = s * i / 0.5;
1095
+ } else if (i > 0.5) {
1096
+ s = 2 * s + 2 * i - (s * i / 0.5) - 1;
1097
+ }
1098
+
1099
+ if (s === 0) {
1100
+ r = g = b = Math.round(l * 255);
1101
+ } else {
1102
+ if (l < 0.5) {
1103
+ q = l * (1 + s);
1104
+ } else if (l >= 0.5) {
1105
+ q = l + s - (l * s);
1106
+ }
1107
+ p = 2 * l - q;
1108
+ hK = h / 360;
1109
+ tR = hK + 1 / 3;
1110
+ tG = hK;
1111
+ tB = hK - 1 / 3;
1112
+ let correctRGB = (t) => {
1113
+ if (t < 0) {
1114
+ return t + 1.0;
1115
+ }
1116
+ if (t > 1) {
1117
+ return t - 1.0;
1118
+ }
1119
+ return t;
1120
+ };
1121
+ let createRGB = (t) => {
1122
+ if (t < (1 / 6)) {
1123
+ return p + ((q - p) * 6 * t);
1124
+ } else if (t >= (1 / 6) && t < (1 / 2)) {
1125
+ return q;
1126
+ } else if (t >= (1 / 2) && t < (2 / 3)) {
1127
+ return p + ((q - p) * 6 * ((2 / 3) - t));
1128
+ }
1129
+ return p;
1130
+ };
1131
+ r = tR = Math.round(createRGB(correctRGB(tR)) * 255);
1132
+ g = tG = Math.round(createRGB(correctRGB(tG)) * 255);
1133
+ b = tB = Math.round(createRGB(correctRGB(tB)) * 255);
1134
+ }
1135
+ a && (target[n] = a);
1136
+ target[n - 3] = r;
1137
+ target[n - 2] = g;
1138
+ target[n - 1] = b;
1139
+ }
1140
+ }
1141
+ let prvX = this.prvX,
1142
+ prvY = this.prvY,
1143
+ prvWidth = this.prvWidth,
1144
+ prvHeight = this.prvHeight;
1145
+
1146
+ if (this.fillColor && this.fillColor !== 'transparent') {
1147
+ this.ctxCanvasPrv.setFillStyle(this.fillColor);
1148
+ this.ctxCanvasPrv.fillRect(prvX, prvY, prvWidth, prvHeight);
1149
+ }
1150
+ this.ctxCanvasPrv.draw(true);
1151
+
1152
+ // #ifdef APP-PLUS||H5
1153
+ prvX *= this.pixelRatio;
1154
+ prvY *= this.pixelRatio;
1155
+ prvWidth *= this.pixelRatio;
1156
+ prvHeight *= this.pixelRatio;
1157
+ // #endif
1158
+ this.ctxCanvasPrv.putImageData({
1159
+ x: prvX,
1160
+ y: prvY,
1161
+ width: prvWidth,
1162
+ height: prvHeight,
1163
+ data: target,
1164
+ fail() {
1165
+ uni.showToast({
1166
+ title: 'error_put',
1167
+ duration: 2000
1168
+ })
1169
+ },
1170
+ complete() {
1171
+ uni.hideLoading();
1172
+ }
1173
+ });
1174
+ },
1175
+ btop(base64) {
1176
+ return new Promise(function (resolve, reject) {
1177
+ var arr = base64.split(','),
1178
+ mime = arr[0].match(/:(.*?);/)[1],
1179
+ bstr = atob(arr[1]),
1180
+ n = bstr.length,
1181
+ u8arr = new Uint8Array(n);
1182
+ while (n--) {
1183
+ u8arr[n] = bstr.charCodeAt(n);
1184
+ }
1185
+ return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([u8arr], { type: mime })));
1186
+ });
1187
+ },
1188
+ }
1189
+ }
1190
+ </script>
1191
+
1192
+ <style lang="scss" scoped>
1193
+ .dd-cropper {
1194
+ .my-canvas {
1195
+ display: flex;
1196
+ position: fixed !important;
1197
+ background: #000000;
1198
+ left: 0;
1199
+ z-index: 100000;
1200
+ width: 100%;
1201
+ }
1202
+
1203
+ .my-avatar {
1204
+ width: 150rpx;
1205
+ height: 150rpx;
1206
+ border-radius: 100%;
1207
+ }
1208
+
1209
+ .oper-canvas {
1210
+ display: flex;
1211
+ position: fixed !important;
1212
+ left: 0;
1213
+ z-index: 100001;
1214
+ width: 100%;
1215
+ }
1216
+
1217
+ .prv-canvas {
1218
+ display: flex;
1219
+ position: fixed !important;
1220
+ background: #000000;
1221
+ left: 0;
1222
+ z-index: 200000;
1223
+ width: 100%;
1224
+ }
1225
+
1226
+ .oper-wrapper {
1227
+ height: 50px;
1228
+ position: fixed !important;
1229
+ box-sizing: border-box;
1230
+ border: 1px solid #F1F1F1;
1231
+ background: #ffffff;
1232
+ width: 100%;
1233
+ left: 0;
1234
+ bottom: 0;
1235
+ z-index: 100009;
1236
+ flex-direction: row;
1237
+ }
1238
+
1239
+ .oper {
1240
+ display: flex;
1241
+ flex-direction: column;
1242
+ justify-content: center;
1243
+ padding: 10rpx 20rpx;
1244
+ width: 100%;
1245
+ height: 100%;
1246
+ box-sizing: border-box;
1247
+ align-self: center;
1248
+ }
1249
+
1250
+ .btn-wrapper {
1251
+ display: flex;
1252
+ flex-direction: row;
1253
+ /* #ifndef H5 */
1254
+ flex-grow: 1;
1255
+ /* #endif */
1256
+ /* #ifdef H5 */
1257
+ height: 50px;
1258
+ /* #endif */
1259
+ justify-content: space-between;
1260
+ }
1261
+
1262
+ .btn-wrapper view {
1263
+ display: flex;
1264
+ align-items: center;
1265
+ justify-content: center;
1266
+ font-size: 16px;
1267
+ color: #333;
1268
+ border: 1px solid #f1f1f1;
1269
+ border-radius: 6%;
1270
+ }
1271
+
1272
+ .hover {
1273
+ background: #f1f1f1;
1274
+ border-radius: 6%;
1275
+ }
1276
+
1277
+ .clr-wrapper {
1278
+ display: flex;
1279
+ flex-direction: row;
1280
+ flex-grow: 1;
1281
+ }
1282
+
1283
+ .clr-wrapper view {
1284
+ display: flex;
1285
+ align-items: center;
1286
+ justify-content: center;
1287
+ font-size: 16px;
1288
+ color: #333;
1289
+ border: 1px solid #f1f1f1;
1290
+ border-radius: 6%;
1291
+ }
1292
+
1293
+ .my-slider {
1294
+ flex-grow: 1;
1295
+ }
1296
+ }
1297
+ </style>