Cropper react assembly component used theme

- recent project with react, react and learn to use cropper assembly crop the picture.

(Here is not unified development components useful for tsx (TypeScript + xml / html) writing components useful jsx (javascript + xml / html) write components

Preface: cropper component into the project in hand along a direct look at the official documentation; GitHub: https://github.com/fengyuanchen/cropperjs#methods   online demo url:  https://fengyuanchen.github.io/cropper/

1.cropper simple assembly and packaging of various operations.

  react-cropper.js file

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Cropper from 'cropperjs';

const optionProps = [
  'dragMode',
  'aspectRatio',
  'data',
  'crop',
  // unchangeable props start from here
  'viewMode',
  'preview',
  'responsive',
  'restore',
  'checkCrossOrigin',
  'checkOrientation',
  'modal',
  'guides',
  'center',
  'highlight',
  'background',
  'autoCrop',
  'autoCropArea',
  'movable',
  'rotatable',
  'scalable',
  'zoomable',
  'zoomOnTouch',
  'zoomOnWheel',
  'wheelZoomRatio',
  'cropBoxMovable',
  'cropBoxResizable',
  'toggleDragModeOnDblclick',
  'minContainerWidth',
  'minContainerHeight',
  'minCanvasWidth',
  'minCropBoxWidth',
  'minCanvasHeight',
  'minCropBoxHeight',
  'ready',
  'cropstart',
  'cropmove',
  'cropend',
  'zoom',
];

const unchangeableProps = optionProps;

class ReactCropper extends Component {
  componentDidMount() {
    const options = Object.keys(this.props)
      .filter(propKey => optionProps.indexOf(propKey) !== -1)
      .reduce((prevOptions, propKey) =>
        Object.assign({}, prevOptions, { [propKey]: this.props[propKey] }), {});
    this.cropper = new Cropper(this.img, options);

  }
  
  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.src !== this.props.src) {
      this.cropper.reset().clear().replace(nextProps.src);
    }
    if (nextProps.aspectRatio !== this.props.aspectRatio) {
      this.setAspectRatio(nextProps.aspectRatio);
    }
    if (nextProps.data !== this.props.data) {
      this.setData(nextProps.data);
    }
    if (nextProps.dragMode !== this.props.dragMode) {
      this.setDragMode(nextProps.dragMode);
    }
    if (nextProps.cropBoxData !== this.props.cropBoxData) {
      this.setCropBoxData(nextProps.cropBoxData);
    }
    if (nextProps.canvasData !== this.props.canvasData) {
      this.setCanvasData(nextProps.canvasData);
    }
    if (nextProps.moveTo !== this.props.moveTo) {
      if (nextProps.moveTo.length > 1) {
        this.moveTo(nextProps.moveTo[0], nextProps.moveTo[1]);
      } else {
        this.moveTo(nextProps.moveTo[0]);
      }
    }
    if (nextProps.zoomTo !== this.props.zoomTo) {
      this.zoomTo(nextProps.zoomTo);
    }
    if (nextProps.rotateTo !== this.props.rotateTo) {
      this.rotateTo(nextProps.rotateTo);
    }
    if (nextProps.scaleX !== this.props.scaleX) {
      this.scaleX(nextProps.scaleX);
    }
    if (nextProps.scaleY !== this.props.scaleY) {
      this.scaleY(nextProps.scaleY);
    }
    if (nextProps.enable !== this.props.enable) {
      if (nextProps.enable) {
        this.enable();
      } else {
        this.disable();
      }
    }

    Object.keys(nextProps).forEach((propKey) => {
      let isDifferentVal = nextProps[propKey] !== this.props[propKey];
      const isUnchangeableProps = unchangeableProps.indexOf(propKey) !== -1;

      if (typeof nextProps[propKey] === 'function' && typeof this.props[propKey] === 'function') {
        isDifferentVal = nextProps[propKey].toString() !== this.props[propKey].toString();
      }

      if (isDifferentVal && isUnchangeableProps) {
        throw new Error(`prop: ${propKey} can't be change after componentDidMount`);
      }
    });
  }

  componentWillUnmount() {
    if (this.img) {
      // Destroy the cropper, this makes sure events such as resize are cleaned up and do not leak
      this.cropper.destroy();
      delete this.img;
      delete this.cropper;
    }
  }

  setDragMode(mode) {
    return this.cropper.setDragMode(mode);
  }

  setAspectRatio(aspectRatio) {
    return this.cropper.setAspectRatio(aspectRatio);
  }

  getCroppedCanvas(options) {
    return this.cropper.getCroppedCanvas(options);
  }

  setCropBoxData(data) {
    return this.cropper.setCropBoxData(data);
  }

  getCropBoxData() {
    return this.cropper.getCropBoxData();
  }

  setCanvasData(data) {
    return this.cropper.setCanvasData(data);
  }

  getCanvasData() {
    return this.cropper.getCanvasData();
  }

  getImageData() {
    return this.cropper.getImageData();
  }

  getContainerData() {
    return this.cropper.getContainerData();
  }

  setData(data) {
    return this.cropper.setData(data);
  }

  getData(rounded) {
    return this.cropper.getData(rounded);
  }

  crop() {
    return this.cropper.crop();
  }

  move(offsetX, offsetY) {
    return this.cropper.move(offsetX, offsetY);
  }

  moveTo(x, y) {
    return this.cropper.moveTo(x, y);
  }

  zoom(ratio) {
    return this.cropper.zoom(ratio);
  }

  zoomTo(ratio) {
    return this.cropper.zoomTo(ratio);
  }

  rotate(degree) {
    return this.cropper.rotate(degree);
  }

  rotateTo(degree) {
    return this.cropper.rotateTo(degree);
  }

  enable() {
    return this.cropper.enable();
  }

  disable() {
    return this.cropper.disable();
  }

  reset() {
    return this.cropper.reset();
  }

  clear() {
    return this.cropper.clear();
  }

  replace(url, onlyColorChanged) {
    return this.cropper.replace(url, onlyColorChanged);
  }

  scale(scaleX, scaleY) {
    return this.cropper.scale(scaleX, scaleY);
  }

  scaleX(scaleX) {
    return this.cropper.scaleX(scaleX);
  }

  scaleY(scaleY) {
    return this.cropper.scaleY(scaleY);
  }

  render() {
    const {
      src,
      alt,
      crossOrigin,
      style,
      className,
    } = this.props;

    return (
      <div
        style={style}
        className={className}
      >
        <img
          crossOrigin={crossOrigin}
          ref={(img) => { this.img = img; }}
          src={src}
          alt={alt === undefined ? 'picture' : alt}
          style={{ opacity: 0 }}
        />
      </div>
    );
  }
}

