AngularJs directive for Image Cropping

Whenever we are allowing a user to upload images, it's better to provide cropping option for them. So, today we will discuss about the AngularJs directive which allows users to crop image before saving it.

For that you need to use JQuery's JCrop plugIn in your project. You can download it from https://github.com/tapmodo/Jcrop . Download the zip from the above link and add jquery.jcrop.js and jquery.jcrop.css files to your project.

<script src="scripts/jquery.min.js" type="text/javascript">
</script>
<script src="scripts/jquery.Jcrop.js" type="text/javascript">
</script>

<link href="css/jquery.Jcrop.css" rel="stylesheet" type="text/css">

Now add the following angularjs directive in your javascript file
app.directive('imgCropped'function () {
    return {
        restrict: 'E',
        replace: true,
        scope: { src: '@', selected: '&' },
        link: function (scope, element, attr) {
            var myImg;
            var clear = function () {
                if (myImg) {
                    myImg.next().remove();
                    myImg.remove();
                    myImg = undefined;
                }
            };
 
            scope.$watch('src'function (nv) {
                clear();
                if (nv) {
                    element.after('<img />');
                    myImg = element.next();
                    myImg.attr('src', nv);
                    $(myImg).Jcrop({
                        trackDocument: true,
                        onSelect: function (x) {
                            scope.$apply(function () {
                                scope.selected({ cords: x });
                            });
                        },
                        aspectRatio: 1
                    }, function () {
                        // Use the API to get the real image size 
                        var bounds = this.getBounds();
                        boundx = bounds[0];
                        boundy = bounds[1];
                    });
                }
            });
            scope.$on('$destroy', clear);
        }
    };
});

Now add the following html code in body section
<div ng-controller="MainCtrl">
    <img-cropped src='http://deepliquid.com/Jcrop/demos/demo_files/pool.jpg' selected='selected(cords)'></img-cropped>
    <div ng-show="cropped" id="cropped-image-container">
        <img id="preview" src='http://deepliquid.com/Jcrop/demos/demo_files/pool.jpg'>
    </div>
</div>
add the following custom styles to your style sheet
div#cropped-image {
    height150px;
    width150px;
    overflowhidden;
}

In the above HTML we are using a image to crop and a div which contains the cropped image. So, if we start cropping the original image, the new cropped image is showed in the div. (see this plnkr for live example: angularjs directive for image cropping )

Now add the following controller to your javascript file
app.controller('MainCtrl'function ($scope) {
    $scope.selected = function (cords) {
        $scope.cropped = true;
        var rx = 150 / cords.w;
        var ry = 150 / cords.h;
        $('#preview').css({
            width: Math.round(rx * boundx) + 'px',
            height: Math.round(ry * boundy) + 'px',
            marginLeft: '-' + Math.round(rx * cords.x) + 'px',
            marginTop: '-' + Math.round(ry * cords.y) + 'px'
        });
    };
});

When a user crops the image, the "selected" function inside the "MainCtrl" gets called which gets the cropped image's co-ordinates. Now using that co-ordinates we are applying css styles to the preview image(which is in the second div).

That's it. Here JCrop doesnot creates a new image , instead it just gives you the cropped image's co-ordinates. Using that co-ordinates you have to change the css of the image. See this stackoverflow question for more details about saving the cropped image to database. save cropped image - jcrop

Hope it helps you. Happy coding :-) :-)

For more articles on AngularJs visit: AngularJs


3 comments:

  1. hi, just want to ask how would you use the coordinates to create a new image? Thanks, having a hard time figuring that one out

    ReplyDelete
  2. Hi.. i too had the hard time to know :-). later i came to know that, jcrop wont creates a new image. it just gives you the co.ordinates. we just need to save those co.ordinates in our DB table(along with original image). and while showing the image we have to apply css dynamically(through javascript). here i am posting my code. look at how i applied css dynamically.

    <img id="profile-picture" src="url of the image" />

    javascript to apply css:(add this code after fetching data from db)

    $('#profile-picture').css({
    width: $scope.model.profileImage.width,
    height: $scope.model.profileImage.height,
    marginLeft: $scope.model.profileImage.marginLeft,
    marginTop: $scope.model.profileImage.marginTop,
    });

    i am storing width, height, marginLeft and marginRight in DB table. so i am applying these four css properties to image.
    please let me know if you have any other doubts.

    ReplyDelete
  3. can it crop with fix rectangle size?

    ReplyDelete