Render image editor dialog in Vue Image Editor component

19 Jul 202314 minutes to read

Image Editor is rendered within a dialog and opens an image by passing its URL path to the open method of the Image Editor component.

The following operations are supported in the Image Editor:

  • Selection : Multiple selection options are available. The selection region can be a square or circle, customized to various aspect ratios, and customized by dragging and resizing.
  • Crop : The image can be cropped based on the selection.
  • Rotate : The image can be rotated both clockwise and anticlockwise by 90 degrees.
<template>
    <div class="control-section e-img-editor-canvas">
        <div class='e-profile e-hide'>
            <div class="e-custom-wrapper">
                <canvas id='img-canvas'></canvas>
                <img alt="img" id="custom-img"  v-on:load="imageLoad" crossorigin="anonymous" src="images/profile.png"
                style="display: none;"/>
                <input type="file" id="img-upload" style="display:none" v-on:change="fileChanged" accept="image/*"/>
                <span id="custom-edit" class="e-custom-edit" v-on:click="editClicked">
                    <span class="e-custom-icon sb-icons"></span>
                </span>
            </div>
        </div>
        <div id='profile-dialog' class="e-img-editor-profile">
            <ejs-dialog id="componentsDialog" :position="position" :closeOnEscape=true :open="dlgOpened" :buttons='dlgButtons' ref="dialogObj" :header='header' :animationSettings='animationSettings' :content='imageEditorTemplate' showCloseIcon=true :target='target' width='340px' height="400px" :visible= false>
        </ejs-dialog>
        </div>
    </div>
</template>



<script>
import Vue from "vue";
import { ImageEditorPlugin } from "@syncfusion/ej2-vue-image-editor";
import { DialogPlugin } from '@syncfusion/ej2-vue-popups';
import { getComponent, createElement } from "@syncfusion/ej2-base";
Vue.use(DialogPlugin);

Vue.use(ImageEditorPlugin);

export default Vue.extend({
  data: function() {
    return {
        target: '.sb-desktop-wrapper',
        header: 'Profile',
	    imgSrc: '',
        position: {X: 'center', Y: 100},
	    imgSrc: '',
        dlgButtons: [
            { click: this.dlgOpenBtnClick, buttonModel: { content: 'Open', cssClass: 'e-custom-img-btn e-img-custom-open' } },
            { click: this.dlgResetBtnClick, buttonModel: { content: 'Reset', cssClass: 'e-custom-img-btn e-img-custom-reset' } },
            { click: this.dlgRotateBtnClick, buttonModel: { content: 'Rotate', cssClass: 'e-custom-img-btn e-img-custom-rotate' } },
            { click: this.dlgDoneBtnClick, buttonModel: { content: 'Apply', isPrimary: true, cssClass: 'e-custom-img-btn e-img-custom-apply' } }
        ],
        animationSettings: { effect: 'None' },
        imageEditorTemplate: function() {
            return {
                template: Vue.component('ImageEditorComponent', {
                    theme: 'Bootstrap5',
                    template: '<ejs-imageeditor :theme="themeValue" id="image-editor" :created="created" :fileOpened="fileOpened" :toolbar=[]></ejs-imageeditor>',
                    methods: {
                        fileOpened: function() {
                            let imgEditor = getComponent(document.getElementById('image-editor'), 'image-editor');
                            imgEditor.select('circle');
                        },
                        created: function() {
                            if (this.themeValue && window.location.href.split('#')[1]) {
                                this.themeValue = window.location.href.split('#')[1].split('/')[1];
                            } 
                        }
                    },
                    computed: {
                        themeValue: {
                            get: function () {
                                return this.theme;
                            },
                            set: function (theme) {
                                this.theme = theme
                            }
                        }
                    }
                })
            }
        }		
    };
  },
   methods: {
        imageLoad: function() {
	    if (this.imgSrc === '') {
		    let canvas = document.querySelector('#img-canvas');
		    let image = document.querySelector('#custom-img');
		    let ctx = canvas.getContext('2d');
		    canvas.width = image.width < image.height ? image.width : image.height; 
		    canvas.height = canvas.width;
		    ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
		    document.querySelector('.e-profile').classList.remove('e-hide');
	     }
        },
        dlgOpened: function() {
            let image = document.querySelector('#custom-img');
            let imgEditor = getComponent(document.getElementById('image-editor'), 'image-editor');
            imgEditor.open(image.src);
        },
        editClicked: function() {
            this.$refs.dialogObj.show();
        },
        dlgOpenBtnClick: function() {
            document.getElementById('img-upload').click();
        },
        dlgResetBtnClick: function() {
            let imgEditor = getComponent(document.getElementById('image-editor'), 'image-editor');
            imgEditor.reset();
        },
        dlgRotateBtnClick: function() {
            let imgEditor = getComponent(document.getElementById('image-editor'), 'image-editor');
            imgEditor.rotate(-90);
        },
        dlgDoneBtnClick: function() {
            let imgEditor = getComponent(document.getElementById('image-editor'), 'image-editor');
            imgEditor.crop();
            let croppedData = imgEditor.getImageData();
            let canvas = document.querySelector('#img-canvas');
            let ctx = canvas.getContext('2d');
            let parentDiv = document.querySelector('.e-profile');
            let tempCanvas = parentDiv.appendChild(createElement('canvas'));
            let tempContext = tempCanvas.getContext('2d');
            tempCanvas.width = croppedData.width; tempCanvas.height = croppedData.height;
            tempContext.putImageData(croppedData, 0, 0);
            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.drawImage(tempCanvas, 0, 0, canvas.width, canvas.height);
            tempCanvas.remove();
            parentDiv.style.borderRadius = '100%'; canvas.style.backgroundColor = '#fff';
            this.$refs.dialogObj.hide();
            if (this.imgSrc !== '') {
            const img = document.querySelector('#custom-img');
            img.src = this.imgSrc;
            }
        },
        fileChanged: function(args) {
            const URL = window.URL; const url = URL.createObjectURL((args.target).files[0]);
            const imageEditor = getComponent(document.getElementById('image-editor'), 'image-editor');
            imageEditor.open(url.toString());
            document.getElementById('img-upload').value = null;
	        this.imgSrc = url.toString();
        }
    }
});
</script>