Advanced Cropper

The flexible Vue cropper component that gives you the opportunity to create almost any cropper that you desire. Identically easy to use and customize.
npm install -S vue-advanced-cropper
yarn / npm

Features

Fully Customisable
Customise almost any aspect of the cropper component, or use it right out of the box.
Mobile Support
Vue Advanced Cropper supports desktop and mobile devices alike. Built in support for touch events, cropper resizing, etc.
Canvas / Coordinates
This Cropper can be used to create a canvas with a cropped area or just coordinates relative to the original image to crop it server-side in the future.
Advanced Features
Set minimum and maximum aspect ratios, customize minimum and maximum height and width, etc.

Minimum Example

After you have installed the cropper, it's very easy to integrate it in your website. The minimum working example of the cropper is presented below.

<template>
	<cropper
		:src="img"
		@change="change"
	/>
</template>

<script>
import { Cropper } from 'vue-advanced-cropper';
import 'vue-advanced-cropper/dist/style.css';

export default {
	components: {
		Cropper,
	},
	data() {
		return {
			img: 'https://images.pexels.com/photos/4323307/pexels-photo-4323307.jpeg',
		};
	},
	methods: {
		change({ coordinates, canvas }) {
			console.log(coordinates, canvas);
		},
	},
};
</script>

Concepts

The goal of this library to give developers an opportunity create any cropper component easily and effortless. To achieve this goal, the cropper is divided into two main parts: the broadly customizable cropper and the arbitrary component stencil.

What is the cropper?

Cropper is the root component of this library. It contains the coordinates of the currently cropped area (left, top, width, height) relative to the original image coordinates. These coordinates can be imagined like a box. That's responsible for:

  • resizing and moving the box
  • displaying the cropped image and fitting it to the container
  • setting default coordinates
  • cropping canvas area

What is the stencil?

The Cropper operates the abstract box that represents the currently cropped area, but it only abstracts a couple of coordinates. Visualizing the cropped area and giving the user the ability to interact with the cropper is what the stencil component is used for.

The Stencil can literally be any arbitrary component, but in order for it to make sense there are some requirements:

  • it should be inscibed to box is represented by coordinates (width, height, left, top)
  • if the stencil has aspect ratios it should have an aspectRatios method to inform the cropper resize algorithm (this method should return an object with minimum and maximum aspect ratio values)
  • it should emit resize and move events
  • it should display the cropped part of a image

Resize and move events are very flexible and allow you to create almost any moving and especially resizng logic (more details here)

The typical stencil components are represented below. They include handlers that emit resize events, a movable area that emits move events, and a cropped image preview.

There are default customizable components out of the box that allow you to create your first cropper component within five minutes.

<script>
import { StencilPreview, BoundingBox, DraggableArea } from 'vue-advanced-cropper';

export default {
	components: {
		StencilPreview,
		BoundingBox,
		DraggableArea,
	},
	props: [
		// Image object
		'image',
		// Actual coordinates of the cropped fragment
		'coordinates',
		// Stencil size desired by cropper
		'stencilCoordinates',
		// Aspect ratios
		'aspectRatio',
		'minAspectRatio',
		'maxAspectRatio',
		// Transitions:
		'transitions'
	],
	computed: {
		style() {
			const { height, width, left, top } = this.stencilCoordinates;
			const style = {
				position: 'absolute',
				width: `${width}px`,
				height: `${height}px`,
				transform: `translate(${left}px, ${top}px)`,
			};
			if (this.transitions && this.transitions.enabled) {
				style.transition = `${this.transitions.time}ms ${this.transitions.timingFunction}`;
			}
			return style;
		},
	},
	methods: {
		onMove(moveEvent) {
			this.$emit('move', moveEvent);
		},
		onMoveEnd() {
			this.$emit('moveEnd');
		},
		onResize(resizeEvent) {
			this.$emit('resize', resizeEvent);
		},
		onResizeEnd() {
			this.$emit('resizeEnd');
		},
		aspectRatios() {
			return {
				minimum: this.aspectRatio || this.minAspectRatio,
				maximum: this.aspectRatio || this.maxAspectRatio,
			};
		},
	},
};
</script>

<template>
	<div :style="style">
		<bounding-box @resize="onResize" @resize-end="onMoveEnd">
			<draggable-area @move="onMove" @move-end="onMoveEnd">
				<stencil-preview
					:image="image"
					:width="stencilCoordinates.width"
					:height="stencilCoordinates.height"
					:coordinates="coordinates"
					:transitions="transitions"
				/>
			</draggable-area>
		</bounding-box>
	</div>
</template>

That’s pretty much all you need to know to get started. Below there are a couple different stencil examples to show what you can create.