image-transfer / src /components /dropzone.tsx
william
add login
a8dfd23
import {
CloseSquareOutlined,
InboxOutlined,
SyncOutlined,
} from "@ant-design/icons";
import { Upload } from "antd";
import { useAtom, atom } from "jotai";
import imageCompression from "browser-image-compression";
import React, { useState } from "react";
const { Dragger } = Upload;
export const uploadImageAtom = atom<string | null>(null);
const Dropzone: React.FC = () => {
const [file, setFile] = useAtom(uploadImageAtom);
const [compressing, setCompressing] = useState(false);
return (
<div className="relative flex justify-center items-center w-[600px] h-[400px]">
<>
{compressing && (
<div className="absolute top-0 w-full h-full flex justify-center items-center z-10">
<SyncOutlined spin className="text-9xl text-gray-700 opacity-60" />
</div>
)}
{file && (
<>
<CloseSquareOutlined
className="absolute top-0 right-0 translate-x-[100%] pl-1 text-xl text-gray-800 opacity-60 hover:scale-125"
onClick={() => setFile(null)}
/>
<img className="object-contain w-full h-full" src={file} />
</>
)}
<Dragger
accept="image/*"
className="absolute w-full h-full"
name="file"
multiple={false}
showUploadList={false}
maxCount={1}
beforeUpload={async (file) => {
console.log("file", file);
let compressedFile: File;
if (file.size / 1024 > 500) {
setCompressing(true);
compressedFile = await imageCompression(file, {
maxSizeMB: 1,
maxWidthOrHeight: 1920,
useWebWorker: true,
});
console.log(`compress ratio ${compressedFile.size / file.size}`);
}
const base64 = await new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(compressedFile || file);
reader.onload = () => resolve(reader.result as string);
reader.onerror = (error) => reject(error);
});
setFile(base64);
setCompressing(false);
return false;
}}
>
{!file && (
<>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">
Click or drag file to this area to upload
</p>
</>
)}
</Dragger>
</>
</div>
);
};
export default Dropzone;