A simple straightforward customizable mobile-friendly image cropper for Vue 2.0.
A simple straightforward customizable mobile-friendly image cropper for Vue 2.0.
<croppa v-model="myCroppa"
:width="400"
:height="400"
:canvas-color="'default'"
:placeholder="'Choose an image'"
:placeholder-font-size="0"
:placeholder-color="'default'"
:accept="'image/*'"
:file-size-limit="0"
:quality="2"
:zoom-speed="3"
:disabled="false"
:disable-drag-and-drop="false"
:disable-click-to-choose="false"
:disable-drag-to-move="false"
:disable-scroll-to-zoom="false"
:disable-rotation="false"
:prevent-white-space="false"
:reverse-scroll-to-zoom="false"
:show-remove-button="true"
:remove-button-color="'red'"
:remove-button-size="0"
:initial-image="'path/to/initial-image.png'"
@init="handleCroppaInit"
@file-choose="handleCroppaFileChoose"
@file-size-exceed="handleCroppaFileSizeExceed"
@file-type-mismatch="handleCroppaFileTypeMismatch"
@new-image-drawn="handleNewImage"
@image-remove="handleImageRemove"
@move="handleCroppaMove"
@zoom="handleCroppaZoom"></croppa>
NOTE: This is an almost-full-use example. Usually you don’t need to specify so many props, because they all have default values. Most simply, you can even do:
<croppa v-model="myCroppa"></croppa>
this.myCroppa.remove();
this.myCroppa.zoomIn();
alert(this.myCroppa.generateDataUrl());
Using build tools:
npm install --save vue-croppa
import Vue from 'vue';
import Croppa from 'vue-croppa';
Vue.use(Croppa);
// If your build tool supports css module
import 'vue-croppa/dist/vue-croppa.css';
Not using build tools:
<link href="https://unpkg.com/vue-croppa/dist/vue-croppa.min.css" rel="stylesheet" type="text/css">
<script src="https://unpkg.com/vue-croppa/dist/vue-croppa.min.js"></script>
Vue.use(Croppa);
<croppa v-model="myCroppa"></croppa>
new Vue({
// ... other vm options omitted
data: {
myCroppa: {}
},
methods: {
uploadCroppedImage() {
this.myCroppa.generateBlob(
blob => {
// write code to upload the cropped image file (a file is a blob)
},
'image/jpeg',
0.8
); // 80% compressed jpeg file
}
}
});
Live example: https://jsfiddle.net/jdcvpvty/2/
import Vue from 'vue';
import Croppa from 'vue-croppa';
Vue.use(Croppa, { componentName: 'my-image-cropper' });
<my-image-cropper v-model="myCroppa"></my-image-cropper>
Croppa.component
. This is useful when you want to register the component by yourself manually.Vue.component('croppa', Croppa.component);
// Register async component (Webpack 2 + ES2015 Example). More about async component: https://vuejs.org/v2/guide/components.html#Async-Components
Vue.component('croppa', () => import(Croppa.component));
ref
both point to the same thing - the component itself. So you don’t need to set v-model anymore if you have a ref
on the component.<croppa ref="myCroppa"></croppa>
this.$refs.myCroppa.chooseFile();
this.$refs.myCroppa.generateDataUrl();
// ...
A two-way binding prop. It syncs an object from within the croppa component with a data in parent. We can use this object to call useful methods (Check out “Methods” section). Since v1.0.0, you don’t need this anymore, the ref
on component can also be used to call methods.
object
Display width of the preview container.
number
200
val > 0
Display height of the preview container.
number
200
val > 0
Placeholder text of the preview container. It shows up when there is no image.
string
'Choose an image'
Placeholder text color.
CanvasRenderingContext2D.fillStyle
accepts.'#606060'
Placeholder text font size in pixel. When set to 0
, the font size will be ajust automatically so that the whole placehoder only takes up 2/3 of the container’s width.
number
0
Initial background color and white space color if there is an image.
CanvasRenderingContext2D.fillStyle
accepts.'#e6e6e6'
; after v0.2.0 - 'transparent'
Specifies how many times larger the actual image is than the container’s display size.
number
2
val > 0
Specifies how fast the zoom is reacting to scroll gestures. Default to level 3.
number
3
val > 0
Limits the types of files that users can choose.
accept
attribute of HTML input
element takes.Limits the byte size of file that users can choose. If set to 0
, then no limit.
number
0
Disables user interaction.
boolean
false
Disables the default “drag and drop a file” user interaction. You can instead trigger the file chooser window programmatically by “click to choose” functionality or invoking chooseFile()
method.
boolean
false
Disables the default “click to choose a file” (“tab” on mobile) user interaction. You can instead trigger the file chooser window programmatically by “drag and drop” functionality or invoking chooseFile()
method.
boolean
false
Disables the default “drag to move” user interaction. You can instead move the image programmatically by invoking moveUpwards()
/ moveDownwards()
/ moveLeftwards()
/ moveRightwards()
methods.
boolean
false
Disables the default “scroll to zoom” user interaction. You can instead zoom the image programmatically by invoking zoomIn()
/ zoomOut()
methods.
boolean
false
Disables the default “pinch with two fingers to zoom” user interaction on mobile. You can instead zoom the image programmatically by invoking zoomIn()
/ zoomOut()
methods.
boolean
false
(v0.2.0+) Rotation methods won’t work if this is set to true
boolean
false
Deprecated Please use reverse-scroll-to-zoom
instead.
Reverses the zoom-in/zoom-out direction when scrolling.
boolean
false
Reverses the zoom-in/zoom-out direction when scrolling.
boolean
false
Prevents revealing background white space when moving or zooming the image.
boolean
false
Specifies whether to show the built-in remove-button. You can change the button’s color and size using the following two props. If you still find it ugly, hide it and use the remove()
method to implement your own trigger.
boolean
true
Changes the default color of the remove-button. Accepts any css color format.
string
'red'
Specifies the remove-button’s width and height (they are equal). If set to 0
, then it use the default size.
number
(v0.1.0+) Set initial image. You can pass a string as the url or an Image object (HTMLImageElement instance). This is an alternative way to set initial image besides using slot. Useful when you want to set cross origin image as initial image.
string
or object
(HTMLImageElement instance)undefined
(v0.2.0+) works similar to css’s background-size. It specifies the image’s size when it is first loaded on croppa. contain
and natural
won’t work if prevent-white-space
is set to true
.
string
'cover'
'cover'
, 'contain'
, 'natural'
(v0.2.0+) works similar to css’s background-position. It specifies the image’s position relative to croppa container when it is first loaded.
string
'center'
'center'
(default value)'top'
'bottom'
'left'
'right'
'top left'
, 'right top'
etc.)'30% 40%'
(similar to background-position in css)(v1.0.0+) to pass attributes to the hidden input[type=file]
element.
<croppa :input-attrs="{capture: true, class: 'file-input'}"></croppa>
(v1.1.0+) show default loading spinner at the bottom right corner of the container when image is loading (will but not yet be drawn on canvas).
boolean
false
(v1.1.0+) loading spinner’s size in px.
number
20
(v1.1.0+) loading spinner’s color in css color value formats.
string
'#606060'
(v1.1.4+) Replace current image on drag and drop.
boolean
false
(By default you need to remove the current image to drop a new one)(1.2.0) Switch to passive mode. Croppa in passive mode will sync state with another croppa if they v-model the same object. Also it will not have self-control - user can’t manipulate image on passive croppa. This is useful as a preview component.
These states will be synced:
[
'imgData',
'img',
'imgSet',
'originalImage',
'naturalHeight',
'naturalWidth',
'orientation',
'scaleRatio'
];
boolean
false
(1.2.0) Set rounded corders to image. Note that this has effect on the output image. Note that it only works when prevent-white-space
is true
. (Demo)
number
or string
0
\(1.3.0) If it is set to true
, width
and height
will not work. Instead, croppa will adjust itself to it’s container(.croppa-container
)'s size. It’s useful to make croppa’s dimension responsive.
boolean
false
(1.3.1) If it is set to true
, you can choose a video file. If the video is supported by the browser, the first frame will be drawn on the canvas. You can play/pause the video by dbclick croppa. This feature is not fully developed yet, but you can still play around with it.
boolean
false
<img>
node as a named slot initial
. For example:<croppa v-model="myCroppa">
<img slot="initial" :src="initialImageUrl" />
</croppa>
.refresh()
method after changing inital image.initial-image
prop, the slot will be the one that is used.<img>
slot named placeholder
to get an image placeholder! The image will be draw on croppa under the placeholder text.<croppa v-model="myCroppa">
<img slot="placeholder" src="static/placeholder-image.png" />
</croppa>
position: absolute
on these slots or it will expand the container.{ width, height }
describing the real image size (preview size * quality
)this.myCroppa.outputWidth
and this.myCroppa.outputHeight
instead.remove()
instead.type
parameter (defaults to png).compressionRate
(v0.2.0+) defaults to 1
, you can pass a number between 0 and 1 to get a compressed output image.null
.Promise
wrapping around generateBlob()
, so that you can use async/await
syntax instead of a callback to get blob data, it’s simpler.const blob = await this.myCroppa.promisedBlob()
null
.var metadata = this.myCroppa.getMetadata();
console.log(metadata);
/* in console
{
startX:-535.5180530546083,
startY:-358.0699623303261,
scale:2.2502626424905396,
orientation:6
}
*/
metadata
can have one or more of these 4 properties: startX
, startY
, scale
, orientation
. Usually you will use the object returned by getMetadata()
.var metadata = {
startX: -535.5180530546083,
startY: -358.0699623303261,
scale: 2.2502626424905396,
orientation: 6
};
this.myCroppa.applyMetadata(metadata);
// Add a clip plugin to make a circle clip on image
onInit(vm) {
this.croppa.addClipPlugin(function (ctx, x, y, w, h) {
/*
* ctx: canvas context
* x: start point (top-left corner) x coordination
* y: start point (top-left corner) y coordination
* w: croppa width
* h: croppa height
*/
ctx.beginPath()
ctx.arc(x + w / 2, y + h / 2, w / 2, 0, 2 * Math.PI, true)
ctx.closePath()
})
},
ctx.beginPath()
and end with ctx.closePath()
.prevent-white-space
is true
.{
basic: true, // supports basic functionality
dnd: false // does not support drag and drop
}
croppa
is the croppa component itself - same as what v-model
and ref
bind.file
is a file object - same as what getChosenFile()
returns.file
is a file object - same as what getChosenFile()
returns.accept
.file
is a file object - same as what getChosenFile()
returns.ctx
is the CanvasRenderingContext2D
object for you to draw anything you want on the current image. You can also get it with the method getContext()
.initial-image
prop.Since v1.0.0, you can access all state data of croppa via the instance. For example,
this.myCroppa.naturalWidth;
this.myCroppa.imgData.startX;
this.myCroppa.scaleRatio;
this.myCroppa.pinching;
//...
All data available:
Sorry I’m too lazy to doc about each of them. Please open the vue-devtool to figure out what they mean by yourself.
You can also open an issue to ask me any question about this component.
Note that “computed” and “props” are read-only. Some value on “data” are also not recommended to modify from outside, for example ctx
, canvas
, img
.
loading
indicates whether an image is loading (will but not yet be drawn on canvas).$ cd vue-croppa
$ npm install
$ cd docs
$ npm install
# under vue-croppa/
$ npm run dev
# under vue-croppa/docs/
$ npm run dev
Edit file ./docs/simple-test.html
and open http://localhost:3000/simple-test.html to test while developing.
# under vue-croppa/
$ npm run build
auto-size=true
#122