react图片裁剪工具 - react-image-crop

react-image-crop

react-image-crop 是react响应式图片裁剪的一个工具包,能做到裁剪区域,裁剪宽高比限制等等。
npm地址:https://www.npmjs.com/package/react-image-crop

阅读前须知

版本的不同,在使用时有不同的表现,也可能造成使用失败。
本文中基于版本:8.6.2

安装

npm

npm install react-image-crop --save

CDN

<script src="https://unpkg.com/react-image-crop/dist/ReactCrop.min.js"></script>

注意,当使用<script>标签全局导入脚本时,请使用ReactCrop.Component访问组件。

使用

在使用得地方导入组件和样式模块

import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';
// or scss;
import 'react-image-crop/lib/ReactCrop.scss'

组件使用

  <ReactCrop
            src={imageurl} 
            crop={crop}
            ruleOfThirds
            onImageLoaded={this.onImageLoaded}
            onComplete={this.onCropComplete}
            onChange={this.onCropChange}
          />

属性解释:

src:图片路径
crop:裁剪相关配置 参考地址:https://www.npmjs.com/package/react-image-crop#crop-required
ruleOfThirds:裁剪区域三分规则默认false;

ruleOfThirds为false时:
在这里插入图片描述
ruleOfThirds为true时(注意图中裁剪区域的九宫格):
在这里插入图片描述
onImageLoaded: 图片加载时的回调函数,返回image对象;
onComplete:裁剪区域调整大小、拖动、微调之后的回调,返回当前裁剪对象;
onChange:裁剪区域调整大小、拖动、微调时的回调,返回当前裁剪对象;官网中的提示:请注意,您必须实现此回调并更新您的裁剪状态,否则什么都不会改变!
更多属性参考

获取到的裁剪区域保存为图片

  // 组件的onComplete事件
  onCropComplete = crop => {
    this.makeClientCrop(crop);
  };
  // 调用getCroppedImg函数获取裁剪图片信息
   async makeClientCrop(crop) {
    if (this.imageRef && crop.width && crop.height) {
      const croppedImageUrl = await this.getCroppedImg(
        this.imageRef,
        crop,
        'newFile.jpeg'
      );
      /*
      * croppedImageUrl: {url,blob,crop}
      *  @url:图片文件对象的DOMString url 
      *  @blob: 图片文件的类文件对象
      *  @crop: 裁剪参数
      */
  }
// 裁剪区域转图片的处理 
 getCroppedImg(image, crop, fileName) {
    const canvas = document.createElement('canvas');
    const scaleX = image.naturalWidth / image.width;
    const scaleY = image.naturalHeight / image.height;
    canvas.width = crop.width;
    canvas.height = crop.height;
    const ctx = canvas.getContext('2d');

    ctx.drawImage(
      image,
      crop.x * scaleX,
      crop.y * scaleY,
      crop.width * scaleX,
      crop.height * scaleY,
      0,
      0,
      crop.width,
      crop.height
    );

    return new Promise((resolve, reject) => {
      canvas.toBlob(blob => {
        if (!blob) {
          //reject(new Error('Canvas is empty'));
          console.error('Canvas is empty');
          return;
        }
        blob.name = fileName;
        window.URL.revokeObjectURL(this.fileUrl);
        this.fileUrl = window.URL.createObjectURL(blob);
        resolve({url:this.fileUrl,blob,crop});
      }, 'image/jpeg');
    });
  }

官方完整示例代码

import ReactDOM from "react-dom";
import React, { PureComponent } from "react";
import ReactCrop from "react-image-crop";
import "react-image-crop/dist/ReactCrop.css";

import "./App.css";

class App extends PureComponent {
  state = {
    src: null,
    crop: {
      unit: "%",
      width: 30,
      aspect: 16 / 9
    }
  };

  onSelectFile = e => {
    if (e.target.files && e.target.files.length > 0) {
      const reader = new FileReader();
      reader.addEventListener("load", () =>
        this.setState({ src: reader.result })
      );
      reader.readAsDataURL(e.target.files[0]);
    }
  };

  // If you setState the crop in here you should return false.
  onImageLoaded = image => {
    this.imageRef = image;
  };

  onCropComplete = crop => {
    this.makeClientCrop(crop);
  };

  onCropChange = (crop, percentCrop) => {
    // You could also use percentCrop:
    // this.setState({ crop: percentCrop });
    this.setState({ crop });
  };

  async makeClientCrop(crop) {
    if (this.imageRef && crop.width && crop.height) {
      const croppedImageUrl = await this.getCroppedImg(
        this.imageRef,
        crop,
        "newFile.jpeg"
      );
      this.setState({ croppedImageUrl });
    }
  }

  getCroppedImg(image, crop, fileName) {
    const canvas = document.createElement("canvas");
    const scaleX = image.naturalWidth / image.width;
    const scaleY = image.naturalHeight / image.height;
    canvas.width = crop.width;
    canvas.height = crop.height;
    const ctx = canvas.getContext("2d");

    ctx.drawImage(
      image,
      crop.x * scaleX,
      crop.y * scaleY,
      crop.width * scaleX,
      crop.height * scaleY,
      0,
      0,
      crop.width,
      crop.height
    );

    return new Promise((resolve, reject) => {
      canvas.toBlob(blob => {
        if (!blob) {
          //reject(new Error('Canvas is empty'));
          console.error("Canvas is empty");
          return;
        }
        blob.name = fileName;
        window.URL.revokeObjectURL(this.fileUrl);
        this.fileUrl = window.URL.createObjectURL(blob);
        resolve(this.fileUrl);
      }, "image/jpeg");
    });
  }

  render() {
    const { crop, croppedImageUrl, src } = this.state;

    return (
      <div className="App">
        <div>
          <input type="file" accept="image/*" onChange={this.onSelectFile} />
        </div>
        {src && (
          <ReactCrop
            src={src}
            crop={crop}
            ruleOfThirds
            onImageLoaded={this.onImageLoaded}
            onComplete={this.onCropComplete}
            onChange={this.onCropChange}
          />
        )}
        {croppedImageUrl && (
          <img alt="Crop" style={{ maxWidth: "100%" }} src={croppedImageUrl} />
        )}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));

在线编辑地址:https://codesandbox.io/s/react-image-crop-demo-with-classes-7jxc0?file=/src/index.js:0-2838

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

caperxi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值