ReactCropper.propTypes = {
  style: PropTypes.object, // eslint-disable-line react/forbid-prop-types
  className: PropTypes.string,

  // react cropper options
  crossOrigin: PropTypes.string,
  src: PropTypes.string,
  alt: PropTypes.string,

  // props of option can be changed after componentDidmount
  aspectRatio: PropTypes.number,
  dragMode: PropTypes.oneOf(['crop', 'move', 'none']),
  data: PropTypes.shape({
    x: PropTypes.number,
    y: PropTypes.number,
    width: PropTypes.number,
    height: PropTypes.number,
    rotate: PropTypes.number,
    scaleX: PropTypes.number,
    scaleY: PropTypes.number,
  }),
  scaleX: PropTypes.number,
  scaleY: PropTypes.number,
  enable: PropTypes.bool,
  cropBoxData: PropTypes.shape({
    left: PropTypes.number,
    top: PropTypes.number,
    width: PropTypes.number,
    height: PropTypes.number,
  }),
  canvasData: PropTypes.shape({
    left: PropTypes.number,
    top: PropTypes.number,
    width: PropTypes.number,
    height: PropTypes.number,
  }),
  zoomTo: PropTypes.number,
  moveTo: PropTypes.arrayOf(PropTypes.number),
  rotateTo: PropTypes.number,

  // cropperjs options
  // https://github.com/fengyuanchen/cropperjs#options
  AspectRatio //, dragMode, data 
  viewMode: PropTypes.oneOf([0, 1, 2, 3]),
  preview: PropTypes.string, 
  Responsive: PropTypes.bool, 
  restore: PropTypes.bool, 
  checkCrossOrigin: PropTypes.bool, 
  checkOrientation: PropTypes.bool, 
  modal: PropTypes.bool, 
  guides: PropTypes.bool, 
  center : PropTypes.bool, 
  highlight: PropTypes.bool, 
  background: PropTypes.bool, 
  autoCrop: PropTypes.bool, 
  autoCropArea: PropTypes.number, 
  movable: PropTypes.bool, 
  rotatable: PropTypes.bool, 
  scalable: PropTypes.bool, 
  zoomable: PropTypes .bool, 
  zoomOnTouch: PropTypes.bool, 
  zoomOnWheel: PropTypes.bool, 
  wheelZoomRatio: PropTypes.number, 
  cropBoxMovable: PropTypes.bool, 
  cropBoxResizable: PropTypes.bool,
  toggleDragModeOnDblclick: PropTypes.bool,
  minContainerWidth: PropTypes.number,
  minContainerHeight: PropTypes.number,
  minCanvasWidth: PropTypes.number,
  minCanvasHeight: PropTypes.number,
  minCropBoxWidth: PropTypes.number,
  minCropBoxHeight: PropTypes.number,
  ready: PropTypes.func,
  cropstart: PropTypes.func,
  cropmove: PropTypes.func,
  cropend: PropTypes.func,
  crop: PropTypes.func,
  zoom: PropTypes.func,
};

