我想在前端上传之前裁剪图像(反应)

Posted

技术标签:

【中文标题】我想在前端上传之前裁剪图像(反应)【英文标题】:i wanna crop image before upload in frontend (react) 【发布时间】:2020-12-24 23:44:54 【问题描述】:

这是产品表单组件,我想裁剪图像并在没有后端的情况下上传,然后将其上传到 Firebase 存储 我想以恒定的纵横比自动或手动裁剪以适合卡片,或者我想在卡片本身裁剪它我尝试使用 react-image-crop 但我没有成功,它需要大量设置,我不知道怎么弄

import React,  useState  from 'react'
import Input from '../../components/input/input.component'
import Button from '../../components/button/button.component'
import db from '../../firebase'
import './addproduct.styles.scss'
import  storage  from 'firebase'
import Spinner from '../../components/spinner/spinner.component'
const AddProduct = (catigories) => 
    const [name,setName] = useState('')
    const [price,setPrice] = useState('')
    const [catigory,setCatigory] = useState('')
    const [newCatigoryName,setNewCatigoryName] = useState('')
    const [newCatigoryImg,setNewCatigorImg] = useState(null)
    const [image,setImage] = useState(null)
    const [isSending,setIsSending] = useState(false)
    console.log(image)
    const handleSubmit = async (event) => 
        event.preventDefault()
        if(name && price  && image && catigory)
            setIsSending(true)
            if(catigory === 'addNewCatigory' && newCatigoryImg && newCatigoryName)
                await storage().ref().child(`catigories/$newCatigoryName.jpg`).put(newCatigoryImg)
                const catigoryImgUrl = await storage().ref().child(`catigories/$newCatigoryName.jpg`).getDownloadURL()
                await db.collection('catigories').doc(newCatigoryName).set(
                    name:newCatigoryName,
                    imgUrl:catigoryImgUrl
                )
                const storageId = `$name-$price-$catigory`
                await storage().ref().child(`products/$storageId.jpg`).put(image)
                const productImgUrl = await storage().ref().child(`products/$storageId.jpg`).getDownloadURL()
                await db.collection('products').add(
                    name:name,
                    price: parseInt(price),
                    imgUrl:productImgUrl,
                    catigory:newCatigoryName
                )
                setIsSending(false)
            else
                const storageId = `$name-$price-$catigory`
                await storage().ref().child(`products/$storageId.jpg`).put(image)
                const productImgUrl = await storage().ref().child(`products/$storageId.jpg`).getDownloadURL()
                await db.collection('products').add(
                    name:name,
                    price: parseInt(price),
                    imgUrl:productImgUrl,
                    catigory:catigory
                )
                setIsSending(false)
            
        
        
    
    if(isSending)
        return <Spinner />
    
    return (
        <div className='product'>
            <form onSubmit=handleSubmit className="product__form">
                <Input placeholder='Enter Product Name' value=name setValue=setName width='100%' fontSize='20px' height='40px' borderRadius='20px'type='text' margin />            
                <Input placeholder='Product Price' value=price setValue=setPrice width='100%' fontSize='20px' height='40px' borderRadius='20px'type='number' margin />            
                <input type="file" onChange=(event) => event.target.files[0] ? setImage(event.target.files[0]) :null/> 
                <select className='product__form__select' onChange=(event) => setCatigory(event.target.value)>
                    <option value=''>Catigories</option>
                    catigories.map(item => <option key=item.name value=item.name>item.name</option>)
                    <option value='addNewCatigory'>other</option>
                </select>
                catigory === 'addNewCatigory' ? 
                    <div className='product__form__addcatigory'>
                        <Input placeholder='Catigory Name' value=newCatigoryName setValue=setNewCatigoryName width='100%' fontSize='20px' height='40px' borderRadius='20px'type='text' margin />
                        <input type="file" onChange=(event) => event.target.files[0] ? setNewCatigorImg(event.target.files[0]) :null/> 
                    </div>
                    : null
                
                <Button title='add Item' width='100px' height='40px' style=borderRadius:'20px'/>
            </form>
        </div>
    )


export default AddProduct

【问题讨论】:

【参考方案1】:

您可以在前端选择图像后裁剪图像。对于裁剪图像,这 2 个模块是最好的。

    React-easy-crop React-image-crop。

这些模块的集成也很简单。

【讨论】:

【参考方案2】:

我最近在blogged 上讨论了如何使用react-uploady 执行此操作。

查看此codesandbox 以获取完整示例。

代码使用 react-image-crop,但与它没有任何关联,因此您可以将其替换为您想要的任何其他裁剪解决方案。

归结为:

import React,  useState, useCallback, useRef  from "react";
import ReactCrop from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";
import Uploady,  withRequestPreSendUpdate  from "@rpldy/uploady";
import UploadButton from "@rpldy/upload-button";
import UploadPreview from "@rpldy/upload-preview";
import cropImage from "./cropImage";

const ItemPreviewWithCrop = withRequestPreSendUpdate((props) => 
  const  url, updateRequest, requestData  = props;
  const [crop, setCrop] = useState( aspect: 4 / 3 );

  const onUploadCrop = useCallback(async () => 
    if (updateRequest && (crop?.height || crop?.width)) 
      requestData.items[0].file = await cropImage(url, requestData.items[0].file, crop);
      updateRequest( items: requestData.items );
    
  , [url, requestData, updateRequest, crop]);

  return (
    <>
      <ReactCrop
        src=url
        crop=crop
        onChange=setCrop
        onComplete=setCrop
      />
      <br/>
      <button onClick=onUploadCrop>Upload Cropped</button>
    </>
  );
);

export default function App() 
  const previewMethodsRef = useRef();

  return (
    <Uploady destination= url: "[upload-url]"  multiple=false>
      <br />
      <UploadButton>Select File</UploadButton>
      <br />
      <UploadPreview
        PreviewComponent=ItemPreviewWithCrop
        previewComponentProps= previewMethods: previewMethodsRef 
        previewMethodsRef=previewMethodsRef       
      />
    </Uploady>
  );

它将在裁剪区域中以固定的 4/3 纵横比显示所选文件(仅作为示例)。

【讨论】:

以上是关于我想在前端上传之前裁剪图像(反应)的主要内容,如果未能解决你的问题,请参考以下文章

在通过 slingshot 上传之前使用 Meteor js 中的 Cropit 进行图像裁剪

上传时如何裁剪图像?

当我们上传图像时,是不是有任何反应原生包可以像 instagram 一样自动裁剪图像?

没有 .net 库的图像裁剪 C#

将裁剪添加到 PHP 图像调整大小脚本

在将图像发送到服务器之前上传并裁剪图像[关闭]