@douyinfe/semi-foundation 2.72.2 → 2.73.0-beta.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 (60) hide show
  1. package/audioPlayer/audioPlayer.scss +217 -0
  2. package/audioPlayer/constants.ts +7 -0
  3. package/audioPlayer/foundation.ts +103 -0
  4. package/audioPlayer/variables.scss +55 -0
  5. package/button/iconButton.scss +8 -0
  6. package/cropper/constants.ts +26 -0
  7. package/cropper/cropper.scss +116 -0
  8. package/cropper/foundation.ts +821 -0
  9. package/cropper/utils.ts +12 -0
  10. package/cropper/variables.scss +6 -0
  11. package/dragMove/foundation.ts +12 -0
  12. package/jsonViewer/foundation.ts +6 -0
  13. package/jsonViewer/jsonViewer.scss +8 -3
  14. package/lib/cjs/audioPlayer/audioPlayer.css +188 -0
  15. package/lib/cjs/audioPlayer/audioPlayer.scss +217 -0
  16. package/lib/cjs/audioPlayer/constants.d.ts +4 -0
  17. package/lib/cjs/audioPlayer/constants.js +10 -0
  18. package/lib/cjs/audioPlayer/foundation.d.ts +41 -0
  19. package/lib/cjs/audioPlayer/foundation.js +79 -0
  20. package/lib/cjs/audioPlayer/variables.scss +55 -0
  21. package/lib/cjs/button/iconButton.css +8 -0
  22. package/lib/cjs/button/iconButton.scss +8 -0
  23. package/lib/cjs/cropper/constants.d.ts +17 -0
  24. package/lib/cjs/cropper/constants.js +24 -0
  25. package/lib/cjs/cropper/cropper.css +97 -0
  26. package/lib/cjs/cropper/cropper.scss +116 -0
  27. package/lib/cjs/cropper/foundation.d.ts +101 -0
  28. package/lib/cjs/cropper/foundation.js +786 -0
  29. package/lib/cjs/cropper/utils.d.ts +2 -0
  30. package/lib/cjs/cropper/utils.js +19 -0
  31. package/lib/cjs/cropper/variables.scss +6 -0
  32. package/lib/cjs/dragMove/foundation.d.ts +2 -0
  33. package/lib/cjs/dragMove/foundation.js +10 -0
  34. package/lib/cjs/jsonViewer/foundation.js +6 -0
  35. package/lib/cjs/jsonViewer/jsonViewer.css +8 -2
  36. package/lib/cjs/jsonViewer/jsonViewer.scss +8 -3
  37. package/lib/es/audioPlayer/audioPlayer.css +188 -0
  38. package/lib/es/audioPlayer/audioPlayer.scss +217 -0
  39. package/lib/es/audioPlayer/constants.d.ts +4 -0
  40. package/lib/es/audioPlayer/constants.js +5 -0
  41. package/lib/es/audioPlayer/foundation.d.ts +41 -0
  42. package/lib/es/audioPlayer/foundation.js +72 -0
  43. package/lib/es/audioPlayer/variables.scss +55 -0
  44. package/lib/es/button/iconButton.css +8 -0
  45. package/lib/es/button/iconButton.scss +8 -0
  46. package/lib/es/cropper/constants.d.ts +17 -0
  47. package/lib/es/cropper/constants.js +19 -0
  48. package/lib/es/cropper/cropper.css +97 -0
  49. package/lib/es/cropper/cropper.scss +116 -0
  50. package/lib/es/cropper/foundation.d.ts +101 -0
  51. package/lib/es/cropper/foundation.js +778 -0
  52. package/lib/es/cropper/utils.d.ts +2 -0
  53. package/lib/es/cropper/utils.js +12 -0
  54. package/lib/es/cropper/variables.scss +6 -0
  55. package/lib/es/dragMove/foundation.d.ts +2 -0
  56. package/lib/es/dragMove/foundation.js +10 -0
  57. package/lib/es/jsonViewer/foundation.js +6 -0
  58. package/lib/es/jsonViewer/jsonViewer.css +8 -2
  59. package/lib/es/jsonViewer/jsonViewer.scss +8 -3
  60. package/package.json +4 -4
