背景
最近接到的需求中H5头像上传和实现基本的图片裁剪,这也是比较常见且典型的场景。
思路
1. 调起移动端相机拍照或相册功能;
2. 选择图片后,将选中的图片放入画布;
3. 因为基于react框架开发,所以使用了第三方插件react- cropper
代码实现
1. 封装react组件
import { useState } from "react";
import HooksCropperModal from "./HooksCropperModal";
import styles from "./index.module.less";
const MAX_FILE_SIZE = 5 * 1024 * 1024; // 文件最大限制为5M
const Avator = () => {
const [hooksModalVisible, setHooksModalVisible] = useState(false); // 裁剪图片
const [hooksModalFile, setHooksModalFile] = useState(null); // 选取的img文件
const [hooksResultImgUrl, setHooksResultImgUrl] = useState(null); // 裁剪后的img
const handleHooksFileChange = (e) => {
const file = e.target.files[0];
if (file) {
if (file.size <= MAX_FILE_SIZE) {
setHooksModalFile(file);
setHooksModalVisible(true);
} else {
console.log("文件过大");
}
}
};
// 图片预览
const handlePreview = () => {};
return (
<div className={styles.container}>
<h1>图片裁剪组件</h1>
<div className={styles["half-area"]}>
<input
type="file"
accept="image/jpeg,image/jpg,image/png"
className={styles["base-upload-input"]}
onChange={handleHooksFileChange}
/>
{/* 最终裁剪好的图片 */}
<div className={styles["img-container"]}>
{hooksResultImgUrl && (
<img
className="img"
src={hooksResultImgUrl}
alt="classResultImgUrl"
onClick={handlePreview}
/>
)}
</div>
</div>
{/* 裁剪框 */}
{hooksModalVisible && (
<HooksCropperModal
uploadedImageFile={hooksModalFile}
onClose={() => {
setHooksModalVisible(false);
}}
onSubmit={setHooksResultImgUrl}
/>
)}
</div>
);
};
export default Avator;
2. 实现图片裁剪功能
import React, { useState, useRef, useEffect, useCallback } from "react";
import { upload } from "@/api/workbench";
import Cropper from "react-cropper";
import styles from "./index.module.less";
import "cropperjs/dist/cropper.css";
/**
* 1. 获取图片,经过reader.readAsDataURL读取,转为为base64格式
* 2. 进行图片的渲染
* (1)压缩图片
* (2)对压缩后的图片进行裁剪
* @returns
*/
const FILE_TYPES = ["image/jpg", "image/png", "image/jpeg", "image/bmp"];
const HooksCropperModal = ({ uploadedImageFile, onClose, onSubmit }) => {
const [src, setSrc] = useState("");
const cropperRef = useRef<any>(null);
useEffect(() => {
if (uploadedImageFile) {
const fileReader = new FileReader(); // 拿到文件
fileReader.onload = (e: any) => {
const dataURL = e.target.result; // base64
setSrc(dataURL);
};
fileReader.readAsDataURL(uploadedImageFile);
}
}, [uploadedImageFile]);
const handleSubmit = useCallback(() => {
const filename = uploadedImageFile.name;
console.log("正在上传图片", filename);
// const data = cropperRef.current.cropper.getCroppedCanvas().toDataURL(); // base64位数据
cropperRef?.current?.cropper?.getCroppedCanvas().toBlob(async (blob) => {
console.log("blob = ", blob);
const formData = new FormData();
formData.append("file", blob, filename);
console.log("formafta", formData);
const { data } = await upload(formData);
onSubmit(data);
onClose();
});
}, [onSubmit, onClose]);
return (
<div className={styles["hooks-cropper-modal"]}>
<div className={styles["modal-panel"]}>
<h1>个人头像</h1>
<div className={styles["cropper-container-container"]}>
<div className={styles["cropper-container"]}>
<Cropper
src={src}
className={styles["cropper"]}
ref={cropperRef}
viewMode={1}
rotatable={true} // 旋转图片
zoomable={false}
aspectRatio={1} // 固定为1:1 可以自己设置比例, 默认情况为自由比例
guides={false}
preview=".cropper-preview"
/>
</div>
</div>
<div className={styles["button-row"]}>
<div
className={styles["cancel-button"]}
onClick={() => {
//
onClose;
}}
>
取消
</div>
<div
className={styles["rotate-button"]}
onClick={() => {
cropperRef?.current?.cropper?.rotate(90); // 顺时针旋转,若逆时针,则为-90
}}
>
旋转
</div>
<div className={styles["submit-button"]} onClick={handleSubmit}>
完成
</div>
</div>
</div>
</div>
);
};
export default HooksCropperModal;
本文介绍了如何在H5中实现头像上传和基本的图片裁剪功能。首先,通过调用移动端相机或相册获取图片,然后将图片放入画布。由于基于React框架,使用了react-cropper第三方插件来实现裁剪功能。
1375

被折叠的 条评论
为什么被折叠?



