如何修复这个 AngularJS JCrop 指令?

Posted

技术标签:

【中文标题】如何修复这个 AngularJS JCrop 指令?【英文标题】:how to fix this AngularJS JCrop directive? 【发布时间】:2013-01-24 15:03:45 【问题描述】:

我正在尝试将 JCrop 与 AngularJS 一起使用。我有以下指令需要帮助来修复一下:

.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) 
                            /*if (!scope.$$phase) 
                                scope.$apply(function() 
                                    scope.selected(cords: x);
                                );
                            */
                            scope.selected(cords: x);
                        ,
                        aspectRatio: 1,
                        boxWidth: 400, boxHeight: 400,
                        setSelect: [0, 0, 400, 400]
                    );
                
            );

            scope.$on('$destroy', clear);
        
    ;
)

问题是 JCrop 没有正确检测到真实的图像大小,我需要添加一个 trueSize 选项,我知道如何做的唯一方法是将 Jcrop 调用包装在回调中,看起来很讨厌。

另外,如果我在 onSelect 回调中使用 scope.$apply,我会收到 $digest already in progress 错误。这是为什么呢?

编辑:我可以使用以下代码成功获得真实的图像大小,但必须有更好的方法来做到这一点

.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);

                    var temp = new Image();
                    temp.src = nv;
                    temp.onload = function() 
                        var width = this.width;
                        var height = this.height;

                        $(myImg).Jcrop(
                            trackDocument: true,
                            onSelect: function(x) 
                                /*if (!scope.$$phase) 
                                 scope.$apply(function() 
                                 scope.selected(cords: x);
                                 );
                                 */
                                scope.selected(cords: x);
                            ,
                            aspectRatio: 1,
                            boxWidth: 400, boxHeight: 400,
                            setSelect: [0, 0, 400, 400],
                            trueSize: [width, height]
                        );
                    
                
            );

            scope.$on('$destroy', clear);
        
    ;
)

【问题讨论】:

你有什么不工作的 plunker 或 jsfiddle 吗?我实际上是在 Angular 中使用 JCrop,但不是这样。我的 img src 没有改变,所以我只是在 img 标签上使用属性指令。 我创建了一个 plunkr - plnkr.co/edit/phXrGBxpPY7DZjkQmGXd - 在 plunkr 中它工作得很好(我故意放了一个巨大的图像)。在我的应用程序中它不起作用并且检测到错误的图像尺寸。是否有可能某些 css 规则正在为图像设置样式并导致此问题? CSS 规则不应影响 Image 对象加载图像的方式。 我想我不明白你的问题。最初你的问题是“有没有更好的方法来做到这一点?”而你正在使用一个 DOM 元素......我回答了。现在问题包括我的答案,但仍在询问是否有更好的方法来做到这一点?因为你不喜欢嵌套回调?你的问题到底是什么? 我的问题是,在 plunkr 中它似乎工作正常(没有临时图像)并且 JCrop 正在检测正确的图像大小。但是当我在我的应用程序中使用它时,检测到错误的图像大小,我需要使用该临时图像。是什么原因造成的? 【参考方案1】:

你正在做的可能没问题。该指令看起来不错。至于获取图像大小,您可以使用直接的 javascript 来完成,如下所示:

var img = new Image();
img.onload = function () 
   var w = img.width,
       h = img.height;
   //do what you need to do here.
;
img.src = 'somefile.gif';

它将为您节省 DOM 操作。

【讨论】:

这是我在问题的编辑部分添加的内容。将 JCrop 语句放在回调中看起来很丑 嘿...好吧,欢迎使用 JavaScript。您始终可以将回调函数分解为自己的声明,而不是嵌套匿名函数。不过我给你的一个提示是:你在指令的 scope.src 上有一个监视,但你从不更新它,你用单向绑定“@”而不是双向绑定“填充它” ="。需要注意的事项。 这就是我要说的......你实际上是以一种奇怪的方式这样做......而不是 src="image"src: "@" ,你可以这样做 src="image"src: "=" .我想任何一种方式都有效,只要你从不试图将改变推回另一个方向。【参考方案2】:

我正在制定一项指令,我将推动凉亭(经过多​​次修复):

angular-image-crop

working demo

在构造函数回调中,我调用this.getBounds(),然后将这些值应用到onSelect 中的cords

https://github.com/coolaj86/angular-image-crop/blob/master/app/scripts/controllers/profile-pic.js#L24

【讨论】:

以上是关于如何修复这个 AngularJS JCrop 指令?的主要内容,如果未能解决你的问题,请参考以下文章

angularJS中如何写自定义指令

angularJS中如何写自定义指令

Angularjs +如何在指令中获取先前的输入字段值

AngularJS指令包含范围=假?

如何在我的angularjs指令中切换属性的值,如contenteditable?

AngularJS无法将表单输入输入指令