图片等比例自适应填充
需求描述:用户可以上传任意尺寸的图片,但在实际显示时有固定尺寸,也就是等比缩放,完全铺满,溢出部分不显示。其实,也就是css3中background-size的cover所实现的,不过这都是后话了。
一 讲道理,不管什么问题都是先上网看看有没有现成的可以用的,该抄则抄。不过最后结果不是太好。上网查询大致分为了两种方式,第一种方式就是上面说的background-size,第二种就是通过JavaScript来自己实现了,不过肯定不会像第一种方式那么简单了。但是,事情总有个意外,background-size,看名称都知道它是针对背景的,而我们需求中要处理的是img(其实也想过要不直接把img取消换成背景显示得了,不过因为已经在img上实现了拖拽功能,在我之前的一位大神写的特别高大上,不敢改),所以只能试试第二种方式了。
二 既然打算用JavaScript来实现,就详细地捋捋思路。在img标签中我们可以通过设置width,height来设置图片的大小,如果同时设置宽高为100%,不就ok了嘛。问题没有这么简单,不要忘了我们还有等比例的要求,图片可以溢出但不能变形。然后上网搜了搜,如何控制图片等比例缩放,答案是不要同时设置img的 width和height。这就遇到问题了,如果我们设置了width为100%,这就可能存在高度方面没有完全填充的情况,反之亦然。举例子来说,我们有一张400*300的图片,要放进100*100的div中,如果我们设置了宽度为100%,那么图片的宽高分别为100 75,并没有完全填充div。或许有人会说,可以设高度为100%呀,那么我给你一张300*400的图片又该怎么处理呢。说到这大家可能明白了,这就是我们要通过javascript要做的事,根据图片的尺寸来分情况给图片设置宽高属性。基本上原理就算是明白了,可以具体实现了。
三 在通过JavaScript实现后,测试发现,并不是每回都能达到我们想要的结果。有的时候直接按图片的原始尺寸给我们显示出来了。调试发现,显示原始尺寸的时候,是因为JavaScript获取到的图片宽高为0,而原因是因为我们在图片还未加载成功,我们便进行了获取。在这里上网搜索的比较好的处理方式时,在存储图片时同时存储图片的高宽,这样就可以不依赖图片加载。想了想,确实是很不错的处理方式,打算以后如果有这方面功能设计要做的话,一定这么处理。不过大家也能想的到,都已经是改bug的阶段了,怎么可能去耗费大量时间去更改后台。 所以只能一条道走到黑了,那我们就等图片加载玩再处理,也就找到了这个方法$("img").load()。把我们的处理逻辑放在了这里面,我们就等图片完全加载后再处理。可是后来还是不行,有的时候还是直接原图显示了,有的时候会先显示原图,然后换成我们想要的尺寸,造成页面的抖动,用户体验非常不好。这其实是两个问题,前一个是因为缓存的存在,造成了load事件没有触发,后一个是因为图片加载是需要时间的。分别处理这两个问题,前一个我们通过判断图片有没有宽高值,有就直接处理,没有就绑定load事件。后一个,通过div占位,图片设置为不显示,当我们处理完成后再显示。
四 所有的处理过程就是这样,也许其中有很多处理方式不符合规范的,但我也只想到这么多了,反正最后功能实现了。
欢迎大家指出我的错误或者提供更好的解决方式。
下面是我写完的Javascript函数。
function setImgSize(address, displayWidth, displayHeight, displayMode) { var displayRatio = displayWidth / displayHeight; $(address).each(function () { $(this).load(function () { var picRatio = this.width / this.height; if (picRatio > displayRatio) { $(this).css("height", displayHeight + "px"); var width = $(this).css("width"); $(this).css("margin-left", -(parseInt(width) - displayWidth) / 2 + "px"); $(this).css("display", displayMode); } else { $(this).css("width", displayWidth + "px"); var height = $(this).css("height"); $(this).css("margin-top", -(parseInt(height) - displayHeight) / 2 + "px"); $(this).css("display", displayMode); } }); if (this.width != 0 && this.height != 0) { var picRatio = this.width / this.height; if (picRatio > displayRatio) { $(this).css("height", displayHeight + "px"); var width = $(this).css("width"); $(this).css("margin-left", -(parseInt(width) - displayWidth) / 2 + "px"); $(this).css("display", displayMode); } else { $(this).css("width", displayWidth + "px"); var height = $(this).css("height"); $(this).css("margin-top", -(parseInt(height) - displayHeight) / 2 + "px"); $(this).css("display", displayMode); } } }); }
新手,可以指出错误,不要喷我。