javascript jCrop (jQuery) 有时无法加载图像/裁剪区域
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5937208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jCrop (jQuery) sometimes fails to load image/cropper area
提问by Joshua - Pendo
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:
我有一个非常简单的问题,但我对导致问题的原因一无所知。在我的一个应用程序中,我使用 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
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:
在大约 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)
});
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...
我注意到,当我将#cropbox 正在转换的部分放在可裁剪区域时,图像加载得很好,所以错误在于该var = jcrop_api
部分,但我慢慢开始认为没有解决方案。 ..
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.
制作一个 div<div id="cropper-box"></div>
并使用jQuery('#cropper-box').append('<img src="" id="cropbox" />');
,然后设置该值。我尝试了同样的事情,但在 1 步而不是之后设置图像 src。
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.
我试图在页面上放置一个占位符<img src="placeholder.png" id="cropbox" />
并在单击按钮时更改源。这是有效的,但cropperarea 保持图像的大小(300x180px 或其他东西)并且不会像它应该的那样变大。
// 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.
尝试更多后,我发现图像源已被正确替换(!使用 Firefox 显示所选文本的源),我再次检查了 URL,但这是一个正确的 URL 和工作图像。
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.
在裁剪器应该出现的地方,有一个大约 10x10 像素的白点,裁剪器图标(一个加号)正在弹出。但如前所述:图像未显示。
// Edit 2:
// 编辑 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:
所选页面源显示 1 个不同之处,即首先尝试:
<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.
我想这是被 jCrop 替换的图像,但这是一个完整的谜语,为什么它第一次将 0 高度/宽度放在那里,第二次放在适当的大小。
采纳答案by Joshua - Pendo
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.
如果加载图像和对其应用 jCrop 的操作在彼此之后排队太快,jCrop 会有点混乱。我仍然觉得奇怪的是,第二次尝试完美无缺,但我认为这与页面 DOM 识别的缓存图像尺寸有关。
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.
我想出的解决方案是创建一个函数,将 #cropbox 转换为 jCrop 区域,然后设置 2 秒间隔,只是为了给 jCrop 一些时间来识别图像及其尺寸,然后转换元素。
This is the part of html I used (with a preloader):
这是我使用的 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;" />
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:
正如您所看到的,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>
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.
就我而言,我一直在使用 KCFinder 加载图像(它是 CKEditor 的一部分,非常值得一看!),KCFinder 处理上传、重命名等,并在选择它后将所选图像路径(相对/绝对是可配置的)返回到输入字段。
Then when clicking #selectimg this code is called:
然后当点击#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);
});
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).
起初,我防止链接也像往常一样(或按钮动作)被跟踪,然后显示加载 div(这是我隐藏占位符图像的原因,否则它看起来会一团糟)。
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.
然后图像位置从输入字段加载并复制到另一个(#img),此字段用于之后处理图像(PHP 使用#img 的值加载此图像)。同时,#cropbox src 被设置为新图像。
And here comes the part which solved my problem:
这是解决我的问题的部分:
Instead of directly activating jCrop, I've made a function that:
我没有直接激活 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)
And after this function you can see that, just to be save, I took 2 seconds delay before the jCrop area is being converted.
在这个函数之后你可以看到,为了保存,我在 jCrop 区域被转换之前延迟了 2 秒。
Hope it helps anyone in the future!
希望它可以帮助未来的任何人!
Cheers and thanks for thinking @vector and whoever else did ;-)
干杯并感谢您想到@vector 和其他人;-)
回答by Roei Bahumi
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.
创建 'Image' 对象并设置 'src' 属性并不适用,您可以将图像视为已加载。此外,提供任何固定的超时间隔并不能保证图像已经加载。
Instead, you should set up an 'onload' callback for the Image Object - which will then initialize the Jcrop Object:
相反,您应该为图像对象设置一个“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
回答by siong1987
Try the edge library on the repo here: https://github.com/tapmodo/Jcrop
在此处尝试 repo 上的边缘库: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);
}
回答by user3526742
Don't call this function onChange : updateCoords
不要调用这个函数 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.
您可以直接创建 base64 并将它们显示为您想要的任何图像。
回答by GWR
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.
我知道这是旧的,但它最近在我的安装中随机发生。发现是jCrop初始化之前图片没有完全加载造成的。
All it took to fix it was wrapping the jCrop initialization stuff inside of a
修复它所需要的只是将 jCrop 初始化内容包装在一个
$(window).on("load", function () { //jcrop stuff here });
$(window).on("load", function () { //jcrop stuff here });
And it has been working well since.
从那以后它一直运行良好。
回答by MGE
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);
}