ReactCropper.defaultProps = {
  src: null,
  dragMode: 'crop',
  data: null,
  scaleX: 1,
  scaleY: 1,
  enable: true,
  zoomTo: 1,
  rotateTo: 0,
};

export default ReactCropper;

 

Simple calling component package 2.cropper

CropperView.jsx file

import React, { Component, useEffect } from 'react';
import $ from "jquery";
import Cropper from './cropper/react-cropper'
import 'cropperjs/dist/cropper.css'

/* global FileReader */
var showCropArea = true;

export default class CropperView extends Component {

  constructor(props) {
    super(props);
    this.state = {
      cropResult: null,
    };
    // this.cropper = this;
    this.onChange = this.onChange.bind(this);
    this.src = props.src;
  }

  // componentDidMount(){
  //   useEffect(() => {
  //     alert("cropZone" + this.cropper);
  //     // if (typeof this.cropper.getCroppedCanvas() === 'undefined') {
  //     //   return;
  //     // }
  //     alert("left:" + this.cropper.getCropBoxData().left
  //         + "top:" + this.cropper.getCropBoxData().top
  //         + "width:" + this.cropper.getCropBoxData().width
  //         + "height:" + this.cropper.getCropBoxData().height);
  //       }, [this.props.save]);
  // }

  onChange(e) {
    e.preventDefault();
    let files;
    if (e.dataTransfer) {
      files = e.dataTransfer.files;
    } else if (e.target) {
      files = e.target.files;
    }
    const reader = new FileReader();
    reader.onload = () => {
      this.setState({ src: reader.result });
    };
    reader.readAsDataURL(files[0]);
  }

  cropZone() {
    if (typeof this.cropper.getCroppedCanvas() === 'undefined') {
      return;
    }
    alert("left:" + this.cropper.getCropBoxData().left
        + "top:" + this.cropper.getCropBoxData().top
        + "width:" + this.cropper.getCropBoxData().width
        + "height:" + this.cropper.getCropBoxData().height);
        $(".cropper-crop-box").hide();
        $(".cropper-drag-box").hide();
        $(".cropper-wrap-box").append(
          "<div style=\"width:" + this.cropper.getCropBoxData().width + ";"
          + "height:" + this.cropper.getCropBoxData().height + ";"
          + "background:#0000FF; opacity:0.3"
          + "position:absolute; left:" + this.cropper.getCropBoxData().left +";"
          + "top:" + this.cropper.getCropBoxData().top + ";\">"); 
  }

  showCropZone() {
    if (showCropArea) {
      $(".cropper-crop-box").css("display", "block");
      $(".cropper-drag-box").css("display", "block");
    } else {
      $(".cropper-crop-box").hide();
      $(".cropper-drag-box").hide();
    }
  }

  creatCrop(){
    this.cropper.crop();
  }

  clearCrop(){
    this.cropper.clear();
  }

