Vue Cropper JS

vue-cropperjs is a Vue wrapper component for cropperjs, which is image cropper.

Basic example

Advanced JavaScript image cropper.

Source Image
px
px
px
px
deg
							
                                
<template>
    <div class="row">
        <div class="col-md-8">
        <div class="img-container">
            <vue-cropper
            ref="cropper"
            :guides="true"
            :view-mode="viewmodeselected"
            drag-mode="crop"
            :aspect-ratio="16 / 9"
            :auto-crop-area="0.5"
            :min-container-width="10"
            :min-container-height="10"
            :background="true"
            :rotatable="true"
            :movable="true"
            :src="CropperImg"
            alt="Source Image"
            :ready="ready"
            :crop="cropImage"
            :img-style="{ width: '800px', height: '500px' }"
            preview=".img-preview"
            >
            </vue-cropper>
        </div>
        </div>
        <div class="col-md-4">
        <div class="docs-preview clearfix">
            <div class="img-preview preview-lg"></div>
            <div class="img-preview preview-md"></div>
            <div class="img-preview preview-sm"></div>
            <div class="img-preview preview-xs"></div>
        </div>
        <div class="docs-data">
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataX">X</label>
            <input 
                type="text" 
                class="form-control" 
                id="dataX" 
                placeholder="x" 
                :value="imageData.x" />
            <span class="input-group-text">px</span>
            </div>
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataY">Y</label>
            <input 
                type="text" 
                class="form-control" 
                id="dataY" 
                placeholder="y" 
                :value="imageData.y" />
            <span class="input-group-text">px</span>
            </div>
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataWidth">Width</label>
            <input
                type="text"
                class="form-control"
                id="dataWidth"
                placeholder="width"
                :value="imageData.width"
            />
            <span class="input-group-text">px</span>
            </div>
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataHeight">Height</label>
            <input
                type="text"
                class="form-control"
                id="dataHeight"
                placeholder="height"
                :value="imageData.height"
            />
            <span class="input-group-text">px</span>
            </div>
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataRotate">Rotate</label>
            <input
                type="text"
                class="form-control"
                id="dataRotate"
                placeholder="rotate"
                :value="imageData.rotate"
            />
            <span class="input-group-text">deg</span>
            </div>
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataScaleX">ScaleX</label>
            <input
                type="text"
                class="form-control"
                id="dataScaleX"
                placeholder="scaleX"
                :value="imageData.scaleX"
            />
            </div>
            <div class="input-group input-group-sm">
            <label class="input-group-text" for="dataScaleY">ScaleY</label>
            <input
                type="text"
                class="form-control"
                id="dataScaleY"
                placeholder="scaleY"
                :value="imageData.scaleY"
            />
            </div>
        </div>
        </div>
    </div>
    <div class="row mt-4" id="actions">
        <div class="col-md-8 docs-buttons">
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="setDragMode"
            data-option="move"
            title="Move"
            id="move"
            v-on:click="moveImage"
            >
            <span title='cropper.setDragMode("move")'>
                <span class="fa fa-arrows"></span>
            </span>
            </button>
            <button
            class="btn btn-primary br-right"
            type="button"
            data-method="setDragMode"
            data-option="crop"
            title="Crop"
            id="crop"
            v-on:click="cropImage"
        >
            <span class="fa fa-crop"></span>
        </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="zoom"
            data-option="0.1"
            title="Zoom In"
            v-on:click="zoom(0.1)"
            >
            <span title="cropper.zoom(0.1)">
                <span class="fa fa-search-plus"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="zoom"
            data-option="-0.1"
            title="Zoom Out"
            v-on:click="zoom(-0.1)"
            >
            <span title="cropper.zoom(-0.1)">
                <span class="fa fa-search-minus"></span>
            </span>
            </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="move"
            data-option="-10"
            data-second-option="0"
            title="Move Left"
            v-on:click="moveImageLeft"
            >
            <span title="cropper.move(-10, 0)">
                <span class="fa fa-arrow-left"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="move"
            data-option="10"
            data-second-option="0"
            title="Move Right"
            v-on:click="moveImageRight"
            >
            <span title="cropper.move(10, 0)">
                <span class="fa fa-arrow-right"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="move"
            data-option="0"
            data-second-option="-10"
            title="Move Up"
            v-on:click="moveImageUp"
            >
            <span title="cropper.move(0, -10)">
                <span class="fa fa-arrow-up"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="move"
            data-option="0"
            data-second-option="10"
            title="Move Down"
            v-on:click="moveImageDown"
            >
            <span title="cropper.move(0, 10)">
                <span class="fa fa-arrow-down"></span>
            </span>
            </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="rotate"
            data-option="-45"
            title="Rotate Left"
            v-on:click="rotateLeft"
            >
            <span title="cropper.rotate(-45)">
                <span class="fa fa-undo"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="rotate"
            data-option="45"
            title="Rotate Right"
            v-on:click="rotateRight"
            >
            <span title="cropper.rotate(45)">
                <span class="fa fa-rotate-right"></span>
            </span>
            </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="scaleX"
            data-option="-1"
            title="Flip Horizontal"
            v-on:click="fliphorizontal"
            >
            <span title="cropper.scaleX(-1)">
                <span class="fa fa-arrows-h"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="scaleY"
            data-option="-1"
            title="Flip Vertical"
            v-on:click="flipvertical"
            >
            <span title="cropper.scaleY(-1)">
                <span class="fa fa-arrows-v"></span>
            </span>
            </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="crop"
            title="Crop"
            >
            <span title="cropper.crop()">
                <span class="fa fa-check"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="clear"
            title="Clear"
            v-on:click="clear"
            >
            <span title="cropper.clear()">
                <span class="fa fa-remove"></span>
            </span>
            </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="disable"
            title="Disable"
            v-on:click="disable"
            >
            <span title="cropper.disable()">
                <span class="fa fa-lock"></span>
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="enable"
            title="Enable"
            v-on:click="enable"
            >
            <span title="cropper.enable()">
                <span class="fa fa-unlock"></span>
            </span>
            </button>
        </div>
        <div class="btn-group">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="reset"
            title="Reset"
            v-on:click="reset"
            >
            <span title="cropper.reset()">
                <span class="fa fa-refresh"></span>
            </span>
            </button>
            <label
            class="btn btn-primary btn-upload mb-0"
            data-toggle="tooltip"
            data-placement="top"
            for="inputImage"
            title="Upload image file"
            >
            <input
                type="file"
                class="sr-only"
                id="inputImage"
                name="file"
                accept="image/*"
                @change="setImage"
            />
            <span title="Import image with Blob URLs">
                <span class="fa fa-upload"></span>
            </span>
            </label>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            data-method="destroy"
            title="Destroy"
            v-on:click="destroy"
            >
            <span title="cropper.destroy()">
                <span class="fa fa-power-off"></span>
            </span>
            </button>
        </div>
        <div class="btn-group btn-group-crop">
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="getCroppedCanvas"
            data-method="getCroppedCanvas"
            data-bs-toggle="modal" data-bs-target="#getCroppedCanvasModal"
            v-on:click="getCroppedCanvas"
            >
            <span title="cropper.getCroppedCanvas()"> Get Cropped Canvas </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getCroppedCanvas({ width: 160, height: 90 })"
            data-method="getCroppedCanvas"
            data-option='{ "width": 160, "height": 90 }'
            data-bs-toggle="modal" data-bs-target="#getCroppedCanvasModal"
            v-on:click="getCroppedCanvas16090"
            >
            <span title="cropper.getCroppedCanvas({ width: 160, height: 90 })">
                160&times;90
            </span>
            </button>
            <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getCroppedCanvas({ width: 320, height: 180 })"
            data-method="getCroppedCanvas"
            data-option='{ "width": 320, "height": 180 }'
            data-bs-toggle="modal" data-bs-target="#getCroppedCanvasModal"
            v-on:click="getCroppedCanvas320180"
            >
            <span title="cropper.getCroppedCanvas({ width: 320, height: 180 })">
                320&times;180
            </span>
            </button>
        </div>
        <div
            class="modal fade docs-cropped"
            id="getCroppedCanvasModal"
            role="dialog"
            aria-hidden="true"
            aria-labelledby="getCroppedCanvasTitle"
            tabindex="-1"
        >
            <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                <h5 class="modal-title" id="getCroppedCanvasTitle">Cropped</h5>
                <button
                    type="button"
                    class="btn-close"
                    data-bs-dismiss="modal"
                    aria-hidden="true"
                >
                    &times;
                </button>
                </div>
                <div class="modal-body">
                <img :src="croppedImg" ></img>
                </div>
                <div class="modal-footer">
                <a
                    class="btn btn-primary"
                    id="download"
                    :href="croppedImg"
                    download="cropped.jpeg"
                    >Download</a
                >
                </div>
            </div>
            </div>
        </div>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getData()"
            data-method="getData"
            data-option
            data-target="#putData"
            v-on:click="getCropperdata"
        >
            <span title="cropper.getData()"> Get Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.setData(data)"
            data-method="setData"
            data-target="#putData"
            v-on:click="setData"
        >
            <span title="cropper.setData(data)"> Set Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getContainerData()"
            data-method="getContainerData"
            data-option
            data-target="#putData"
            v-on:click="getContainerdata"
        >
            <span title="cropper.getContainerData()"> Get Container Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getImageData()"
            data-method="getImageData"
            data-option
            data-target="#putData"
            v-on:click="getImagedata"
        >
            <span title="cropper.getImageData()"> Get Image Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getCanvasData()"
            data-method="getCanvasData"
            data-option
            data-target="#putData"
            v-on:click="getCanvasData"
        >
            <span title="cropper.getCanvasData()"> Get Canvas Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.setCanvasData(data)"
            data-method="setCanvasData"
            data-target="#putData"
            v-on:click="setCanvasData"
        >
            <span title="cropper.setCanvasData(data)"> Set Canvas Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.getCropBoxData()"
            data-method="getCropBoxData"
            data-option
            data-target="#putData"
            v-on:click="getCropBoxData"
        >
            <span title="cropper.getCropBoxData()"> Get Crop Box Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.setCropBoxData(data)"
            data-method="setCropBoxData"
            data-target="#putData"
            v-on:click="setCropBoxData"
        >
            <span title="cropper.setCropBoxData(data)"> Set Crop Box Data </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.moveTo(0)"
            data-method="moveTo"
            data-option="0"
            v-on:click="moveImageTo"
        >
            <span title="cropper.moveTo(0)"> 0,0 </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.zoomTo(1)"
            data-method="zoomTo"
            data-option="1"
            v-on:click="zoom100"
        >
            <span title="cropper.zoomTo(1)"> 100% </span>
        </button>
        <button
            type="button"
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="cropper.rotateTo(180)"
            data-method="rotateTo"
            data-option="180"
            v-on:click="rotate180"
        >
            <span title="cropper.rotateTo(180)"> 180° </span>
        </button>
        <input
            type="text"
            class="form-control mt-3"
            id="putData"
            v-model="putData"
            placeholder="Get data to here or set data with this value"
        />
        </div>
        <div class="col-md-4 docs-toggles">
        <div class="btn-group docs-aspect-ratios" data-toggle="buttons">
            <label
            class="btn btn-primary active"
            data-toggle="tooltip"
            data-placement="top"
            title="aspectRatio: 16 / 9"
            >
            <input
                type="radio"
                class="sr-only"
                id="aspectRatio1"
                name="aspectRatio"
                value="1.7777777777777777"
                v-on:click="setAspectRatio(16 / 9)"
            />
            <span title="aspectRatio: 16 / 9"> 16:9 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="aspectRatio: 4 / 3"
            >
            <input
                type="radio"
                class="sr-only"
                id="aspectRatio2"
                name="aspectRatio"
                value="1.3333333333333333"
                v-on:click="setAspectRatio(4 / 3)"
            />
            <span title="aspectRatio: 4 / 3"> 4:3 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="aspectRatio: 1 / 1"
            >
            <input
                type="radio"
                class="sr-only"
                id="aspectRatio3"
                name="aspectRatio"
                value="1"
                v-on:click="setAspectRatio(1 / 1)"
            />
            <span title="aspectRatio: 1 / 1"> 1:1 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="aspectRatio: 2 / 3"
            >
            <input
                type="radio"
                class="sr-only"
                id="aspectRatio4"
                name="aspectRatio"
                value="0.6666666666666666"
                v-on:click="setAspectRatio(2/3)"
            />
            <span title="aspectRatio: 2 / 3"> 2:3 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="aspectRatio: NaN"
            >
            <input
                type="radio"
                class="sr-only"
                id="aspectRatio5"
                name="aspectRatio"
                value="NaN"
                v-on:click="setAspectRatio(NaN)"
            />
            <span title="aspectRatio: NaN"> Free </span>
            </label>
        </div>
        <div class="btn-group docs-view-modes" data-toggle="buttons">
            <label
            class="btn btn-primary active"
            data-toggle="tooltip"
            data-placement="top"
            title="getCroppedCanvas"
            >
            <input
                type="radio"
                class="sr-only"
                id="viewMode0"
                name="viewMode"
                value="0"
                checked
            />
            <span title="View Mode 0"> VM0 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="View Mode 31"
            >
            <input
                type="radio"
                class="sr-only"
                id="viewMode1"
                name="viewMode"
                value="1"
            />
            <span title="View Mode 1"> VM1 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="View Mode 2"
            >
            <input
                type="radio"
                class="sr-only"
                id="viewMode2"
                name="viewMode"
                value="2"
            />
            <span title="View Mode 2"> VM2 </span>
            </label>
            <label
            class="btn btn-primary"
            data-toggle="tooltip"
            data-placement="top"
            title="View Mode 3"
            >
            <input
                type="radio"
                class="sr-only"
                id="viewMode3"
                name="viewMode"
                value="3"
            />
            <span title="View Mode 3"> VM3 </span>
            </label>
        </div>
        </div>
    </div>
