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

发布于 2024-11-05 22:35:35 字数 1898 浏览 1 评论 0原文

我有一个非常简单的问题,但我对导致问题的原因一无所知。在我的一个应用程序中,我使用 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< /code> 部分,但我慢慢地开始认为没有解决方案......

这是我到目前为止尝试过的:

制作一个 div

并使用 jQuery('#cropper-box').append(' ;'); 然后设置该值。我尝试了同样的操作,但在一步中而不是之后设置图像 src。

我尝试在页面上放置一个占位符 并在单击按钮时更改源。这是可行的,但cropperarea保持图像的大小(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 高度/宽度,在第二个中放置适当的尺寸时间。

I've got a pretty simple problem, but I've become clueless on what is causing the problem. In one of my applications I'm using jCrop as a small add-on to crop images to fit in banners/headers etc. These steps will be taken:

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

in about 75% of the cases everything goes according to plan, however the in the other 25% of the cases jCrop fails to load the cropping area and leaves it blank. Here's the jQuery code I'm using:

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

I noticed that when I left the part away where #cropbox is being transformd in a cropable area, that the image is loading just fine, so the mistake lies with the var = jcrop_api part, but I slowsly start to think that there is no solution for this...

This is what I've tried so far:

Making a div <div id="cropper-box"></div> and use jQuery('#cropper-box').append('<img src="" id="cropbox" />'); and afterwards set the value. I tried the same thing but setting the image src in 1 step instead of afterwards.

I tried to put a placeholder on the page <img src="placeholder.png" id="cropbox" /> and change the source upon clicking the button. This works, but the cropperarea stays the size of the image (300x180px or something) and doesn't get bigger as it should.

// Edit:

Trying some more showed me that the image source is being replaced properly(! using Firefox to show the source for the selected text), I double checked the URL but this was a correct URL and a working image.

At the place where the cropper should be, there's an about 10x10 pixel white spot where the cropper icon (a plus sign) is popping up.. but as said before: the image isn't shown.

// Edit 2:

So I've took the sources for both the 1st and the 2nd try for the same image. As told before the first try the image won't load properly and the 2nd try it does (only when the 2nd try is the same image(!!)).

The selected page source shows 1 difference which is, first try:

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

second try:

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

I guess this is the image that's being replace by jCrop, but it's a complete riddle why it puts 0 heigth/width in there the first and the proper sizes the second time.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

心病无药医 2024-11-12 22:35:35

好吧,大家以防万一其他人遇到这个问题:

如果加载图像和应用 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 和其他人的思考;-)

Okay guys, in case anyone else runs into this problem:

jCrop kinda gets messed up if the actions of loading an image and applying jCrop to it are queued too fast after eachother. I still find it strange that a second attempt works perfect, but I think that has something to do with cached image dimensions which are recognized by the DOM of the page or something.

The solution I came up with was by creating a function that converts the #cropbox into a jCrop area and then setting a 2 second interval, just to give jCrop some time to recognize the image and it's dimensions and then convert the element.

This is the part of html I used (with a preloader):

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

As you can see both the cropbox image and cropper-loading div are hidden as they are not needed instantly. You could display the placeholder if you wanted though.. Then this HTML form is used:

<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>

In my case I've been using KCFinder to load the images (it's part of CKEditor, really worth watching into!), KCFinder handles uploads, renaming etc and after choosing it returns the chosen image path (relative/absolute is configurable) to the input field.

Then when clicking #selectimg this code is called:

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

At first I prevent the link too be followed as it normally would (or button action) and after that the loading div is displayed (that's my reason for hiding the placeholder image, otherwise it would look messed up).

Then the image location is being loaded from the input field and copied into another (#img), this field is used to process the image afterwards (PHP uses the value of #img to load this image). Also simultaneously the #cropbox src is being set to the new image.

And here comes the part which solved my problem:

Instead of directly activating jCrop, I've made a function that:

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)

And after this function you can see that, just to be save, I took 2 seconds delay before the jCrop area is being converted.

Hope it helps anyone in the future!

Cheers and thanks for thinking @vector and whoever else did ;-)

捶死心动 2024-11-12 22:35:35

创建“Image”对象并设置“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

Creating an 'Image' object and setting up the 'src' attribute does not apply that you can treat the image like it had already been loaded.
Also, giving any fixed timeout interval does not guaranty the image has already been loaded.

Instead, you should set up an 'onload' callback for the Image Object - which will then initialize the Jcrop Object:

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
禾厶谷欠 2024-11-12 22:35:35

在此处尝试存储库上的边缘库: 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);
}

Try the edge library on the repo here: https://github.com/tapmodo/Jcrop

This should solve your problem. The lines that are changed to solve your problem:

// 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);
}
好多鱼好多余 2024-11-12 22:35:35

不要调用此函数 onChange : updateCoords

尝试不调用此函数,它将在移动设备上顺利运行。

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

Don't call this function onChange : updateCoords

Try it without and it will run smooth on mobiles.

You can create base64 directly and show them as an image wherever you want.

Oo萌小芽oO 2024-11-12 22:35:35

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

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

Here my weird but fantastic solution:

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);
  } 
亚希 2024-11-12 22:35:35

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

修复它所需要做的就是将 jCrop 初始化内容包装在

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

并且它一直在工作好吧,自从。

I know this is old, but it was happening randomly to my install recently. Found that it was due to images not being full loaded before before jCrop intialized.

All it took to fix it was wrapping the jCrop initialization stuff inside of a

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

And it has been working well since.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文