在angularjs的jrcrop图像裁剪插件中将较大的图像缩小到较小的图像

问题描述 投票:0回答:1

我正在使用angularjs中的jrCrop插件尝试使用cordova的相机插件和裁剪图像捕获图像。

cordova和jrCrop插件的相机插件都可以很好地裁剪图像并存储在文件系统中。

问题在于,当比jCrop显示图像的容器裁剪更小的图像时有预览,但是当较大的图像用于裁剪时,则它不适合预览显示。

原始图片(截图 - 1)

大图像的问题(截图 - 2)

我想成为(截图 - 3)

有没有任何方法或解决方案可以缩小较大的图像以适应jrCrop的预览显示。

初始化的jCrop插件:

$jrCrop.crop({  
    url: imageSrc, //get image path from camera plugin
    width: $scope.imgWidth,
    height: $scope.imgHeight,
}).then(function(canvas){
    UserImages.tmpImage=canvas.toDataURL();
    $location.path('/crop-image');
});  

代码:jrCrop.js

angular.module('ionic')

.factory('$jrCrop', [
    '$ionicModal',
    '$rootScope',
    '$q',
    function($ionicModal, $rootScope, $q) {

        var template = '<div class="jr-crop modal" ng-style="{height: heightGap + \'px\'}" style="min-height:50px;" >' +
                '<div class="jr-crop-title fmed-reg">Pinch to zoom in/out <br> Position photo with your finger</div>' +
                '<div class="jr-crop-center-container">' +
                  '<div class="jr-crop-img" ng-style="{width: width + \'px\', height: height + \'px\'}"></div>' +
                '</div>' +
                '<div class="jr-crop-center-container"  style="opacity:0.5; background:#fff;border:1px solid #000;" >' +
                  '<div class="jr-crop-select" style="overflow: hidden;" ng-style="{width: width + \'px\', height: height + \'px\'}"></div>' +
                '</div>' +
                '<div class="bar bar-footer bar-dark jr-crop-footer">' +
                  '<button class="button button-clear fmed-reg jr-choose" ng-click="cancel()">Cancel</button>' +
                  '<div class="title">{{title}}</div>' +
                  '<button class="button button-clear fmed-reg jr-choose" ng-click="crop()">Choose</button>' +
                '</div>' +
              '</div>';

        var jrCropController = ionic.views.View.inherit({
            promise: null,
            imgWidth: null,
            imgHeight: null,

            // Elements that hold the cropped version and the full
            // overlaying image.
            imgSelect: null,
            imgFull: null,

            // Values exposed by scaling and moving. Needed
            // to calculate the result of cropped image
            posX: 0,
            posY: 0,
            scale: 1,

            initialize: function(options) {
                var self = this;

                this.options = options;
                this.promise = $q.defer();
                this.loadImage().then(function(elem) {
                self.imgWidth = elem.naturalWidth;
                self.imgHeight = elem.naturalHeight;

                self.options.modal.el.querySelector('.jr-crop-img').appendChild(self.imgSelect = elem.cloneNode());
                self.options.modal.el.querySelector('.jr-crop-select').appendChild(self.imgFull = elem.cloneNode());

                self.bindHandlers();            
            });

        // options === scope. Expose actions for modal.
        this.options.cancel = this.cancel.bind(this);
        this.options.crop = this.crop.bind(this);
    },

    cancel: function() {
        var self = this;

        this.options.modal.remove().then(function() {
            self.promise.reject('canceled');
        });
    },

    /**
        * This is where the magic happens
    */
    bindHandlers: function() {
        var self = this,

        last_scale,
        last_posX = 0, last_posY = 0,
        min_pos_x = 0, min_pos_y = 0,
        max_pos_x = 0, max_pos_y = 0,
        transforming_correctX = 0, transforming_correctY = 0,

        scaleMin,
        image_ratio = self.imgWidth / self.imgHeight,
        cropper_ratio = self.options.width / self.options.height;

        if (cropper_ratio < image_ratio) {
            scaleMin = self.options.height / self.imgHeight;
        } else {
            scaleMin = self.options.width / self.imgWidth;
        }

    function setPosWithinBoundaries() {
        calcMaxPos();
        if (self.posX > min_pos_x) {
            self.posX = min_pos_x;
        }
        if (self.posX < max_pos_x) {
            self.posX = max_pos_x;
        }
        if (self.posY > min_pos_y) {
            self.posY = min_pos_y;
        }
        if (self.posY < max_pos_y) {
            self.posY = max_pos_y;
        }
    }

    /**
        * Calculate the minimum and maximum positions.
        * This took some headaches to write, good luck
        * figuring this out.
    */

    function calcMaxPos() {
        // Calculate current proportions of the image.
        var currWidth = self.scale * self.imgWidth;
        var currHeight = self.scale * self.imgHeight;

        // Images are scaled from the center
        min_pos_x = (currWidth - self.imgWidth) / 2;
        min_pos_y = (currHeight - self.imgHeight) / 2;
        max_pos_x = -(currWidth - min_pos_x - self.options.width);
        max_pos_y = -(currHeight - min_pos_y - self.options.height);
    }

    // Based on: http://stackoverflow.com/questions/18011099/pinch-to-zoom-using-hammer-js

    ionic.onGesture('touch transform drag dragstart dragend', function(e) {
        switch (e.type) {
            case 'touch':
                last_scale = self.scale;
                break;
            case 'drag':
                self.posX = last_posX + e.gesture.deltaX - transforming_correctX;
                self.posY = last_posY + e.gesture.deltaY - transforming_correctY;
                setPosWithinBoundaries();
                break;
            case 'transform':
                self.scale = Math.max(scaleMin, Math.min(last_scale * e.gesture.scale, 10));
                setPosWithinBoundaries();
                break;
            case 'dragend':
                last_posX = self.posX;
                last_posY = self.posY;
        $(".jr-crop-select").show();
                break;
            case 'dragstart':
                last_scale = self.scale;

                // After scaling, hammerjs needs time to reset the deltaX and deltaY values,
                // when the user drags the image before this is done the image will jump.
                // This is an attempt to fix that.
                if (e.gesture.deltaX > 1 || e.gesture.deltaX < -1) {
                    transforming_correctX = e.gesture.deltaX;
                    transforming_correctY = e.gesture.deltaY;
                } else {
                    transforming_correctX = 0;
                    transforming_correctY = 0;
                }
                break;
        }

        var transform ='translate3d(' + self.posX + 'px,' + self.posY + 'px, 0) ' +'scale3d(' + self.scale + ',' + self.scale + ', 0)';

            self.imgSelect.style[ionic.CSS.TRANSFORM] = transform;
            self.imgFull.style[ionic.CSS.TRANSFORM] = transform;

        }, self.options.modal.el);

    },

    /**
        * Calculate the new image from the values calculated by
        * user input. Return a canvas-object with the image on it.
        * 
        * Note: It doesn't actually downsize the image, it only returns
        * a cropped version. Since there's inconsistenties in image-quality
        * when downsizing it's up to the developer to implement this. Preferably
        * on the server.
    */
    crop: function() {
        var canvas = document.createElement('canvas');
        var context = canvas.getContext('2d');

        // Canvas size is original proportions but scaled down.
        canvas.width = this.options.width / this.scale;
        canvas.height = this.options.height / this.scale;

        // The full proportions 
        var currWidth = this.imgWidth * this.scale;
        var currHeight = this.imgHeight * this.scale;

        // Because the top/left position doesn't take the scale of the image in
        // we need to correct this value.
        var correctX = (currWidth - this.imgWidth) / 2;
        var correctY = (currHeight - this.imgHeight) / 2;

        var sourceX = (this.posX - correctX) / this.scale;
        var sourceY = (this.posY - correctY) / this.scale;

        context.drawImage(this.imgFull, sourceX, sourceY);

        this.options.modal.remove();
        this.promise.resolve(canvas);
    },

    /**
        * Load the image and return the element.
        * Return Promise that will fail when unable to load image.
    */
    loadImage: function() {
        var promise = $q.defer();

        // Load the image and resolve with the DOM node when done.
        angular.element('<img />')
        .bind('load', function(e) {
            promise.resolve(this);
        })
        .bind('error', promise.reject)
        .prop('src', this.options.url);

    //this.options.heightGap=200;
        // Return the promise
        return promise.promise;
      }
    });

    return {
        crop: function(options) {
            var scope = $rootScope.$new(true);

            ionic.Utils.extend(scope, options);

            scope.modal = $ionicModal.fromTemplate(template, {
            scope: scope
        });

        // Show modal and initialize cropper.
        return scope.modal.show().then(function() {
        return (new jrCropController(scope)).promise.promise;
    });
   }
  };
}]);
android angularjs cordova jcrop ionic
1个回答
0
投票

问题解决与这些插件jr-Crop的官方更新。

© www.soinside.com 2019 - 2024. All rights reserved.