1- import { showElem , type DOMEvent } from '../../utils/dom.ts' ;
1+ import { CropperCanvas , CropperImage } from 'cropperjs' ;
2+ import { createElementFromHTML , showElem , type DOMEvent } from '../../utils/dom.ts' ;
23
34type CropperOpts = {
45 container : HTMLElement ,
@@ -7,33 +8,54 @@ type CropperOpts = {
78}
89
910async function initCompCropper ( { container, fileInput, imageSource} : CropperOpts ) {
10- const { default : Cropper } = await import ( /* webpackChunkName: "cropperjs" */ 'cropperjs' ) ;
11+ await import ( /* webpackChunkName: "cropperjs" */ 'cropperjs' ) ;
1112 let currentFileName = '' ;
1213 let currentFileLastModified = 0 ;
13- const cropper = new Cropper ( imageSource , {
14- aspectRatio : 1 ,
15- viewMode : 2 ,
16- autoCrop : false ,
17- crop ( ) {
18- const canvas = cropper . getCroppedCanvas ( ) ;
19- canvas . toBlob ( ( blob ) => {
20- const croppedFileName = currentFileName . replace ( / \. [ ^ . ] { 3 , 4 } $ / , '.png' ) ;
21- const croppedFile = new File ( [ blob ] , croppedFileName , { type : 'image/png' , lastModified : currentFileLastModified } ) ;
22- const dataTransfer = new DataTransfer ( ) ;
23- dataTransfer . items . add ( croppedFile ) ;
24- fileInput . files = dataTransfer . files ;
25- } ) ;
26- } ,
14+
15+ const canvasEl = createElementFromHTML < CropperCanvas > ( `
16+ <cropper-canvas background>
17+ <cropper-image src="${ imageSource . src } " rotatable scalable skewable translatable></cropper-image>
18+ <cropper-shade hidden></cropper-shade>
19+ <cropper-handle action="select" plain></cropper-handle>
20+ <cropper-selection initial-coverage="0.5" initial-aspect-ratio="1" movable resizable>
21+ <cropper-grid role="grid" covered></cropper-grid>
22+ <cropper-crosshair centered></cropper-crosshair>
23+ <cropper-handle action="move" theme-color="#ffffff23"></cropper-handle>
24+ <cropper-handle action="n-resize"></cropper-handle>
25+ <cropper-handle action="e-resize"></cropper-handle>
26+ <cropper-handle action="s-resize"></cropper-handle>
27+ <cropper-handle action="w-resize"></cropper-handle>
28+ <cropper-handle action="ne-resize"></cropper-handle>
29+ <cropper-handle action="nw-resize"></cropper-handle>
30+ <cropper-handle action="se-resize"></cropper-handle>
31+ <cropper-handle action="sw-resize"></cropper-handle>
32+ </cropper-selection>
33+ </cropper-canvas>
34+ ` ) ;
35+
36+ const imgEl = canvasEl . querySelector < CropperImage > ( 'cropper-image' ) ;
37+
38+ canvasEl . addEventListener ( 'action' , async ( e ) => {
39+ const canvas = await ( e . target as CropperCanvas ) . $toCanvas ( ) ;
40+ canvas . toBlob ( ( blob ) => {
41+ const croppedFileName = currentFileName . replace ( / \. [ ^ . ] { 3 , 4 } $ / , '.png' ) ;
42+ const croppedFile = new File ( [ blob ] , croppedFileName , { type : 'image/png' , lastModified : currentFileLastModified } ) ;
43+ const dataTransfer = new DataTransfer ( ) ;
44+ dataTransfer . items . add ( croppedFile ) ;
45+ fileInput . files = dataTransfer . files ;
46+ } ) ;
2747 } ) ;
2848
49+ imageSource . replaceWith ( canvasEl ) ;
50+
2951 fileInput . addEventListener ( 'input' , ( e : DOMEvent < Event , HTMLInputElement > ) => {
3052 const files = e . target . files ;
3153 if ( files ?. length > 0 ) {
3254 currentFileName = files [ 0 ] . name ;
3355 currentFileLastModified = files [ 0 ] . lastModified ;
3456 const fileURL = URL . createObjectURL ( files [ 0 ] ) ;
3557 imageSource . src = fileURL ;
36- cropper . replace ( fileURL ) ;
58+ imgEl . src = fileURL ;
3759 showElem ( container ) ;
3860 }
3961 } ) ;
0 commit comments