  resetCrop(){
    this.cropper.reset();
  }

  moveLeft(){
    this.cropper.move(-5, 0);
  }

  moveRight(){
    this.cropper.move(5, 0);
  }

  moveUp(){
    console.log("====moveUp===");
    try {
      this.cropper.move(0, -5);
    }catch (err){
        console.log(err);
    }
  }

  moveDown(){
    this.cropper.move(0, 5);
  }

  enlarge(){
    try {
      // 放大
      // this.cropper.zoom(0.1);
      var allCanvasDate = this.cropper.getCanvasData();
      var newCanvasDate = {left:allCanvasDate.left, top: allCanvasDate.top,
        width: allCanvasDate.width*2, height: allCanvasDate.height*2}

      this.cropper.setCanvasData(newCanvasDate);
     

    }catch (err){
        console.log(err);
    }
  
  }

  shrink(){
    try {
      // 缩小
      // this.cropper.zoom(-0.1)
      var allCanvasDate = this.cropper.getCanvasData();
      var newCanvasDate = {left:allCanvasDate.left, top: allCanvasDate.top,
        width: allCanvasDate.width*0.5, height: allCanvasDate.height*0.5}

      this.cropper.setCanvasData(newCanvasDate);
    }catch (err){
        console.log(err);
    }
  }

  test(){
    try {
      var allDate = this.cropper.getData(true);
      alert(allDate.toString());
      var par = {x:allDate.x, y:allDate.y, width:allDate.width*2, height:allDate.height*2,
        rotate:allDate.rotate, scaleX:allDate.scaleX, scaleY:allDate.scaleY}
        
      this.cropper.setData(par);
    }catch (err){
        console.log(err);
    }
  }

  moveCrop(){
    //this.cropper.movecrop();
    console.log("===move===crop===");
  }

  reduceCrop(){
    var par = {left:this.cropper.getCropBoxData().left, top:this.cropper.getCropBoxData().top,
      width:this.cropper.getCropBoxData().width*0.8, height:this.cropper.getCropBoxData().height*0.8}
    this.cropper.setCropBoxData(par);
  }

  raiseCrop(){
    var par = {left:this.cropper.getCropBoxData().left, top:this.cropper.getCropBoxData().top,
      width:this.cropper.getCropBoxData().width*1.2, height:this.cropper.getCropBoxData().height*1.2}
    this.cropper.setCropBoxData(par);
  }

  CropLeft(){
    var par = {left:this.cropper.getCropBoxData().left - 10, top:this.cropper.getCropBoxData().top,
      width:this.cropper.getCropBoxData().width, height:this.cropper.getCropBoxData().height}
    this.cropper.setCropBoxData(par);
  }

  CropRight(){
    var par = {left:this.cropper.getCropBoxData().left + 10, top:this.cropper.getCropBoxData().top,
      width:this.cropper.getCropBoxData().width, height:this.cropper.getCropBoxData().height}
    this.cropper.setCropBoxData(par);
  }

  CropUp(){
    var par = {left:this.cropper.getCropBoxData().left, top:this.cropper.getCropBoxData().top - 10,
      width:this.cropper.getCropBoxData().width, height:this.cropper.getCropBoxData().height}
    this.cropper.setCropBoxData(par);
  }

  CropDown(){
    var par = {left:this.cropper.getCropBoxData().left, top:this.cropper.getCropBoxData().top + 10,
      width:this.cropper.getCropBoxData().width, height:this.cropper.getCropBoxData().height}
    this.cropper.setCropBoxData(par);
  }

  render() {
    return (
      <div className="r-view" style={{ position:'absolute', left:'185px', top:"83px" }}>
        <Cropper
          style={{ height:'100%', width:'auto' }}
          aspectRatio={16 / 9}
          preview=".img-preview"
          guides={false}
          src={this.props.src}
          viewMode={2}
          minContainerWidth={585}
          minContainerHeight={430}
          ref={cropper => { this.cropper = cropper; }}
          zoomable={true}
          zoomOnTouch={true}
        />
      </div>
    );
  }
}

3.cropper components and bind a variety of button operation (reason: the device does not support the operation and to enlarge the picture of the finger in the selection area reduction operation), page integration component.

  CropperScreen.tsx file

