重用 FileReader 时宽度和高度错误
Wrong width and height when reusing FileReader
我目前正在开发一个简单的界面,允许用户上传图片、预览图片,然后将其裁剪成正方形。
我正在使用 FileReader 获取图像预览,并使用 jCrop 对其进行裁剪。
这是我正在使用的代码(其中的一部分):
var jcrop = null;
var reader = new FileReader();
reader.onload = function (e) {
$('#upload-picture-sample').attr('src', e.target.result).load(function(){
var img = this;
var imageWidth = img.width;
var imageHeight = img.height;
console.log(img.width+'-- WIDTH --'+$(this).width());
console.log(img.height+'-- HEIGHT --'+$(this).height());
if(imageWidth != imageHeight){
var selectArray = [];
if(imageWidth > imageHeight){
selectArray = [(imageWidth-imageHeight)/2, 0, (imageWidth-imageHeight)/2 + imageHeight, imageHeight];
}else{
selectArray = [0, (imageHeight - imageWidth)/2, imageWidth, (imageHeight - imageWidth)/2 + imageWidth];
}
if(!jcrop){
$('#upload-picture-sample').Jcrop({
aspectRatio: 1,
keySupport: false,
addClass: 'jcrop-centered',
setSelect: selectArray
}, function(){
jcrop = this;
});
}else{
jcrop.setImage(e.target.result);
jcrop.setSelect(selectArray);
}
}
$(this).unbind('load');
});
}
$('#upload-picture-file').change(function(){
$('#upload-picture-send').removeClass('disabled');
$('#upload-picture-error').hide();
console.log('changed!');
reader.readAsDataURL(this.files[0]);
})
我认为唯一真正重要的部分是计算宽度和高度的部分。
为了说明问题,我上传:
1/ 图片 1 (600x450)
2/ 图片 2 (94x125)
3/ Picture1 再次 (600x450)
第一次上传正常,第二次上传也正常,但我想这比其他事情更幸运,因为高度被错误地计算为 0。
第三次上传失败(大小设置不正确)。
表示cropzone显示不正确
关于css,我有这个:
#upload-picture-sample{
display:block;
margin-left: auto;
margin-right: auto;
margin-bottom: 30px;
max-height:125px;
height:auto;
width:auto;
max-width:300px;
}
您知道如何解决我的问题吗?
更新:按照@initialxy 的建议添加 setTimeout
之后
所以好多了,但是,第一张图片的尺寸与最后一张的尺寸不同(应该是,因为它是完全相同的图片)
谢谢。
你所有的数字看起来都不一致。在第一张图片中,img.width
的宽度最终为 167,而 jQuery 的宽度最终为 167。需要注意的一件事是 jQuery 得到 computed style 而 img.width
和 img.height
是设置所需宽度和高度的 DOM 属性。 (仅供参考,还有 naturalWidth
和 naturalHeight
,它们是只读 DOM 属性,可让您获得 img
的原始尺寸。)
it's more luck than something else
如果您的代码取决于运气,那么我们遇到了问题。
看起来浏览器发出加载事件有点过早,以至于布局引擎尚未完成 DOM 的更新。 load
只是表示数据加载完毕,并不一定意味着布局引擎必须完成。因此,请稍后在任务队列中将您的代码块放入您的加载函数中。我的意思是将所有内容包装在 setTimeout(..., 0);
中,注意 this
,因为它已更改。
例如
$('#upload-picture-sample').attr('src', e.target.result).load(function(){
var img = this;
setTimeout(function() {
var imageWidth = img.width;
var imageHeight = img.height;
console.log(img.width+'-- WIDTH --'+$(img).width());
console.log(img.height+'-- HEIGHT --'+$(img).height());
// TODO: Crop
...
}, 0);
$(this).unbind('load');
});
编辑: 回应@Vico 的更新。看起来布局引擎这次已经解决了。让我们对这些数字进行一些观察。第一张图片的尺寸最初是 600x450,但最终变成了 167x125。这是有道理的,因为它是由 max-height: 125px;
CSS 属性 调整大小的。第二张图片的两个尺寸均小于 max-width
和 max-height
,因此未调整大小。第三张图片的尺寸为 600x450,它最终具有这些尺寸,因此此时 max-width
和 max-height
不再生效。这是为什么?也许 jcrop 搞砸了风格并覆盖了你的风格。启动你的 Chrome 调试器,检查你的 img
元素并使用它的 JavaScript 控制台来玩弄它。 (给你一个简短的回答,是的,jcrop 确实搞砸了样式并将内联样式应用于元素,这会覆盖你的样式。但是嘿,使用调试器更有趣。)另外,我不确定你为什么右边的尺寸都以 1440x514 结尾。你可以通过调试调试器找到答案。
想要了解更多信息,我建议所有潜在的读者看看这个问题:
https://github.com/tapmodo/Jcrop/issues/46
变通办法工作正常。
我目前正在开发一个简单的界面,允许用户上传图片、预览图片,然后将其裁剪成正方形。
我正在使用 FileReader 获取图像预览,并使用 jCrop 对其进行裁剪。
这是我正在使用的代码(其中的一部分):
var jcrop = null;
var reader = new FileReader();
reader.onload = function (e) {
$('#upload-picture-sample').attr('src', e.target.result).load(function(){
var img = this;
var imageWidth = img.width;
var imageHeight = img.height;
console.log(img.width+'-- WIDTH --'+$(this).width());
console.log(img.height+'-- HEIGHT --'+$(this).height());
if(imageWidth != imageHeight){
var selectArray = [];
if(imageWidth > imageHeight){
selectArray = [(imageWidth-imageHeight)/2, 0, (imageWidth-imageHeight)/2 + imageHeight, imageHeight];
}else{
selectArray = [0, (imageHeight - imageWidth)/2, imageWidth, (imageHeight - imageWidth)/2 + imageWidth];
}
if(!jcrop){
$('#upload-picture-sample').Jcrop({
aspectRatio: 1,
keySupport: false,
addClass: 'jcrop-centered',
setSelect: selectArray
}, function(){
jcrop = this;
});
}else{
jcrop.setImage(e.target.result);
jcrop.setSelect(selectArray);
}
}
$(this).unbind('load');
});
}
$('#upload-picture-file').change(function(){
$('#upload-picture-send').removeClass('disabled');
$('#upload-picture-error').hide();
console.log('changed!');
reader.readAsDataURL(this.files[0]);
})
我认为唯一真正重要的部分是计算宽度和高度的部分。
为了说明问题,我上传:
1/ 图片 1 (600x450)
2/ 图片 2 (94x125)
3/ Picture1 再次 (600x450)
第一次上传正常,第二次上传也正常,但我想这比其他事情更幸运,因为高度被错误地计算为 0。 第三次上传失败(大小设置不正确)。
表示cropzone显示不正确
关于css,我有这个:
#upload-picture-sample{
display:block;
margin-left: auto;
margin-right: auto;
margin-bottom: 30px;
max-height:125px;
height:auto;
width:auto;
max-width:300px;
}
您知道如何解决我的问题吗?
更新:按照@initialxy 的建议添加 setTimeout
之后
所以好多了,但是,第一张图片的尺寸与最后一张的尺寸不同(应该是,因为它是完全相同的图片) 谢谢。
你所有的数字看起来都不一致。在第一张图片中,img.width
的宽度最终为 167,而 jQuery 的宽度最终为 167。需要注意的一件事是 jQuery 得到 computed style 而 img.width
和 img.height
是设置所需宽度和高度的 DOM 属性。 (仅供参考,还有 naturalWidth
和 naturalHeight
,它们是只读 DOM 属性,可让您获得 img
的原始尺寸。)
it's more luck than something else
如果您的代码取决于运气,那么我们遇到了问题。
看起来浏览器发出加载事件有点过早,以至于布局引擎尚未完成 DOM 的更新。 load
只是表示数据加载完毕,并不一定意味着布局引擎必须完成。因此,请稍后在任务队列中将您的代码块放入您的加载函数中。我的意思是将所有内容包装在 setTimeout(..., 0);
中,注意 this
,因为它已更改。
例如
$('#upload-picture-sample').attr('src', e.target.result).load(function(){
var img = this;
setTimeout(function() {
var imageWidth = img.width;
var imageHeight = img.height;
console.log(img.width+'-- WIDTH --'+$(img).width());
console.log(img.height+'-- HEIGHT --'+$(img).height());
// TODO: Crop
...
}, 0);
$(this).unbind('load');
});
编辑: 回应@Vico 的更新。看起来布局引擎这次已经解决了。让我们对这些数字进行一些观察。第一张图片的尺寸最初是 600x450,但最终变成了 167x125。这是有道理的,因为它是由 max-height: 125px;
CSS 属性 调整大小的。第二张图片的两个尺寸均小于 max-width
和 max-height
,因此未调整大小。第三张图片的尺寸为 600x450,它最终具有这些尺寸,因此此时 max-width
和 max-height
不再生效。这是为什么?也许 jcrop 搞砸了风格并覆盖了你的风格。启动你的 Chrome 调试器,检查你的 img
元素并使用它的 JavaScript 控制台来玩弄它。 (给你一个简短的回答,是的,jcrop 确实搞砸了样式并将内联样式应用于元素,这会覆盖你的样式。但是嘿,使用调试器更有趣。)另外,我不确定你为什么右边的尺寸都以 1440x514 结尾。你可以通过调试调试器找到答案。
想要了解更多信息,我建议所有潜在的读者看看这个问题: https://github.com/tapmodo/Jcrop/issues/46
变通办法工作正常。