@gm-pc/cropper 1.24.9-beta.13 → 1.24.9-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/src/cropper.tsx +120 -120
- package/src/get_type.ts +12 -12
- package/src/index.less +21 -21
- package/src/index.ts +2 -2
- package/src/stories.tsx +77 -77
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gm-pc/cropper",
|
|
3
|
-
"version": "1.24.9-beta.
|
|
3
|
+
"version": "1.24.9-beta.14",
|
|
4
4
|
"description": "",
|
|
5
5
|
"author": "liyatang <liyatang@qq.com>",
|
|
6
6
|
"homepage": "https://github.com/gmfe/gm-pc#readme",
|
|
@@ -26,10 +26,10 @@
|
|
|
26
26
|
"react-dom": "^16.14.0"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@gm-pc/locales": "^1.24.9-beta.
|
|
30
|
-
"@gm-pc/react": "^1.24.9-beta.
|
|
31
|
-
"@gm-pc/table-x": "^1.24.9-beta.
|
|
29
|
+
"@gm-pc/locales": "^1.24.9-beta.14",
|
|
30
|
+
"@gm-pc/react": "^1.24.9-beta.14",
|
|
31
|
+
"@gm-pc/table-x": "^1.24.9-beta.14",
|
|
32
32
|
"cropperjs": "^1.5.9"
|
|
33
33
|
},
|
|
34
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "00c9b30ab0b492a57273126591b003ca2f3dce1b"
|
|
35
35
|
}
|
package/src/cropper.tsx
CHANGED
|
@@ -1,120 +1,120 @@
|
|
|
1
|
-
import React, { FC, useEffect, useRef } from 'react'
|
|
2
|
-
import { Button, Flex, UploaderFile, Modal } from '@gm-pc/react'
|
|
3
|
-
import CropperJS from 'cropperjs'
|
|
4
|
-
import { getLocale } from '@gm-pc/locales'
|
|
5
|
-
import getType from './get_type'
|
|
6
|
-
|
|
7
|
-
const DEFAULT_OPTIONS: CropperJS.Options = {
|
|
8
|
-
aspectRatio: 1,
|
|
9
|
-
viewMode: 1,
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface CropperProps {
|
|
13
|
-
file?: UploaderFile
|
|
14
|
-
url?: string
|
|
15
|
-
options?: CropperJS.Options
|
|
16
|
-
croppedOptions?: { width?: number; height: number }
|
|
17
|
-
onCancel(): void
|
|
18
|
-
onOK(blob: Blob | null): void
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
interface CropperStatic {
|
|
22
|
-
SIZE: {
|
|
23
|
-
SKU: { width: number; height: number }
|
|
24
|
-
LOGO: { width: number; height: number }
|
|
25
|
-
}
|
|
26
|
-
render(props: Omit<CropperProps, 'onCancel' | 'onOK'>): Promise<Blob | null>
|
|
27
|
-
hide: typeof Modal.hide
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const Cropper: FC<CropperProps> & CropperStatic = ({
|
|
31
|
-
file,
|
|
32
|
-
url,
|
|
33
|
-
options,
|
|
34
|
-
croppedOptions,
|
|
35
|
-
onCancel,
|
|
36
|
-
onOK,
|
|
37
|
-
}) => {
|
|
38
|
-
const imageRef = useRef<HTMLImageElement>(null)
|
|
39
|
-
const imgPreviewRef = useRef<HTMLDivElement>(null)
|
|
40
|
-
const cropperRef = useRef<CropperJS>()
|
|
41
|
-
|
|
42
|
-
useEffect(() => {
|
|
43
|
-
const imgDOM: HTMLImageElement = imageRef.current!
|
|
44
|
-
const imgPreviewDOM: HTMLDivElement = imgPreviewRef.current!
|
|
45
|
-
cropperRef.current = new CropperJS(imgDOM, {
|
|
46
|
-
...DEFAULT_OPTIONS,
|
|
47
|
-
...options,
|
|
48
|
-
preview: imgPreviewDOM,
|
|
49
|
-
})
|
|
50
|
-
}, [options])
|
|
51
|
-
|
|
52
|
-
const handleOK = (): void => {
|
|
53
|
-
cropperRef.current!.getCroppedCanvas(croppedOptions).toBlob(
|
|
54
|
-
(blob) => {
|
|
55
|
-
onOK(blob)
|
|
56
|
-
},
|
|
57
|
-
url ? getType(url) ?? 'image/jpeg' : file?.type
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
return (
|
|
62
|
-
<div className='gm-cropper'>
|
|
63
|
-
<Flex justifyBetween>
|
|
64
|
-
<div>
|
|
65
|
-
<img
|
|
66
|
-
alt=''
|
|
67
|
-
className='gm-cropper-img'
|
|
68
|
-
ref={imageRef}
|
|
69
|
-
src={url ?? file?.preview}
|
|
70
|
-
/>
|
|
71
|
-
</div>
|
|
72
|
-
<div>
|
|
73
|
-
<div ref={imgPreviewRef} className='gm-cropper-preview' />
|
|
74
|
-
<div className='gm-text-desc gm-text-center gm-margin-top-10'>
|
|
75
|
-
{getLocale('预览')}
|
|
76
|
-
</div>
|
|
77
|
-
</div>
|
|
78
|
-
</Flex>
|
|
79
|
-
<div className='text-right gm-margin-top-10'>
|
|
80
|
-
<Button onClick={onCancel}>{getLocale('取消')}</Button>
|
|
81
|
-
<div className='gm-gap-10' />
|
|
82
|
-
<Button type='primary' onClick={handleOK}>
|
|
83
|
-
{getLocale('确定')}
|
|
84
|
-
</Button>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
Cropper.SIZE = {
|
|
91
|
-
SKU: { width: 720, height: 720 },
|
|
92
|
-
LOGO: { width: 720, height: 720 },
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
Cropper.render = (props) => {
|
|
96
|
-
return new Promise<Blob | null>((resolve, reject) => {
|
|
97
|
-
const handleOk = (blob: Blob | null) => {
|
|
98
|
-
Modal.hide()
|
|
99
|
-
resolve(blob)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const handleCancel = () => {
|
|
103
|
-
Modal.hide()
|
|
104
|
-
reject(new Error('cancel'))
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
Modal.render({
|
|
108
|
-
title: getLocale('编辑头像'),
|
|
109
|
-
children: <Cropper {...props} onCancel={handleCancel} onOK={handleOk} />,
|
|
110
|
-
disableMaskClose: true,
|
|
111
|
-
style: {
|
|
112
|
-
width: '520px',
|
|
113
|
-
},
|
|
114
|
-
})
|
|
115
|
-
})
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
Cropper.hide = Modal.hide
|
|
119
|
-
|
|
120
|
-
export default Cropper
|
|
1
|
+
import React, { FC, useEffect, useRef } from 'react'
|
|
2
|
+
import { Button, Flex, UploaderFile, Modal } from '@gm-pc/react'
|
|
3
|
+
import CropperJS from 'cropperjs'
|
|
4
|
+
import { getLocale } from '@gm-pc/locales'
|
|
5
|
+
import getType from './get_type'
|
|
6
|
+
|
|
7
|
+
const DEFAULT_OPTIONS: CropperJS.Options = {
|
|
8
|
+
aspectRatio: 1,
|
|
9
|
+
viewMode: 1,
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface CropperProps {
|
|
13
|
+
file?: UploaderFile
|
|
14
|
+
url?: string
|
|
15
|
+
options?: CropperJS.Options
|
|
16
|
+
croppedOptions?: { width?: number; height: number }
|
|
17
|
+
onCancel(): void
|
|
18
|
+
onOK(blob: Blob | null): void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface CropperStatic {
|
|
22
|
+
SIZE: {
|
|
23
|
+
SKU: { width: number; height: number }
|
|
24
|
+
LOGO: { width: number; height: number }
|
|
25
|
+
}
|
|
26
|
+
render(props: Omit<CropperProps, 'onCancel' | 'onOK'>): Promise<Blob | null>
|
|
27
|
+
hide: typeof Modal.hide
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const Cropper: FC<CropperProps> & CropperStatic = ({
|
|
31
|
+
file,
|
|
32
|
+
url,
|
|
33
|
+
options,
|
|
34
|
+
croppedOptions,
|
|
35
|
+
onCancel,
|
|
36
|
+
onOK,
|
|
37
|
+
}) => {
|
|
38
|
+
const imageRef = useRef<HTMLImageElement>(null)
|
|
39
|
+
const imgPreviewRef = useRef<HTMLDivElement>(null)
|
|
40
|
+
const cropperRef = useRef<CropperJS>()
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const imgDOM: HTMLImageElement = imageRef.current!
|
|
44
|
+
const imgPreviewDOM: HTMLDivElement = imgPreviewRef.current!
|
|
45
|
+
cropperRef.current = new CropperJS(imgDOM, {
|
|
46
|
+
...DEFAULT_OPTIONS,
|
|
47
|
+
...options,
|
|
48
|
+
preview: imgPreviewDOM,
|
|
49
|
+
})
|
|
50
|
+
}, [options])
|
|
51
|
+
|
|
52
|
+
const handleOK = (): void => {
|
|
53
|
+
cropperRef.current!.getCroppedCanvas(croppedOptions).toBlob(
|
|
54
|
+
(blob) => {
|
|
55
|
+
onOK(blob)
|
|
56
|
+
},
|
|
57
|
+
url ? getType(url) ?? 'image/jpeg' : file?.type
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className='gm-cropper'>
|
|
63
|
+
<Flex justifyBetween>
|
|
64
|
+
<div>
|
|
65
|
+
<img
|
|
66
|
+
alt=''
|
|
67
|
+
className='gm-cropper-img'
|
|
68
|
+
ref={imageRef}
|
|
69
|
+
src={url ?? file?.preview}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
<div>
|
|
73
|
+
<div ref={imgPreviewRef} className='gm-cropper-preview' />
|
|
74
|
+
<div className='gm-text-desc gm-text-center gm-margin-top-10'>
|
|
75
|
+
{getLocale('预览')}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
</Flex>
|
|
79
|
+
<div className='text-right gm-margin-top-10'>
|
|
80
|
+
<Button onClick={onCancel}>{getLocale('取消')}</Button>
|
|
81
|
+
<div className='gm-gap-10' />
|
|
82
|
+
<Button type='primary' onClick={handleOK}>
|
|
83
|
+
{getLocale('确定')}
|
|
84
|
+
</Button>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
Cropper.SIZE = {
|
|
91
|
+
SKU: { width: 720, height: 720 },
|
|
92
|
+
LOGO: { width: 720, height: 720 },
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Cropper.render = (props) => {
|
|
96
|
+
return new Promise<Blob | null>((resolve, reject) => {
|
|
97
|
+
const handleOk = (blob: Blob | null) => {
|
|
98
|
+
Modal.hide()
|
|
99
|
+
resolve(blob)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const handleCancel = () => {
|
|
103
|
+
Modal.hide()
|
|
104
|
+
reject(new Error('cancel'))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Modal.render({
|
|
108
|
+
title: getLocale('编辑头像'),
|
|
109
|
+
children: <Cropper {...props} onCancel={handleCancel} onOK={handleOk} />,
|
|
110
|
+
disableMaskClose: true,
|
|
111
|
+
style: {
|
|
112
|
+
width: '520px',
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
Cropper.hide = Modal.hide
|
|
119
|
+
|
|
120
|
+
export default Cropper
|
package/src/get_type.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
function getType(url: string): string | undefined {
|
|
2
|
-
if (url.includes('.png')) {
|
|
3
|
-
return 'image/png'
|
|
4
|
-
} else if (url.includes('.jpg') || url.includes('.jpeg')) {
|
|
5
|
-
return 'image/jpeg'
|
|
6
|
-
} else if (url.includes('png')) {
|
|
7
|
-
return 'image/png'
|
|
8
|
-
}
|
|
9
|
-
return undefined
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export default getType
|
|
1
|
+
function getType(url: string): string | undefined {
|
|
2
|
+
if (url.includes('.png')) {
|
|
3
|
+
return 'image/png'
|
|
4
|
+
} else if (url.includes('.jpg') || url.includes('.jpeg')) {
|
|
5
|
+
return 'image/jpeg'
|
|
6
|
+
} else if (url.includes('png')) {
|
|
7
|
+
return 'image/png'
|
|
8
|
+
}
|
|
9
|
+
return undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export default getType
|
package/src/index.less
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
@import '~cropperjs/dist/cropper.min.css';
|
|
2
|
-
|
|
3
|
-
.gm-cropper {
|
|
4
|
-
width: 500px;
|
|
5
|
-
|
|
6
|
-
.gm-cropper-img {
|
|
7
|
-
display: block;
|
|
8
|
-
width: 360px;
|
|
9
|
-
height: 360px;
|
|
10
|
-
max-width: 360px;
|
|
11
|
-
max-height: 360px;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
.gm-cropper-preview {
|
|
15
|
-
width: 120px;
|
|
16
|
-
max-width: 120px;
|
|
17
|
-
height: 120px;
|
|
18
|
-
max-height: 120px;
|
|
19
|
-
overflow: hidden;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
1
|
+
@import '~cropperjs/dist/cropper.min.css';
|
|
2
|
+
|
|
3
|
+
.gm-cropper {
|
|
4
|
+
width: 500px;
|
|
5
|
+
|
|
6
|
+
.gm-cropper-img {
|
|
7
|
+
display: block;
|
|
8
|
+
width: 360px;
|
|
9
|
+
height: 360px;
|
|
10
|
+
max-width: 360px;
|
|
11
|
+
max-height: 360px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.gm-cropper-preview {
|
|
15
|
+
width: 120px;
|
|
16
|
+
max-width: 120px;
|
|
17
|
+
height: 120px;
|
|
18
|
+
max-height: 120px;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { default as Cropper } from './cropper'
|
|
2
|
-
export type { CropperProps } from './cropper'
|
|
1
|
+
export { default as Cropper } from './cropper'
|
|
2
|
+
export type { CropperProps } from './cropper'
|
package/src/stories.tsx
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import Cropper from './cropper'
|
|
3
|
-
import { Uploader } from '@gm-pc/react'
|
|
4
|
-
|
|
5
|
-
export const ComCropper = () => {
|
|
6
|
-
return (
|
|
7
|
-
<Uploader
|
|
8
|
-
accept='image/*'
|
|
9
|
-
onUpload={(files) => {
|
|
10
|
-
console.log(files[0])
|
|
11
|
-
console.log('size before', files[0].size / 1024)
|
|
12
|
-
Cropper.render({
|
|
13
|
-
file: files[0],
|
|
14
|
-
}).then((data) => {
|
|
15
|
-
console.log(data)
|
|
16
|
-
console.log('size after', data!.size / 1024)
|
|
17
|
-
|
|
18
|
-
window.open(window.URL.createObjectURL(data))
|
|
19
|
-
})
|
|
20
|
-
}}
|
|
21
|
-
/>
|
|
22
|
-
)
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const ComCropperWithSize = () => {
|
|
26
|
-
return (
|
|
27
|
-
<Uploader
|
|
28
|
-
accept='image/*'
|
|
29
|
-
onUpload={(files) => {
|
|
30
|
-
console.log(files[0])
|
|
31
|
-
console.log('size before', files[0].size / 1024, 'kb')
|
|
32
|
-
Cropper.render({
|
|
33
|
-
file: files[0],
|
|
34
|
-
croppedOptions: {
|
|
35
|
-
...Cropper.SIZE.SKU,
|
|
36
|
-
},
|
|
37
|
-
}).then((data) => {
|
|
38
|
-
console.log(data)
|
|
39
|
-
console.log('size after', data!.size / 1024, 'kb')
|
|
40
|
-
|
|
41
|
-
window.open(window.URL.createObjectURL(data))
|
|
42
|
-
})
|
|
43
|
-
}}
|
|
44
|
-
/>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export const ComCropperWithAspectRatio = () => {
|
|
49
|
-
return (
|
|
50
|
-
<Uploader
|
|
51
|
-
accept='image/*'
|
|
52
|
-
onUpload={(files) => {
|
|
53
|
-
console.log(files[0])
|
|
54
|
-
console.log('size before', files[0].size / 1024, 'kb')
|
|
55
|
-
Cropper.render({
|
|
56
|
-
file: files[0],
|
|
57
|
-
options: {
|
|
58
|
-
aspectRatio: 2,
|
|
59
|
-
},
|
|
60
|
-
croppedOptions: {
|
|
61
|
-
width: 720,
|
|
62
|
-
height: 360,
|
|
63
|
-
},
|
|
64
|
-
}).then((data) => {
|
|
65
|
-
console.log(data)
|
|
66
|
-
console.log('size after', data!.size / 1024, 'kb')
|
|
67
|
-
|
|
68
|
-
window.open(window.URL.createObjectURL(data))
|
|
69
|
-
})
|
|
70
|
-
}}
|
|
71
|
-
/>
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export default {
|
|
76
|
-
title: 'Cropper/Cropper',
|
|
77
|
-
}
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import Cropper from './cropper'
|
|
3
|
+
import { Uploader } from '@gm-pc/react'
|
|
4
|
+
|
|
5
|
+
export const ComCropper = () => {
|
|
6
|
+
return (
|
|
7
|
+
<Uploader
|
|
8
|
+
accept='image/*'
|
|
9
|
+
onUpload={(files) => {
|
|
10
|
+
console.log(files[0])
|
|
11
|
+
console.log('size before', files[0].size / 1024)
|
|
12
|
+
Cropper.render({
|
|
13
|
+
file: files[0],
|
|
14
|
+
}).then((data) => {
|
|
15
|
+
console.log(data)
|
|
16
|
+
console.log('size after', data!.size / 1024)
|
|
17
|
+
|
|
18
|
+
window.open(window.URL.createObjectURL(data))
|
|
19
|
+
})
|
|
20
|
+
}}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const ComCropperWithSize = () => {
|
|
26
|
+
return (
|
|
27
|
+
<Uploader
|
|
28
|
+
accept='image/*'
|
|
29
|
+
onUpload={(files) => {
|
|
30
|
+
console.log(files[0])
|
|
31
|
+
console.log('size before', files[0].size / 1024, 'kb')
|
|
32
|
+
Cropper.render({
|
|
33
|
+
file: files[0],
|
|
34
|
+
croppedOptions: {
|
|
35
|
+
...Cropper.SIZE.SKU,
|
|
36
|
+
},
|
|
37
|
+
}).then((data) => {
|
|
38
|
+
console.log(data)
|
|
39
|
+
console.log('size after', data!.size / 1024, 'kb')
|
|
40
|
+
|
|
41
|
+
window.open(window.URL.createObjectURL(data))
|
|
42
|
+
})
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const ComCropperWithAspectRatio = () => {
|
|
49
|
+
return (
|
|
50
|
+
<Uploader
|
|
51
|
+
accept='image/*'
|
|
52
|
+
onUpload={(files) => {
|
|
53
|
+
console.log(files[0])
|
|
54
|
+
console.log('size before', files[0].size / 1024, 'kb')
|
|
55
|
+
Cropper.render({
|
|
56
|
+
file: files[0],
|
|
57
|
+
options: {
|
|
58
|
+
aspectRatio: 2,
|
|
59
|
+
},
|
|
60
|
+
croppedOptions: {
|
|
61
|
+
width: 720,
|
|
62
|
+
height: 360,
|
|
63
|
+
},
|
|
64
|
+
}).then((data) => {
|
|
65
|
+
console.log(data)
|
|
66
|
+
console.log('size after', data!.size / 1024, 'kb')
|
|
67
|
+
|
|
68
|
+
window.open(window.URL.createObjectURL(data))
|
|
69
|
+
})
|
|
70
|
+
}}
|
|
71
|
+
/>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export default {
|
|
76
|
+
title: 'Cropper/Cropper',
|
|
77
|
+
}
|