</template>

<script>
import VueCropper from 'vue-cropperjs';
import 'cropperjs/dist/cropper.css';

export default {
  components: {
    VueCropper,
  },
  data() {
    return {
      myimgSrc: "cropper.jpg",
      imgSrc: "",
      imageData: "",
      containerData: "",
      putData: "",
      viewmodeselected: 0,
      cropImg: "",
      croppedImg: "",
    };
  },
  methods: {
    getImgUrl() {
        var images = require.context("@/assets/img/", false, /.jpg$/);
        return images("./" + this.myimgSrc);
    },
    ready() {
        this.containerData = this.$refs.cropper.getContainerData();
    },
    cropImage() {
        this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL();
        this.imageData = this.$refs.cropper.getData();
    },
    moveImage() {
        this.$refs.cropper.move(1);
    },
    zoom(percent) {
        this.$refs.cropper.relativeZoom(percent);
    },
    zoom100() {
        this.$refs.cropper.zoomTo(1);
    },
    moveImageLeft() {
        this.$refs.cropper.move(-10, 0);
    },
    moveImageRight() {
        this.$refs.cropper.move(10, 0);
    },
    moveImageUp() {
        this.$refs.cropper.move(0, 10);
    },
    moveImageDown() {
        this.$refs.cropper.move(0, -10);
    },
    moveImageTo() {
        this.$refs.cropper.moveTo(0);
    },
    rotateLeft() {
        this.$refs.cropper.rotate(-45);
    },
    rotateRight() {
        this.$refs.cropper.rotate(45);
    },
    rotate180() {
        this.$refs.cropper.rotateTo(180);
    },
    fliphorizontal() {
        if (this.imageData.scaleX === 1) {
            this.$refs.cropper.scale(-1, 1);
        } else {
            this.$refs.cropper.scale(1, 1);
        }
    },
    flipvertical() {
        if (this.imageData.scaleY === 1) {
            this.$refs.cropper.scale(1, -1);
        } else {
            this.$refs.cropper.scale(1, 1);
        }
    },
    scaleImage() {
        this.$refs.cropper.scale(-2, -1);
    },
    clear() {
        this.$refs.cropper.clear();
    },
    disable() {
        this.$refs.cropper.disable();
    },
    enable() {
        this.$refs.cropper.enable();
    },
    reset() {
        this.$refs.cropper.reset();
    },
    destroy() {
        this.$refs.cropper.destroy();
    },
    setImage(e) {
        const file = e.target.files[0];

        if (file.type.indexOf("image/") === -1) {
            alert("Please select an image file");
            return;
        }

        if (typeof FileReader === "function") {
            const reader = new FileReader();

            reader.onload = (event) => {
                this.imgSrc = event.target.result;
                // rebuild cropperjs with the updated source
                this.$refs.cropper.replace(event.target.result);
            };

            reader.readAsDataURL(file);
        } else {
            alert("Sorry, FileReader API not supported");
        }
    },
    getCroppedCanvas() {
        this.croppedImg = this.$refs.cropper.getCroppedCanvas().toDataURL();
    },
    getCroppedCanvas16090() {
        this.croppedImg = this.$refs.cropper.getCroppedCanvas({ width: 160, height: 90 }).toDataURL();
    },
    getCroppedCanvas320180() {
        this.croppedImg = this.$refs.cropper.getCroppedCanvas({ width: 320, height: 180 }).toDataURL();
    },
    getCropperdata() {
        var data = this.$refs.cropper.getData();
        this.putData =
            '{"x":' +
            data.x +
            ',"y":' +
            data.y +
            ',"width":' +
            data.width +
            ',"height":' +
            data.height +
            ',"rotate":' +
            data.rotate +
            ',"scaleX":' +
            data.scaleX +
            ',"scaleY":' +
            data.scaleY +
            "}";
    },
    setData() {
        if (!this.putData) return;
        this.$refs.cropper.setData(JSON.parse(this.putData));
    },
    getContainerdata() {
        var data = this.$refs.cropper.getContainerData();
        this.putData =
            '{"width":' + data.width + ',"height":' + data.height + "}";
    },
    getImagedata() {
        var data = this.$refs.cropper.getImageData();
        this.putData =
            '{"naturalWidth":' +
            data.naturalWidth +
            ',"naturalHeight":' +
            data.naturalHeight +
            ',"aspectRatio":' +
            data.aspectRatio +
            ',"width":' +
            data.width +
            ',"height":' +
            data.height +
            ',"left":' +
            data.left +
            ',"top":' +
            data.top +
            "}";
    },
    getCanvasData() {
        var data = this.$refs.cropper.getCanvasData();
        this.putData =
            '{"left":' +
            data.left +
            ',"top":' +
            data.top +
            ',"width":' +
            data.width +
            ',"height":' +
            data.height +
            ',"naturalWidth":' +
            data.naturalWidth +
            ',"naturalHeight":' +
            data.naturalHeight +
            "}";
    },
    setCanvasData() {
        if (!this.putData) return;
        this.$refs.cropper.setCanvasData(JSON.parse(this.putData));
    },
    getCropBoxData() {
        var data = this.$refs.cropper.getCropBoxData();
        this.putData =
            '{"left":' +
            data.left +
            ',"top":' +
            data.top +
            ',"width":' +
            data.width +
            ',"height":' +
            data.height +
            "}";
    },
    setCropBoxData() {
        if (!this.putData) return;

        this.$refs.cropper.setCropBoxData(JSON.parse(this.putData));
    },

    //setAspectRatio
    setAspectRatio(aspectRatio) {
        this.$refs.cropper.setAspectRatio(aspectRatio);
    },
  },
};
</script>