【问题标题】:jCrop (jQuery) sometimes fails to load image/cropper areajCrop (jQuery) 有时无法加载图像/裁剪区域
【发布时间】:2011-08-21 16:29:29
【问题描述】:

我遇到了一个非常简单的问题,但我对导致问题的原因一无所知。在我的一个应用程序中,我使用 jCrop 作为一个小插件来裁剪图像以适应横幅/标题等。将采取以下步骤:

1) Select an image (using CKFinder for this, CKFinder returns the image path to an input field)
2) Click a button to load the image
3) Crop the image
4) Save the image

在大约 75% 的情况下,一切都按计划进行,但在其他 25% 的情况下,jCrop 无法加载裁剪区域并将其留空。这是我正在使用的 jQuery 代码:

jQuery('#selectimg').live('click', function(e) { 
  e.preventDefault();
  var newsrc = jQuery('#img2').val();
  jQuery('#cropbox').attr('src', newsrc);
  var jcrop_api = jQuery.Jcrop('#cropbox', {
    boxWidth: 700, 
    boxHeight: 700,
    onSelect: updateCoords,
    onChange: updateCoords
  });
  //Some other JS code come's here for buttons (they work all the time)
});

我注意到,当我将#cropbox 正在被转换的部分放在可裁剪区域中时,图像加载得很好,所以错误在于var = jcrop_api 部分,但我慢慢开始认为那里没有办法解决这个问题...

这是我迄今为止尝试过的:

创建一个 div <div id="cropper-box"></div> 并使用 jQuery('#cropper-box').append('<img src="" id="cropbox" />'); 然后设置值。我尝试了同样的事情,但在 1 步中而不是之后设置图像 src。

我尝试在页面<img src="placeholder.png" id="cropbox" /> 上放置一个占位符,并在单击按钮时更改源。这可行,但裁剪区域保持图像的大小(300x180 像素或其他东西)并且不会变大。

// 编辑:

尝试更多显示图像源被正确替换(!使用 Firefox 显示所选文本的源),我仔细检查了 URL,但这是一个正确的 URL 和工作图像。

在裁剪器应该在的地方,有一个大约 10x10 像素的白点,裁剪器图标(加号)正在弹出。但如前所述:图像未显示。

// 编辑2:

所以我已经为同一张图片获取了第一次和第二次尝试的来源。如前所述,第一次尝试无法正确加载图像,第二次尝试加载正常(仅当第二次尝试是相同图像时(!!))。

所选页面源显示 1 个不同之处,即首先尝试:

<img style="position: absolute; width: 0px; height: 0px;" src="http://95.142.175.17/uploads/files/Desert.jpg">

第二次尝试:

<img style="position: absolute; width: 700px; height: 525px;" src="http://95.142.175.17/uploads/files/Desert.jpg">

我猜这是 jCrop 正在替换的图像,但它是一个完整的谜,为什么它第一次将 0 高度/宽度放入其中,第二次放入正确的尺寸。

【问题讨论】:

  • ...不确定它是否会产生影响和/或帮助,但我将初始化过程分解为单独的步骤: var jcrop_api = null; jcrop_api = $.Jcrop('#cropbox'); jcrop_api.setOptions({onChange: [showCoords, setEditDataOK( false ) ], onSelect: showCoords}); jcrop_api.setSelect( [ vx, vy, vx2, vy2 ] ) jcrop_api.focus();
  • 谢谢,但没有解决问题。如果这可能是一个更常见的问题:在第一次尝试每个不同的图像时,它会失败。但是如果我重新加载页面,选择相同的文件再试一次,它就可以了。
  • 问题已解决,我会自己发布答案,以防有人需要。

标签: javascript jquery jcrop


【解决方案1】:

我知道这是旧的,但它最近在我的安装中随机发生。发现是因为在jCrop初始化之前图片没有完全加载。

修复它所需要的只是将 jCrop 初始化内容包装在一个