@@ -0,0 +1,786 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _foundation = _interopRequireDefault(require("../base/foundation"));
8
+ var _utils = require("./utils");
9
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
+ class CropperFoundation extends _foundation.default {
11
+ constructor(adapter) {
12
+ super(Object.assign({}, adapter));
13
+ this.getImgDataWhenResize = ratio => {
14
+ const {
15
+ imgData
16
+ } = this.getStates();
17
+ const newImgData = {
18
+ width: imgData.width * ratio,
19
+ height: imgData.height * ratio,
20
+ centerPoint: {
21
+ x: imgData.centerPoint.x * ratio,
22
+ y: imgData.centerPoint.y * ratio
23
+ }
24
+ };
25
+ this.imgData.scale *= ratio;
26
+ return newImgData;
27
+ };
28
+ this.getCropperBoxWhenResize = (ratio, newContainerData) => {
29
+ const {
30
+ cropperBox
31
+ } = this.getStates();
32
+ const {
33
+ aspectRatio
34
+ } = this.getProps();
35
+ const tempCropperBox = {
36
+ width: cropperBox.width * ratio,
37
+ height: cropperBox.height * ratio,
38
+ centerPoint: {
39
+ x: cropperBox.centerPoint.x * ratio,
40
+ y: cropperBox.centerPoint.y * ratio
41
+ }
42
+ };
43
+ let xMin = tempCropperBox.centerPoint.x - tempCropperBox.width / 2;
44
+ let xMax = tempCropperBox.centerPoint.x + tempCropperBox.width / 2;
45
+ let yMin = tempCropperBox.centerPoint.y - tempCropperBox.height / 2;
46
+ let yMax = tempCropperBox.centerPoint.y + tempCropperBox.height / 2;
47
+ if (aspectRatio) {
48
+ if (xMax > newContainerData.width) {
49
+ xMax = newContainerData.width;
50
+ xMin = tempCropperBox.width > newContainerData.width ? 0 : newContainerData.width - tempCropperBox.width;
51
+ tempCropperBox.width = xMax - xMin;
52
+ tempCropperBox.height = tempCropperBox.width / aspectRatio;
53
+ yMax = yMin + tempCropperBox.height;
54
+ }
55
+ if (yMax > newContainerData.height) {
56
+ yMax = newContainerData.height;
57
+ yMin = tempCropperBox.height > newContainerData.height ? 0 : newContainerData.height - tempCropperBox.height;
58
+ tempCropperBox.height = yMax - yMin;
59
+ tempCropperBox.width = tempCropperBox.height * aspectRatio;
60
+ xMax = xMin + tempCropperBox.width;
61
+ }
62
+ } else {
63
+ if (xMax > newContainerData.width) {
64
+ xMax = newContainerData.width;
65
+ xMin = tempCropperBox.width > newContainerData.width ? 0 : newContainerData.width - tempCropperBox.width;
66
+ }
67
+ if (yMax > newContainerData.height) {
68
+ yMax = newContainerData.height;
69
+ yMin = tempCropperBox.height > newContainerData.height ? 0 : newContainerData.height - tempCropperBox.height;
70
+ }
71
+ }
72
+ return {
73
+ width: xMax - xMin,
74
+ height: yMax - yMin,
75
+ centerPoint: {
76
+ x: (xMax + xMin) / 2,
77
+ y: (yMax + yMin) / 2
78
+ }
79
+ };
80
+ };
81
+ this.handleResize = () => {
82
+ const {
83
+ loaded
84
+ } = this.getStates();
85
+ if (!this.initial) {
86
+ this.initial = true;
87
+ return;
88
+ }
89
+ if (!loaded) {
90
+ return;
91
+ }
92
+ const container = this._adapter.getContainer();
93
+ const newContainerData = {
94
+ width: container.clientWidth,
95
+ height: container.clientHeight
96
+ };
97
+ const ratio = newContainerData.width / this.containerData.width;
98
+ const newImgData = this.getImgDataWhenResize(ratio);
99
+ const newCropperBox = this.getCropperBoxWhenResize(ratio, newContainerData);
100
+ this.containerData = newContainerData;
101
+ this.setState({
102
+ imgData: newImgData,
103
+ cropperBox: newCropperBox
104
+ });
105
+ };
106
+ this.handleImageLoad = e => {
107
+ /**
108
+ * 1. 图片加载完成后,获得图片的原始大小
109
+ * 2. 计算图片的缩放比例,中心点位置
110
+ */
111
+ const {
112
+ naturalWidth,
113
+ naturalHeight
114
+ } = e.target;
115
+ const {
116
+ width: containerWidth,
117
+ height: containerHeight
118
+ } = this.containerData;
119
+ this.imgData.originalWidth = naturalWidth;
120
+ this.imgData.originalHeight = naturalHeight;
121
+ let scale = 1;
122
+ const newImgDataState = {};
123
+ /* 计算图片加载后的初始显示尺寸 */
124
+ if (naturalWidth / containerWidth > naturalHeight / containerHeight) {
125
+ scale = containerWidth / naturalWidth;
126
+ newImgDataState.width = containerWidth;
127
+ newImgDataState.height = naturalHeight * scale;
128
+ } else {
129
+ scale = containerHeight / naturalHeight;
130
+ newImgDataState.width = naturalWidth * scale;
131
+ newImgDataState.height = containerHeight;
132
+ }
133
+ this.imgData.scale = scale;
134
+ newImgDataState.centerPoint = {};
135
+ newImgDataState.centerPoint.x = containerWidth / 2;
136
+ newImgDataState.centerPoint.y = containerHeight / 2;
137
+ /* 计算裁切框大小 */
138
+ const newCropperBoxState = {};
139
+ const {
140
+ defaultAspectRatio,
141
+ aspectRatio
142
+ } = this.getProps();
143
+ const calcAspect = aspectRatio || defaultAspectRatio;
144
+ if (containerWidth / containerHeight > calcAspect) {
145
+ newCropperBoxState.width = containerHeight * calcAspect;
146
+ newCropperBoxState.height = containerHeight;
147
+ } else {
148
+ newCropperBoxState.width = containerWidth;
149
+ newCropperBoxState.height = containerWidth / calcAspect;
150
+ }
151
+ newCropperBoxState.centerPoint = {};
152
+ newCropperBoxState.centerPoint.x = containerWidth / 2;
153
+ newCropperBoxState.centerPoint.y = containerHeight / 2;
154
+ this.setState({
155
+ imgData: newImgDataState,
156
+ cropperBox: newCropperBoxState,
157
+ loaded: true
158
+ });
159
+ };
160
+ this.handleWheel = e => {
161
+ // 防止双手缩放导致页面被放大
162
+ e.preventDefault();
163
+ const {
164
+ imgData,
165
+ zoom: currZoom
166
+ } = this.getStates();
167
+ const {
168
+ maxZoom,
169
+ minZoom,
170
+ zoomStep
171
+ } = this.getProps();
172
+ let _zoom;
173
+ if (e.deltaY < 0) {
174
+ /* zoom in */
175
+ if (currZoom + zoomStep <= maxZoom) {
176
+ _zoom = Number((currZoom + zoomStep).toFixed(2));
177
+ }
178
+ } else if (e.deltaY > 0) {
179
+ /* zoom out */
180
+ if (currZoom - zoomStep >= minZoom) {
181
+ _zoom = Number((currZoom - zoomStep).toFixed(2));
182
+ }
183
+ }
184
+ if (_zoom === undefined) {
185
+ return;
186
+ }
187
+ const boundingRect = e.currentTarget.getBoundingClientRect();
188
+ const offsetX = e.clientX - boundingRect.left;
189
+ const offsetY = e.clientY - boundingRect.top;
190
+ const scaleCenter = {
191
+ x: offsetX,
192
+ y: -offsetY
193
+ };
194
+ // 计算新的中心点位置
195
+ const currentPoint = Object.assign({}, imgData.centerPoint);
196
+ currentPoint.y = -currentPoint.y;
197
+ const newCenterPoint = {
198
+ x: (currentPoint.x - scaleCenter.x) / currZoom * _zoom + scaleCenter.x,
199
+ y: -[(currentPoint.y - scaleCenter.y) / currZoom * _zoom + scaleCenter.y]
200
+ };
201
+ const newWidth = imgData.width / currZoom * _zoom;
202
+ const newHeight = imgData.height / currZoom * _zoom;
203
+ const newImgDataState = {
204
+ width: newWidth,
205
+ height: newHeight,
206
+ centerPoint: newCenterPoint
207
+ };
208
+ this.setState({
209
+ imgData: newImgDataState,
210
+ zoom: _zoom
211
+ });
212
+ this._adapter.notifyZoomChange(_zoom);
213
+ };
214
+ this.getRangeForAspectChange = () => {
215
+ const {
216
+ cropperBox
217
+ } = this.getStates();
218
+ const {
219
+ aspectRatio
220
+ } = this.getProps();
221
+ const {
222
+ width: containerWidth,
223
+ height: containerHeight
224
+ } = this.containerData;
225
+ // 可能的最大宽高
226
+ let height, width;
227
+ // 裁剪框当前的位置
228
+ const xMin = cropperBox.centerPoint.x - cropperBox.width / 2;
229
+ const xMax = cropperBox.centerPoint.x + cropperBox.width / 2;
230
+ const yMin = cropperBox.centerPoint.y - cropperBox.height / 2;
231
+ const yMax = cropperBox.centerPoint.y + cropperBox.height / 2;
232
+ switch (this.boxMoveDir) {
233
+ case 'tl':
234
+ height = yMax;
235
+ width = xMax;
236
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
237
+ this.rangeX = [xMax - width, xMax];
238
+ this.rangeY = [yMax - height, yMax];
239
+ break;
240
+ case 'tm':
241
+ height = yMax;
242
+ const leftHalfWidth = cropperBox.centerPoint.x;
243
+ const rightHalfWidth = containerWidth - cropperBox.centerPoint.x;
244
+ width = 2 * (leftHalfWidth < rightHalfWidth ? leftHalfWidth : rightHalfWidth);
245
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
246
+ this.rangeX = [cropperBox.centerPoint.x - width / 2, cropperBox.centerPoint.x + width / 2];
247
+ this.rangeY = [yMax - height, yMax];
248
+ break;
249
+ case 'tr':
250
+ height = yMax;
251
+ width = containerWidth - xMin;
252
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
253
+ this.rangeX = [xMin, xMin + width];
254
+ this.rangeY = [yMax - height, yMax];
255
+ break;
256
+ case 'ml':
257
+ width = xMax;
258
+ const topHalfHeight = cropperBox.centerPoint.y;
259
+ const bottomHalfHeight = containerHeight - cropperBox.centerPoint.y;
260
+ height = 2 * (topHalfHeight < bottomHalfHeight ? topHalfHeight : bottomHalfHeight);
261
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
262
+ this.rangeX = [xMax - width, xMax];
263
+ this.rangeY = [cropperBox.centerPoint.y - height / 2, cropperBox.centerPoint.y + height / 2];
264
+ break;
265
+ case 'mr':
266
+ width = containerWidth - xMin;
267
+ const topHalfHeight2 = cropperBox.centerPoint.y;
268
+ const bottomHalfHeight2 = containerHeight - cropperBox.centerPoint.y;
269
+ height = 2 * (topHalfHeight2 < bottomHalfHeight2 ? topHalfHeight2 : bottomHalfHeight2);
270
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
271
+ this.rangeX = [xMin, xMin + width];
272
+ this.rangeY = [cropperBox.centerPoint.y - height / 2, cropperBox.centerPoint.y + height / 2];
273
+ break;
274
+ case 'bl':
275
+ height = containerHeight - yMin;
276
+ width = xMax;
277
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
278
+ this.rangeX = [xMax - width, xMax];
279
+ this.rangeY = [yMin, yMin + height];
280
+ break;
281
+ case 'bm':
282
+ height = containerHeight - yMin;
283
+ const leftHalfWidth2 = cropperBox.centerPoint.x;
284
+ const rightHalfWidth2 = containerWidth - cropperBox.centerPoint.x;
285
+ width = 2 * (leftHalfWidth2 < rightHalfWidth2 ? leftHalfWidth2 : rightHalfWidth2);
286
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
287
+ this.rangeX = [cropperBox.centerPoint.x - width / 2, cropperBox.centerPoint.x + width / 2];
288
+ this.rangeY = [yMin, yMin + height];
289
+ break;
290
+ case 'br':
291
+ height = containerHeight - yMin;
292
+ width = containerWidth - xMin;
293
+ [width, height] = (0, _utils.getAspectHW)(width, height, aspectRatio);
294
+ this.rangeX = [xMin, xMin + width];
295
+ this.rangeY = [yMin, yMin + height];
296
+ break;
297
+ default:
298
+ break;
299
+ }
300
+ };
301
+ this.handleCornerMouseDown = e => {
302
+ const currentTarget = e.currentTarget;
303
+ if (!currentTarget) {
304
+ return;
305
+ }
306
+ e.preventDefault();
307
+ const dir = currentTarget.dataset.dir;
308
+ this.boxMoveDir = dir;
309
+ this.boxMoveParam = this.getMoveParamByDir(dir);
310
+ this.bindResizeEvent();
311
+ const {
312
+ aspectRatio
313
+ } = this.getProps();
314
+ if (aspectRatio) {
315
+ this.getRangeForAspectChange();
316
+ } else {
317
+ this.rangeX = [0, this.containerData.width];
318
+ this.rangeY = [0, this.containerData.height];
319
+ }
320
+ };
321
+ this.bindResizeEvent = () => {
322
+ const {
323
+ aspectRatio
324
+ } = this.getProps();
325
+ document.addEventListener('mousemove', aspectRatio ? this.handleCornerAspectMouseMove : this.handleCornerMouseMove);
326
+ document.addEventListener('mouseup', this.handleCornerMouseUp);
327
+ };
328
+ this.unBindResizeEvent = () => {
329
+ const {
330
+ aspectRatio
331
+ } = this.getProps();
332
+ document.removeEventListener('mousemove', aspectRatio ? this.handleCornerAspectMouseMove : this.handleCornerMouseMove);
333
+ document.removeEventListener('mouseup', this.handleCornerMouseUp);
334
+ };
335
+ this.viewIMGDragStart = e => {
336
+ e.preventDefault();
337
+ };
338
+ this.handleCornerAspectMouseMove = e => {
339
+ e.preventDefault();
340
+ const {
341
+ clientX,
342
+ clientY
343
+ } = e;
344
+ const {
345
+ cropperBox
346
+ } = this.getStates();
347
+ const {
348
+ aspectRatio
349
+ } = this.getProps();
350
+ const boundingRect = this._adapter.getContainer().getBoundingClientRect();
351
+ const newCropperBoxPos = {
352
+ width: cropperBox.width,
353
+ height: cropperBox.height,
354
+ centerPoint: Object.assign({}, cropperBox.centerPoint)
355
+ };
356
+ let offsetX, offsetY;
357
+ if (['ml', 'mr'].includes(this.boxMoveDir)) {
358
+ offsetX = (0, _utils.getMiddle)(clientX - boundingRect.left, this.rangeX);
359
+ } else {
360
+ offsetY = (0, _utils.getMiddle)(clientY - boundingRect.top, this.rangeY);
361
+ }
362
+ switch (this.boxMoveDir) {
363
+ case 'tl':
364
+ newCropperBoxPos.height = this.rangeY[1] - offsetY;
365
+ newCropperBoxPos.width = newCropperBoxPos.height * aspectRatio;
366
+ newCropperBoxPos.centerPoint = {
367
+ x: this.rangeX[1] - newCropperBoxPos.width / 2,
368
+ y: this.rangeY[1] - newCropperBoxPos.height / 2
369
+ };
370
+ break;
371
+ case 'tm':
372
+ newCropperBoxPos.height = this.rangeY[1] - offsetY;
373
+ newCropperBoxPos.width = newCropperBoxPos.height * aspectRatio;
374
+ newCropperBoxPos.centerPoint = {
375
+ x: cropperBox.centerPoint.x,
376
+ y: this.rangeY[1] - newCropperBoxPos.height / 2
377
+ };
378
+ break;
379
+ case 'tr':
380
+ newCropperBoxPos.height = this.rangeY[1] - offsetY;
381
+ newCropperBoxPos.width = newCropperBoxPos.height * aspectRatio;
382
+ newCropperBoxPos.centerPoint = {
383
+ x: this.rangeX[0] + newCropperBoxPos.width / 2,
384
+ y: this.rangeY[1] - newCropperBoxPos.height / 2
385
+ };
386
+ break;
387
+ case 'ml':
388
+ newCropperBoxPos.width = this.rangeX[1] - offsetX;
389
+ newCropperBoxPos.height = newCropperBoxPos.width / aspectRatio;
390
+ newCropperBoxPos.centerPoint = {
391
+ x: this.rangeX[1] - newCropperBoxPos.width / 2,
392
+ y: cropperBox.centerPoint.y
393
+ };
394
+ break;
395
+ case 'mr':
396
+ newCropperBoxPos.width = offsetX - this.rangeX[0];
397
+ newCropperBoxPos.height = newCropperBoxPos.width / aspectRatio;
398
+ newCropperBoxPos.centerPoint = {
399
+ x: this.rangeX[0] + newCropperBoxPos.width / 2,
400
+ y: cropperBox.centerPoint.y
401
+ };
402
+ break;
403
+ case 'bl':
404
+ newCropperBoxPos.height = offsetY - this.rangeY[0];
405
+ newCropperBoxPos.width = newCropperBoxPos.height * aspectRatio;
406
+ newCropperBoxPos.centerPoint = {
407
+ x: this.rangeX[1] - newCropperBoxPos.width / 2,
408
+ y: this.rangeY[0] + newCropperBoxPos.height / 2
409
+ };
410
+ break;
411
+ case 'bm':
412
+ newCropperBoxPos.height = offsetY - this.rangeY[0];
413
+ newCropperBoxPos.width = newCropperBoxPos.height * aspectRatio;
414
+ newCropperBoxPos.centerPoint = {
415
+ x: cropperBox.centerPoint.x,
416
+ y: this.rangeY[0] + newCropperBoxPos.height / 2
417
+ };
418
+ break;
419
+ case 'br':
420
+ newCropperBoxPos.height = offsetY - this.rangeY[0];
421
+ newCropperBoxPos.width = newCropperBoxPos.height * aspectRatio;
422
+ newCropperBoxPos.centerPoint = {
423
+ x: this.rangeX[0] + newCropperBoxPos.width / 2,
424
+ y: this.rangeY[0] + newCropperBoxPos.height / 2
425
+ };
426
+ break;
427
+ default:
428
+ break;
429
+ }
430
+ if (newCropperBoxPos.height === 0 && newCropperBoxPos.width === 0) {
431
+ this.changeDir();
432
+ this.getRangeForAspectChange();
433
+ }
434
+ this.setState({
435
+ cropperBox: newCropperBoxPos
436
+ });
437
+ };
438
+ this.changeDir = () => {
439
+ if (this.boxMoveDir.includes('t')) {
440
+ this.boxMoveDir = this.boxMoveDir.replace('t', 'b');
441
+ } else if (this.boxMoveDir.includes('b')) {
442
+ this.boxMoveDir = this.boxMoveDir.replace('b', 't');
443
+ }
444
+ if (this.boxMoveDir.includes('l')) {
445
+ this.boxMoveDir = this.boxMoveDir.replace('l', 'r');
446
+ } else if (this.boxMoveDir.includes('r')) {
447
+ this.boxMoveDir = this.boxMoveDir.replace('r', 'l');
448
+ }
449
+ };
450
+ this.handleCornerMouseMove = e => {
451
+ e.preventDefault();
452
+ const {
453
+ clientX,
454
+ clientY
455
+ } = e;
456
+ const {
457
+ cropperBox
458
+ } = this.getStates();
459
+ const boundingRect = this._adapter.getContainer().getBoundingClientRect();
460
+ let offsetX = (0, _utils.getMiddle)(clientX - boundingRect.left, this.rangeX);
461
+ let offsetY = (0, _utils.getMiddle)(clientY - boundingRect.top, this.rangeY);
462
+ const newCropperBoxPos = {
463
+ width: cropperBox.width,
464
+ height: cropperBox.height,
465
+ centerPoint: {
466
+ x: cropperBox.centerPoint.x,
467
+ y: cropperBox.centerPoint.y
468
+ }
469
+ };
470
+ const {
471
+ paramX,
472
+ paramY
473
+ } = this.boxMoveParam;
474
+ let x, y;
475
+ if (paramX) {
476
+ x = cropperBox.centerPoint.x + paramX * cropperBox.width / 2;
477
+ newCropperBoxPos.width = cropperBox.width + paramX * (offsetX - x);
478
+ if (newCropperBoxPos.width < 0) {
479
+ newCropperBoxPos.width = -newCropperBoxPos.width;
480
+ this.boxMoveParam.paramX = -paramX;
481
+ }
482
+ newCropperBoxPos.centerPoint.x = offsetX - paramX * newCropperBoxPos.width / 2;
483
+ }
484
+ if (paramY) {
485
+ y = cropperBox.centerPoint.y + paramY * cropperBox.height / 2;
486
+ newCropperBoxPos.height = cropperBox.height + paramY * (offsetY - y);
487
+ if (newCropperBoxPos.height < 0) {
488
+ newCropperBoxPos.height = -newCropperBoxPos.height;
489
+ this.boxMoveParam.paramY = -paramY;
490
+ }
491
+ newCropperBoxPos.centerPoint.y = offsetY - paramY * newCropperBoxPos.height / 2;
492
+ }
493
+ this.setState({
494
+ cropperBox: newCropperBoxPos
495
+ });
496
+ };
497
+ this.handleCornerMouseUp = e => {
498
+ this.boxMoveParam = {
499
+ paramX: 0,
500
+ paramY: 0
501
+ };
502
+ this.unBindResizeEvent();
503
+ };
504
+ this.handleCropperBoxMouseDown = e => {
505
+ const target = e.target;
506
+ const {
507
+ cropperBox
508
+ } = this.getStates();
509
+ const container = this._adapter.getContainer();
510
+ const boundingRect = container.getBoundingClientRect();
511
+ if (target.dataset.dir) {
512
+ // 如果鼠标是落在了corner上,那么不做任何操作
513
+ return;
514
+ }
515
+ // 移动裁切框
516
+ this.cropperBoxMoveStart = {
517
+ x: e.clientX,
518
+ y: e.clientY
519
+ };
520
+ this.bindMoveEvent();
521
+ // 计算 cropperBox 中心点移动范围
522
+ this.moveRange = {
523
+ xMin: cropperBox.width / 2,
524
+ xMax: boundingRect.width - cropperBox.width / 2,
525
+ yMin: cropperBox.height / 2,
526
+ yMax: boundingRect.height - cropperBox.height / 2
527
+ };
528
+ };
529
+ this.bindMoveEvent = () => {
530
+ document.addEventListener('mousemove', this.handleCropperBoxMouseMove);
531
+ document.addEventListener('mouseup', this.handleCropperBoxMouseUp);
532
+ };
533
+ this.unBindMoveEvent = () => {
534
+ document.removeEventListener('mousemove', this.handleCropperBoxMouseMove);
535
+ document.removeEventListener('mouseup', this.handleCropperBoxMouseUp);
536
+ };
537
+ this.handleCropperBoxMouseMove = e => {
538
+ if (!this.cropperBoxMoveStart) {
539
+ return;
540
+ }
541
+ const {
542
+ clientX,
543
+ clientY
544
+ } = e;
545
+ const {
546
+ cropperBox
547
+ } = this.getStates();
548
+ const offsetX = clientX - this.cropperBoxMoveStart.x;
549
+ const offsetY = clientY - this.cropperBoxMoveStart.y;
550
+ const newCenterPointX = (0, _utils.getMiddle)(cropperBox.centerPoint.x + offsetX, [this.moveRange.xMin, this.moveRange.xMax]);
551
+ const newCenterPointY = (0, _utils.getMiddle)(cropperBox.centerPoint.y + offsetY, [this.moveRange.yMin, this.moveRange.yMax]);
552
+ const newCropperBoxPos = {
553
+ width: cropperBox.width,
554
+ height: cropperBox.height,
555
+ centerPoint: {
556
+ x: newCenterPointX,
557
+ y: newCenterPointY
558
+ }
559
+ };
560
+ this.cropperBoxMoveStart = {
561
+ x: clientX,
562
+ y: clientY
563
+ };
564
+ this.setState({
565
+ cropperBox: newCropperBoxPos
566
+ });
567
+ };
568
+ this.handleCropperBoxMouseUp = e => {
569
+ if (!this.cropperBoxMoveStart) {
570
+ return;
571
+ }
572
+ this.cropperBoxMoveStart = null;
573
+ this.unBindMoveEvent();
574
+ };
575
+ this.handleMaskMouseDown = e => {
576
+ if (e.currentTarget !== e.target) {
577
+ return;
578
+ }
579
+ this.bindImgMoveEvent();
580
+ // 记录开始移动的位置
581
+ this.imgMoveStart = {
582
+ x: e.clientX,
583
+ y: e.clientY
584
+ };
585
+ };
586
+ this.bindImgMoveEvent = () => {
587
+ document.addEventListener('mousemove', this.handleImgMove);
588
+ document.addEventListener('mouseup', this.handleImgMoveUp);
589
+ };
590
+ this.unBindImgMoveEvent = () => {
591
+ document.removeEventListener('mousemove', this.handleImgMove);
592
+ document.removeEventListener('mouseup', this.handleImgMoveUp);
593
+ };
594
+ this.handleImgMove = e => {
595
+ if (!this.imgMoveStart) {
596
+ return;
597
+ }
598
+ const {
599
+ clientX,
600
+ clientY
601
+ } = e;
602
+ const {
603
+ imgData
604
+ } = this.getStates();
605
+ const offsetX = clientX - this.imgMoveStart.x;
606
+ const offsetY = clientY - this.imgMoveStart.y;
607
+ const newCenterPointX = imgData.centerPoint.x + offsetX;
608
+ const newCenterPointY = imgData.centerPoint.y + offsetY;
609
+ const newImgData = {
610
+ width: imgData.width,
611
+ height: imgData.height,
612
+ centerPoint: {
613
+ x: newCenterPointX,
614
+ y: newCenterPointY
615
+ }
616
+ };
617
+ this.imgMoveStart = {
618
+ x: clientX,
619
+ y: clientY
620
+ };
621
+ this.setState({
622
+ imgData: newImgData
623
+ });
624
+ };
625
+ this.handleImgMoveUp = e => {
626
+ if (!this.imgMoveStart) {
627
+ return;
628
+ }
629
+ this.imgMoveStart = null;
630
+ this.unBindImgMoveEvent();
631
+ };
632
+ this.getCropperCanvas = () => {
633
+ const {
634
+ cropperBox,
635
+ imgData,
636
+ rotate,
637
+ zoom
638
+ } = this.getStates();
639
+ const {
640
+ fill
641
+ } = this.getProps();
642
+ const canvas = document.createElement('canvas');
643
+ const ctx = canvas.getContext('2d');
644
+ const img = this._adapter.getImg();
645
+ // 计算包含旋转后的图片的矩形容器的宽高
646
+ const angle = rotate * Math.PI / 180;
647
+ const sine = Math.abs(Math.sin(angle));
648
+ const cosine = Math.abs(Math.cos(angle));
649
+ const imgWidth = this.imgData.originalWidth;
650
+ const imgHeight = this.imgData.originalHeight;
651
+ const containerWidth = imgWidth * cosine + imgHeight * sine;
652
+ const containerHeight = imgHeight * cosine + imgWidth * sine;
653
+ // 判断裁切区域和外接矩形是否存在交集,如果不存在,则直接返回空白图片
654
+ // 计算需要裁剪的区域实际大小和位置
655
+ const cropperContainerWidth = containerWidth * zoom * this.imgData.scale;
656
+ const cropperContainerHeight = containerHeight * zoom * this.imgData.scale;
657
+ const cropperContainerTop = imgData.centerPoint.y - cropperContainerHeight / 2;
658
+ const cropperContainerLeft = imgData.centerPoint.x - cropperContainerWidth / 2;
659
+ const cropperBoxLeft = cropperBox.centerPoint.x - cropperBox.width / 2;
660
+ const cropperBoxTop = cropperBox.centerPoint.y - cropperBox.height / 2;
661
+ const realZoom = zoom * this.imgData.scale;
662
+ const relativeCropLeft = (cropperBoxLeft - cropperContainerLeft) / realZoom;
663
+ const relativeCropTop = (cropperBoxTop - cropperContainerTop) / realZoom;
664
+ const relativeWidth = cropperBox.width / realZoom;
665
+ const relativeHeight = cropperBox.height / realZoom;
666
+ const relativeCropRight = relativeCropLeft + relativeWidth;
667
+ const relativeCropBottom = relativeCropTop + relativeHeight;
668
+ if (relativeCropRight < 0 || relativeCropBottom < 0 || relativeCropLeft > containerWidth || relativeCropTop > containerHeight) {
669
+ // 没有交集,直接返回空白图片
670
+ const emptyCanvas = document.createElement('canvas');
671
+ const ctx = emptyCanvas.getContext('2d');
672
+ emptyCanvas.width = relativeWidth;
673
+ emptyCanvas.height = relativeHeight;
674
+ ctx.fillStyle = fill;
675
+ ctx.fillRect(0, 0, relativeWidth, relativeHeight);
676
+ return emptyCanvas;
677
+ }
678
+ canvas.width = containerWidth;
679
+ canvas.height = containerHeight;
680
+ ctx.fillStyle = fill;
681
+ ctx.fillRect(0, 0, containerWidth, containerHeight);
682
+ const halfWidth = containerWidth / 2;
683
+ const halfHeight = containerHeight / 2;
684
+ ctx.translate(halfWidth, halfHeight);
685
+ ctx.rotate(rotate * Math.PI / 180);
686
+ ctx.translate(-halfWidth, -halfHeight);
687
+ const imgX = (containerWidth - imgWidth) / 2;
688
+ const imgY = (containerHeight - imgHeight) / 2;
689
+ ctx.drawImage(img, 0, 0, imgWidth, imgHeight, imgX, imgY, imgWidth, imgHeight);
690
+ const canvas2 = document.createElement('canvas');
691
+ const ctx2 = canvas2.getContext('2d');
692
+ // 为了避免裁剪时候,超出被裁切的画布的部分颜色不正常,需要将裁切区域限制在画布范围内。
693
+ // 相对位置会在后续进行修正
694
+ let realLeft = relativeCropLeft;
695
+ let realTop = relativeCropTop;
696
+ let realWidth = relativeWidth;
697
+ let realHeight = relativeHeight;
698
+ if (relativeCropLeft < 0) {
699
+ realLeft = 0;
700
+ }
701
+ if (relativeCropTop < 0) {
702
+ realTop = 0;
703
+ }
704
+ if (relativeCropRight > containerWidth) {
705
+ realWidth = containerWidth - realLeft;
706
+ } else if (relativeCropLeft < 0) {
707
+ realWidth = relativeCropRight;
708
+ }
709
+ if (relativeCropBottom > containerHeight) {
710
+ realHeight = containerHeight - realTop;
711
+ } else if (relativeCropTop < 0) {
712
+ realHeight = relativeCropBottom;
713
+ }
714
+ const imgDataResult = ctx.getImageData(realLeft, realTop, realWidth, realHeight);
715
+ canvas2.width = relativeWidth;
716
+ canvas2.height = relativeHeight;
717
+ ctx2.fillStyle = fill;
718
+ ctx2.fillRect(0, 0, relativeWidth, relativeHeight);
719
+ ctx2.putImageData(imgDataResult, relativeCropLeft < 0 ? -relativeCropLeft : 0, relativeCropTop < 0 ? -relativeCropTop : 0);
720
+ return canvas2;
721
+ };
722
+ this.containerData = {};
723
+ this.imgData = {};
724
+ this.boxMoveDir = '';
725
+ this.boxMoveParam = {
726
+ paramX: 0,
727
+ paramY: 0
728
+ };
729
+ this.rangeX = null;
730
+ this.rangeY = null;
731
+ this.initial = false;
732
+ }
733
+ init() {
734
+ // 获取容器的宽高
735
+ // get cropping Container 's width & height
736
+ const container = this._adapter.getContainer();
737
+ this.containerData.width = container.clientWidth;
738
+ this.containerData.height = container.clientHeight;
739
+ this.cropperBoxMoveStart = null;
740
+ }
741
+ destroy() {
742
+ this.unBindMoveEvent();
743
+ this.unBindResizeEvent();
744
+ }
745
+ getMoveParamByDir(dir) {
746
+ let paramX = 0,
747
+ paramY = 0;
748
+ switch (dir) {
749
+ case 'tl':
750
+ paramX = -1;
751
+ paramY = -1;
752
+ break;
753
+ case 'tm':
754
+ paramY = -1;
755
+ break;
756
+ case 'tr':
757
+ paramX = 1;
758
+ paramY = -1;
759
+ break;
760
+ case 'ml':
761
+ paramX = -1;
762
+ break;
763
+ case 'mr':
764
+ paramX = 1;
765
+ break;
766
+ case 'bl':
767
+ paramX = -1;
768
+ paramY = 1;
769
+ break;
770
+ case 'bm':
771
+ paramY = 1;
772
+ break;
773
+ case 'br':
774
+ paramX = 1;
775
+ paramY = 1;
776
+ break;
777
+ default:
778
+ break;
779
+ }
780
+ return {
781
+ paramX,
782
+ paramY
783
+ };
784
+ }
785
+ }
786
+ exports.default = CropperFoundation;