npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

react-multi-cropper

v0.1.16-fabric

Published

A component for allowing multiple cropping regions on a single image, powered by [fabric](https://github.com/fabricjs/fabric.js).

Downloads

198

Readme

React Multi Cropper

A component for allowing multiple cropping regions on a single image, powered by fabric.

build version size downloads

WIP: Certain aspects are in development, and may be incomplete or buggy.
It should be fine for most purposes.

screenshot

Installation

yarn add react-multi-cropper fabric

Development

yarn install
yarn start # in one terminal
yarn serve # in another

Then open http://localhost:3000 in your browser.
If 3000 is occupied, the terminal output will show you what URL the serve command is serving on.

Usage

See the examples/index.tsx file.

Functionality

Draw rectangular regions on an image to obtain the selected area as a base64 encoded data URL.
Multiple regions can be obtained by drawing multiple boxes.

The component is responsive, so the image dimensions can use relative units (like %), and the cropping regions/rectangles should stay in place w.r.t. the image.

The cropping logic is aware of the device pixel ratio, so you won't get blurry crops on a MacBook or phone.

Documentation

Default Usage

const Cropper = ({ imageUrl }: { imageUrl: string ) => {
  const [boxes, setBoxes] = useState<CropperBox[]>([]);
  const [imageMap, setImageMap] = useState<CropperBoxDataMap>({});

  const updateBoxes = (_, __, _boxes) => setBoxes(_boxes);

  return (
    <div>
      <MultiCrops
        src={imageUrl}
        zoom={1}
        boxes={boxes}
        onChange={updateBoxes}
        onCrop={(e, map) => setImageMap(map)}
        onLoad={(map) => setImageMap(map)}
      />
      {boxes.map((box, i) =>
        !!imageMap[box.id] && <img src={imageMap[box.id]} key={i} />
      )}
    </div>
  );
};

How to reset zoom, rotation, and pan?

In examples/index.tsx, you'll see an implementation of reset.

const reset = () => {
  setRotation(0);
  setZoom(1);
  resetCenter();
};

setRotation, and setZoom are simple state setting functions obtained from a useState.
resetCenter needs a few more lines.
Note: Due to the current implementation, when resetting the component you must reset rotation before zoom to avoid bugs. It would be changed in the future to use a different update mechanism.

The second argument of onLoad provides the reset handler. To call this from anywhere, you may want to assign this to a ref.

// Initialize a ref to store the function
const resetCenterRef = useRef(() => {});
const resetCenter = resetCenterRef.current;

// Call function anywhere
resetCenter();

// Obtain the function from onLoad
onLoad={(map, reset) => {
  setImageMap(map);
  resetCenterRef.current = reset;
}}

Props for the MultiCrops component

type CropperProps = {
  cropperRef?: MutableRefObject<fabric.Canvas | null>;
  src: string;
  zoom?: number;
  rotation?: number; // degrees
  cropScale?: number; // the scale of the resultant cropped images
  boxes: CropperBox[];
  onChange?: UpdateFunction;
  onDelete?: UpdateFunction;
  onBoxMouseEnter?: UpdateFunction;
  onBoxMouseLeave?: UpdateFunction;
  onBoxClick?: UpdateFunction;
  onLoad?: ImgOnLoadWithImageData;
  onCrop?: CropTriggerFunctionWithImageData;
  onZoomGesture?: (newZoom: number) => any;
  containerClassName?: string;
  containerStyles?: CSSProperties;
  imageStyles?: CSSProperties;
  cursorMode?: CropperCursorMode;
  disableKeyboard?: boolean;
  disableMouse?: {
    all?: boolean;
    zoom?: boolean;
    pan?: boolean;
    draw?: boolean;
  };
  boxInView?: { id?: string; rotate?: boolean; panInView?: boolean };
};

All the above types have been exported from the module.

Notes:

  • The onLoad prop is optional, but useful for a few things.
    1. To determine that the image has indeed loaded, same as an img tag.
    2. Get access to the internal fabric object.
    3. To get a resetCenter handler to reset the panned position of the image.
  • You need to pass a function the onCrop prop if you want the default functionality to work out of the box. It will be called when a drawing operation was completed. This will be needed if you want to receive the image payload after a cropping action was done.
    • It is however optional, in case you want the box drawing to be controlled externally.
  • The function supplied to onCrop will be called when a drawing operation was completed. This will be needed if you want to receive the image payload after a cropping action was done.
    • The first argument is a CropperEvent event that tells you all you need to know about the event that was triggered to cause this function to fire.
    • The second argument is a dictionary of box.id's and their respective base64 encoded image contents.
  • Removed the ability to change a box after drawing it. The existing functionality was not stable enough to leave it, and leaving it in caused more issues than were manageable.
  • Mouse/Touchpad wheel to pan/zoom is supported. Example for wheel zoom is present in the examples/index.tsx.
  • Arrow Keys based pan/zoom is supported.
  • It would be advisable to memoize the functions passed to the component.
  • If you want to pass a box for reasons other than getting the imageData out of it, add the noImage: true key-val to it.