import * as React from 'react';
import styled from "styled-components";
import useTranslate from "../../hooks/useTranslate";
import CropView from "./CropperView";
import 'cropperjs/dist/cropper.css'

import FormView from "./FormView"

const AppStyle = styled.div`
  background: #CCC;
`;

var showCropArea = false;

export default function CropperScreen() {
    const t = useTranslate();

    const handleBackClicked = () => {
        $("#viewable").show();
        $("#scan_settings_id").css("display","none");
    };

    const doCropClicked = () => {
        // showCropArea = !showCropArea;
        // if (showCropArea) {
        //     alert("disabled false");
        //     $("#btn_save_crop").removeAttr("disabled");
        // } else {
        //     alert("disabled true");
        //     $("#btn_save_crop").attr("disabled", "true");
        // }
        // cropUser.showCropZone(showCropArea);

        cropUser.clearCrop();
        
    };

    const doSaveCropClicked = () => {
        cropUser.cropZone();
    };

    const handReset = () => {
        cropUser.resetCrop();
        cropUser.creatCrop();
    }

    const handMoveLeft = () => {
        cropUser.moveLeft();
    }

    const handMoveRight = () => {
        cropUser.moveRight();
    }

    const handMoveUp = () => {
        console.log("====handMoveUp===");
        try {
            cropUser.moveUp();
        }catch (err){
            console.log(err);
        }
    }

    const handMoveDown = () => {
        cropUser.moveDown();
    }

    const handMoveCrop = () => {
        alert("unknow");
        cropUser.moveCrop();
    }

    const handReduceCrop = () => {
        cropUser.reduceCrop();
    }

    const handRaiseCrop = () => {
        cropUser.raiseCrop()
    }

    const handEnlarge = () => {
        cropUser.enlarge();
    }

    const handShrink = () => {
        cropUser.shrink();
    }

    const handCropLeft = () => {
        cropUser.CropLeft()
    }

    const handCropRight = () => {
        cropUser.CropRight()
    }

    const handCropUp = () => {
        cropUser.CropUp()
    }

    const handCropDown = () => {
        cropUser.CropDown()
    }

    const handTest = () => {
        cropUser.test()
    }

    const handleSubmit = () => {
        alert("====handleSubmit====");
        console.log(formUser);
        
        console.log(formUser.state);
    }

    let maxItem = 2;
    let cropUser
    let formUser
    var initValue = {name:'tom',job: '12'}

    return (
        <AppStyle id="scan_settings_id" className="r-view" style={{display:"none", height:"470px"}}>
            <header className="r-titlebar">
                <a href="#" className="r-titlebar__back" onClick={handleBackClicked} />
                <h1 className="r-titlebar__title">Preview</h1>
            </header>
            <div style={{position:"absolute", left:35}}>
            </div>
            <CropView ref={cropView => {cropUser = cropView}} src={require('../smartsdk-css/img/test.png')}/>
            <div className="r-floating-island">
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={doCropClicked}>Crop</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={doSaveCropClicked}>Save</button>
                </div>
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={handReset}>reset</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={handMoveCrop}>mcrop</button>
                </div>
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={handMoveLeft}>left</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={handMoveRight}>right</button>
                </div>
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={handMoveUp}>up</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={handMoveDown}>down</button>
                </div>
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handEnlarge}>+</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handShrink}>-</button>
                </div>
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handReduceCrop}>reduce</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handRaiseCrop}>raise</button>
                </div>

                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handCropLeft}>cropr</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handCropRight}>cropl</button>
                </div>

                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handCropUp}>cropu</button>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handCropDown}>cropd</button>
                </div>
                <div>
                    <button style={{width:'70px', height:'35px', marginLeft:'5px'}} onClick={ handTest}>test</button>
                </div>
                
               
                {/* <FormView handleSubmit={handleSubmit} ref={formView => {formUser = formView}} props = {initValue}/> */}
                
                {/* <button className="r-start-button">
                    {t("dapi:cba.common.start")}
                </button> */}
            </div>
        </AppStyle >
    );
}

4. Finally call the whole assembly, page display

page

 

Guess you like

Origin www.cnblogs.com/wang-liang-blogs/p/12576023.html