$(window).on("load", function () { //jcrop stuff here });

从那以后它一直运作良好。

【讨论】:

    【解决方案2】:

    好的,如果其他人遇到这个问题:

    如果加载图像和对其应用 jCrop 的操作在彼此之后排队太快,jCrop 会有点混乱。我仍然觉得奇怪的是第二次尝试完美无缺,但我认为这与页面的 DOM 识别的缓存图像尺寸有关。

    我想出的解决方案是创建一个函数,将 #cropbox 转换为 jCrop 区域,然后设置 2 秒的间隔,只是为了给 jCrop 一些时间来识别图像及其尺寸,然后转换元素。

    这是我使用的 html 的一部分(带有预加载器):

    <div id="cropper-loading" style="display: none;"><img src="images/analytics/ajax-loader.gif" /></div>
    <img id="cropbox" src="images/placeholder.png" style="display: none;" />
    

    正如您所见,cropbox 图像和cropper-loading div 都被隐藏了,因为它们不是立即需要的。如果你愿意,你可以显示占位符。然后使用这个 HTML 表单:

    <input name="image2" id="img2" type="text" readonly="readonly" onclick="openKCFinder(this)" value="click here to select an image" style="width: 285px;" />  <button class="button button-blue" type="submit" name="load" id="selectimg">Load Image in cropper</button>
    

    在我的例子中,我一直在使用 KCFinder 来加载图像(它是 CKEditor 的一部分,非常值得一看!),KCFinder 处理上传、重命名等,并在选择它后返回选择的图像路径(相对/绝对是可配置的) 到输入字段。

    然后当单击#selectimg 时调用此代码:

    jQuery('#selectimg').click(function(e) { 
        e.preventDefault();
        jQuery('#cropper-loading').css('display', 'block');
    
        var newsrc = jQuery('#img2').val();
    
        jQuery('#cropbox').attr('src', newsrc);
        jQuery('#img').val(newsrc);
    
        function createJcropArea() {
            jQuery('#cropper-loading').css('display', 'none');                                      
            jQuery('#cropbox').css('display', 'block');
            var jcrop_api = jQuery.Jcrop('#cropbox', {
                boxWidth: 700, 
                boxHeight: 700,
                onSelect: updateCoords,
                onChange: updateCoords
            });
            clearInterval(interval);
        }
        var interval = setInterval(createJcropArea, 2000);
    });
    

    起初我阻止链接像往常一样被关注(或按钮操作),然后显示加载 div(这是我隐藏占位符图像的原因,否则它看起来会一团糟)。

    然后从输入字段加载图像位置并复制到另一个(#img),该字段用于随后处理图像(PHP使用#img的值来加载此图像)。同时,#cropbox src 也被设置为新图像。

    解决我的问题的部分来了:

    我没有直接激活 jCrop,而是创建了一个函数:

    1) hides the loading icon
    2) displays the image
    3) converts #cropbox into a jCrop area
    4) clean the interval (otherwise it would loop un-ending)
    

    在这个函数之后你可以看到,为了保存,我在 jCrop 区域被转换之前延迟了 2 秒。

    希望以后对大家有所帮助!

    干杯并感谢您思考@vector 和其他人;-)

    【讨论】:

    • 谢谢,这可能有一天会派上用场。使用 jCrop 的信息有时可能有点稀少 :-)
    • 谢谢@pendo。有同样的问题,你的回答让我走上了正确的道路。我让我的工作略有不同,但总体思路相同。您还可以使用 .load() jquery 函数填充 init 函数以在图像加载完成后触发。 $("image_cropper").attr("src",YOURSOURCE).load(function() {do_crop_init_here} );您正在强制加载图像,并在完成后附加要触发的功能。希望这可以帮助人们。
    • 这确实是一个不错的补充!
    • 嗨@AlexeyGerasimov,我喜欢你的方法,因为它不需要等待说明。但是,它不适用于我的情况。它仍然是空的...如果我使用浏览器的重新加载功能,图像是空的,如果我使用属性 GET 请求(例如,在 URL 字段中设置光标并按 ENTER),它工作正常。您是否有适合您的完整代码示例?
    • 所提出的解决方案都不适合我。在这里评论是因为它在谷歌上排名很高。我的问题是图像的宽度和高度从原始图像大小更改为加载图像后显示在页面上的大小,并且 jCrop 认为图像的尺寸远小于实际尺寸。我解决了它以将 css 可见性设置为隐藏,在图像加载时初始化 jCrop,并且在 jCrop init 删除 css 可见性属性之后。
    【解决方案3】:

    不要调用这个函数onChange : updateCoords

    尝试不使用它,它会在手机上流畅运行。

    您可以直接创建 base64 并将它们显示为任何您想要的图像。

    【讨论】:

      【解决方案4】:

      创建“图像”对象并设置“src”属性并不适用,您可以将图像视为已加载。 此外,提供任何固定的超时间隔并不能保证图像已经加载。

      相反,您应该为图像对象设置一个“onload”回调 - 然后将初始化 Jcrop 对象:

      var src = 'https://example.com/imgs/someimgtocrop.jpg'; 
      var tmpImg = new Image();
      tmpImg.onload = function() {
         //This is where you can safely create an image and a Jcrop Object
      };
      tmpImg.src = src; //Note that the 'src' attribute is only added to the Image Object after the 'onload' listener was defined
      

      【讨论】:

        【解决方案5】:

        这是我奇怪但绝妙的解决方案:

        if (obj.tagName == 'IMG') {
          var tempImage = new Image();
            tempImage.src = $origimg[0].src;
            $origimg.width(tempImage.width);
            $origimg.height(tempImage.height);
          if ($origimg[0].width > 1 && $origimg[0].height > 1) {
            $origimg.width($origimg[0].width);
            $origimg.height($origimg[0].height);
          } else {
            var tempImage = new Image();
            tempImage.src = $origimg[0].src;
            $origimg.width(tempImage.width);
            $origimg.height(tempImage.height);
             //console.log('error'+$origimg[0].width + $origimg[0].height);
          } 
        

        【讨论】:

          【解决方案6】:

          在此处尝试 repo 上的边缘库:https://github.com/tapmodo/Jcrop

          这应该可以解决您的问题。为解决您的问题而更改的行:

          // Fix size of crop image.
          // Necessary when crop image is within a hidden element when page is loaded.
          if ($origimg[0].width != 0 && $origimg[0].height != 0) {
            // Obtain dimensions from contained img element.
            $origimg.width($origimg[0].width);
            $origimg.height($origimg[0].height);
          } else {
            // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).
            var tempImage = new Image();
            tempImage.src = $origimg[0].src;
            $origimg.width(tempImage.width);
            $origimg.height(tempImage.height);
          }
          

          【讨论】:

          • 这似乎不行。将 alert($tempImage.width) 或 .height() 放在 else 块的末尾。你会得到 0。至少我会。问题似乎和以前一样,图像尚未加载完成,因此获取宽度/高度返回 0。jcrop init 中的额外代码无济于事,因为需要的是图像加载和图像加载之间的延迟初始化自己。
          猜你喜欢
          • 2013-07-28
          • 1970-01-01
          • 1970-01-01
          • 2012-05-01
          • 2014-05-01
          • 2014-07-18
          • 2015-02-23
          • 2013-04-18
          • 2013-10-29
          相关资源
          最近更新 更多