重用 FileReader 时宽度和高度错误
Posted
技术标签:
【中文标题】重用 FileReader 时宽度和高度错误【英文标题】:Wrong width and height when reusing FileReader 【发布时间】:2015-09-22 01:44:52 【问题描述】:我目前正在开发一个简单的界面,允许用户上传图片,预览,然后将其裁剪为正方形。
我正在使用 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/ 再次图片 1 (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
所以它好多了,但是,第一张图像的尺寸与最后一张不同(它应该,因为它是完全相同的图像) 谢谢。
【问题讨论】:
【参考方案1】:您的所有数字看起来都不一致。在第一张图片中,img.width
的宽度最终为 167,而 jQuery 为 167。需要注意的一件事是 jQuery 获取 computed style 而 img.width
和 img.height
是设置所需宽度和高度的 DOM 属性。 (仅供参考,还有 naturalWidth
和 naturalHeight
,它们是只读 DOM 属性,可让您获得 img
的原始尺寸。)
运气比什么都好
如果您的代码取决于运气,那么我们就有问题了。
看起来浏览器发出的加载事件有点太早了,这样布局引擎还没有完成更新 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 结束。你可以通过调试器来找出答案。
【讨论】:
非常感谢您的回答@initialxy,我已更新我的帖子以显示新结果。尽管如此,我上次上传的结果仍然很奇怪。有什么线索吗? 感谢您的更新@initialxy。奇怪的是图像大小正确。 jcrop 一个和原始一个(上传图片样本)。当我与检查员核对时,一切似乎都很好。所以否则宽度和高度值是错误的,否则我会在应用 css 之前得到它们的大小。 @Vico 您正在使用相同的元素来测量图像大小以及让 jcrop 使用它。 jscrop 对它应用了一堆内联样式。打开您的调试器并在检查器中选择您的 originalimg
。 (现在在 JavaScript 控制台中,您可以顺便使用$0
方便地引用它。)您看到了什么? <img id="upload-picture-sample" src="..." style="display: none; visibility: hidden; width: 1440px; height: 514px;">
之类的东西不是吗?注意到style
属性有一堆不需要的值吗?
是的,我见过。但其实值是正确的:“display: none; visibility: hidden; width: 167px; height: 125px;”
这些值是由 jcrop 添加的,它们会覆盖 CSS 的行为。他们正在搞砸你的宽度和高度。【参考方案2】:
如需更多信息,我建议所有潜在读者看看这个问题: https://github.com/tapmodo/Jcrop/issues/46
解决方法工作正常。
【讨论】:
以上是关于重用 FileReader 时宽度和高度错误的主要内容,如果未能解决你的问题,请参考以下文章
显示 SVG 图标的 Angular 可重用组件的宽度/高度未在任何地方设置并位于图标正下方,stackblitz 内部