jCrop(jQuery)有时无法加载图像/裁剪区域。

16

我面临一个相当简单的问题,但我已经对导致该问题的原因毫无头绪了。在我的一个应用程序中,我使用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" /> ,并在点击按钮后更改源。这有效,但裁剪区域保持图像的大小(300x180px或类似),而不会变大。

// 编辑:

尝试更多后,我发现图像源被正确地替换了!(使用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(); - vector
谢谢,但是没有解决问题。如果这可能是一个更常见的问题:对于每个不同的图像,第一次尝试都会失败。但是如果我重新加载页面,选择相同的文件并再次尝试,则可以成功。 - Joshua - Pendo
问题已解决,我会自己发布答案以便其他人需要时参考。 - Joshua - Pendo
6个回答

10

大家好,如果有人遇到了这个问题:

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;" />

正如您所看到的,裁剪框图像和裁剪器加载的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和其他人的想法;祝大家好运!


2
谢谢,这可能会在将来派上用场。有关使用jCrop的信息有时可能有点稀少 :-) - vector
6
谢谢@pendo。我也遇到了同样的问题,你的答案让我找到了正确的解决方法。我使我的代码略有不同,但大致思路相同。你也可以通过使用.load() jquery函数将init函数嵌入到图像加载完成后触发。 $("image_cropper").attr("src",YOURSOURCE).load(function() {do_crop_init_here} ); 这样你就强制加载图像,并在加载完成后附加一个要执行的函数。希望这能对大家有所帮助。 - Alexey Gerasimov
1
这确实是一个不错的补充! - Joshua - Pendo
嗨 @AlexeyGerasimov ,我喜欢你的方法,因为它不需要等待指令。 但是,在我的情况下它不起作用。 它仍然保持为空白... 如果我使用浏览器的重新加载功能,图像为空白,如果我使用正确的GET请求(例如在URL字段中设置光标并按ENTER键),它可以正常工作。 你有完整的可运行代码示例吗? - basZero
没有一个提出的解决方案适用于我。在这里评论是因为它在谷歌排名很高。我的问题是图像的宽度和高度从原始图像大小更改为加载图像后显示在页面上的大小,而jCrop认为图像的尺寸比实际尺寸小得多。我解决了这个问题,将CSS可见性设置为隐藏,在图像加载时初始化jCrop,并在jCrop init之后删除CSS可见性属性。 - Matej Svajger

4
创建一个“Image”对象并设置“src”属性并不意味着您可以像已经加载完成的图片一样处理它。同时,给定任何固定的超时时间也不能保证图像已经加载完成。
相反,您应该为Image对象设置一个“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

3

在这个仓库中尝试使用Edge库: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);
}

2
这似乎行不通。在else块的末尾放置alert($tempImage.width)或.height()。你会得到0。至少我是这样的。问题似乎与以前相同,图像尚未加载完成,因此在其上获取宽度/高度返回0。 jcrop init中的额外代码没有帮助,因为需要的是图像加载和init本身之间的延迟。 - Alexey Gerasimov

1
请勿调用此函数 onChange : updateCoords 不调用此函数可在移动设备上运行顺畅。
您可以直接创建base64并在任何地方显示它们作为图像。

0

我知道这已经是老问题了,但最近我的安装有时也会出现这个问题。后来发现原因是在 jCrop 初始化之前图片没有完全加载好。

只需要将 jCrop 的初始化代码包含在以下语句中:

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

就可以解决问题了。自此以后,一切都运行良好。


0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接