文档地址:https://fengyuanchen.github.io/cropperjs/
使用方式:
.1 下载包
yarn add cropperjs
.2 导入包
importCropperfrom"cropperjs"
import"cropperjs/dist/cropper.css"
.3 自定义裁剪比例
const sizeList = [
? {
? ? name: "1:1",
? ? size: 1 / 1,
? },
? {
? ? name: "16:9",
? ? size: 16 / 9,
? },
? {
? ? name: "4:3",
? ? size: 4 / 3,
? },
? {
? ? name: "2:3",
? ? size: 2 / 3,
? },
? {
? ? name: "自由尺寸",
? ? size: NaN,
? },
]
.4 准备 state 数据
constructor(props) {
? ? super(props)
? ? this.imgRef = React.createRef()
? ? this.state = {
? ? ? buttonLoading: false,
? ? ? currenIndex: 0,
? ? }
? }
.5 准备 html 结构
render() {
? ? const { meCropShow, imgUrl } = this.props
? ? const { buttonLoading, currenIndex } = this.state
? ? return (
? ? ? <Modal
? ? ? ? className="meCropModal_view"
? ? ? ? width="50%"
? ? ? ? title="图片裁剪"
? ? ? ? maskClosable={false}
? ? ? ? closable={false}
? ? ? ? visible={meCropShow}
? ? ? ? onCancel={this.cancelFn}
? ? ? ? footer={[
? ? ? ? ? <Button onClick={this.cancelFn}>取消</Button>,
? ? ? ? ? <Button onClick={this.okFn} loading={buttonLoading}>
? ? ? ? ? ? 确认
? ? ? ? ? </Button>,
? ? ? ? ]}
? ? ? >
? ? ? ? <div className="meCropModal_content">
? ? ? ? ? <img src={imgUrl} ref={this.imgRef} className="meCropModal_img" />
? ? ? ? </div>
? ? ? ? <Space className="cropSize_view" size="large">
? ? ? ? ? {sizeList.map((item, index) => {
? ? ? ? ? ? return (
? ? ? ? ? ? ? <Tag
? ? ? ? ? ? ? ? color={index === currenIndex ? "blue" : ""}
? ? ? ? ? ? ? ? key={item.name}
? ? ? ? ? ? ? ? onClick={this.setSize.bind(this, item.size, index)}
? ? ? ? ? ? ? >
? ? ? ? ? ? ? ? {item.name}
? ? ? ? ? ? ? </Tag>
? ? ? ? ? ? )
? ? ? ? ? })}
? ? ? ? </Space>
? ? ? </Modal>
? ? )
? }
.6 准备 css
.cropper-modal {
? background-color: rgba(0, 0, 0, 0.2);
}
//注意 一定要为裁剪框的父元素设置大小
.meCropModal_content {
? width: 100%;
? height: 500px;
}
.meCropModal_img {
? width: 100%;
}
.7 初始化裁剪框
this.newCropper(sizeList[0].size)
newCropper = (aspectRatio) => {
? ? let myCropper = new Cropper(this.imgRef.current, {
? ? ? viewMode: 1,
? ? ? preview: ".before",
? ? ? zoomOnWheel: false,
? ? ? autoCropArea: 0.6,
? ? ? dragMode: "none",
? ? ? background: false,
? ? ? initialAspectRatio: 1,
? ? ? outputType: "png",
? ? ? ready() {
? ? ? ? myCropper.setAspectRatio(aspectRatio)
? ? ? },
? ? })
? ? this.setState({
? ? ? myCropper,
? ? })
}
.8 若要改变裁剪比例 则执行以下代码
/** @params
val:代表要裁剪的比例
index:当前比例的index值 为了指定样式
*/
setSize = (val, index) => {
? ? this.setState({
? ? ? currenIndex: index,
? ? })
? ? /** 这一块坑爹的很 文档上有reset方法和clear方法 试过了都不行 然后人家的示范又能正常切换比例 只好打开sourcemap看看有没有源代码 碰碰运气 结果还真找到了 一看是有这么一个销毁的方法 文档里写的也不太详细 看半天没看到这么一个方法 坑爹的 加上这一句后 立马就好了 */
? ? this.state.myCropper.destroy() //先销毁裁剪框 在重新设置比例
? ? this.newCropper(val)
? }
.9 确认裁剪的方法
okFn = async () => {
? ? this.setState({
? ? ? buttonLoading: true,
? ? })
? ? let url = this.state.myCropper
? ? ? .getCroppedCanvas({
? ? ? ? imageSmoothingQuality: "high",
? ? ? ? outputType: "png",//这个好像并没有用 可写可不写
? ? ? ? fillColor: "#fff", //设置背景色 意思就是在裁剪透明png图片的时候 默认裁剪出来是黑色背景 此处修改为白色背景
? ? ? })
? ? ? .toDataURL("image/jpeg")
?? ?//此方法是将图片的base64转换为file对象
? ? let files = this.base64toFile(url)
? ? if (files) {
? ? ? var file = new FormData()
? ? ? file.append("file", files)
? ? ? file.append("token", this.state.qiToken)
? ? ? file.append("key", y.randomCount())
? ? ? const res = await instImg({
? ? ? ? method: "post",
? ? ? ? url: "http://upload.qiniu.com",
? ? ? ? data: file,
? ? ? })
? ? ? if (res.status === 200) {
? ? ? ? let key = res.data.key
?? ?//此方法是自定义的子传父的通讯方法 触发后在父组件进行要执行的操作
? ? ? ? this.props.cancleFn({ type: 1, key: key })
? ? ? } else {
? ? ? ? message.info("上传异常,请稍后重新尝试")
? ? ? }
? ? ? this.setState({
? ? ? ? buttonLoading: false,
? ? ? })
? ? }
? }
? /*base64转换为file对象 ?*/
? base64toFile = (dataurl, filename) => {
? ? //将base64转换为文件
? ? var arr = dataurl.split(","),
? ? ? mime = arr[0].match(/:(.*?);/)[1],
? ? ? bstr = atob(arr[1]),
? ? ? n = bstr.length,
? ? ? u8arr = new Uint8Array(n)
? ? while (n--) {
? ? ? u8arr[n] = bstr.charCodeAt(n)
? ? }
? ? return new File([u8arr], filename, { type: mime })
? }
? cancelFn = () => {
? ? this.props.cancleFn({ type: 2 })
? }
.10 在需要的地方导入封装好的裁剪框
import MeCrop from "component/meCrop/meCrop"
.11 父组件的 html 与 state
? state = {
? ? meCropShow: false,
? ? imgUrl: null,
? }
? {meCropShow && (
? ? ? ? ? <MeCrop
? ? ? ? ? ? meCropShow={meCropShow}
? ? ? ? ? ? cancleFn={this.cancleFn}
? ? ? ? ? ? imgUrl={imgUrl}
? ? ? ? ? ></MeCrop>
? ?)}
.12 父组件的通讯回调
? cancleFn = (parmas) => {
? ? const { type } = parmas
? ? if (type == 1) {
? ? ? const { key } = parmas
? ? ? this.setState({
? ? ? ? formData: {
? ? ? ? ? ...this.state.formData,
? ? ? ? ? cover: key,
? ? ? ? },
? ? ? })
? ? }
? ? this.setState({
? ? ? meCropShow: false,
? ? })
? }
.13 效果图
.14 over了
其实我长得就跟上面那个图一样帅!
|