由于 3 月可能要结束实习,所以应该不会有特别固定的主题,另外我会在月初陆续补上上个月的番外篇 Projection 和 TMS,作为介绍性的内容对矢量切片部分进行补充,剩下时间不定期写一些杂烩。
最近两天在做一个地图上 popup 浮动层的功能,因为之前一直沿用 OpenLayers2 中自带的 popup 组件,但 OL2 中实在是难以控制浮动层的样式,远不及直接在地图上覆盖 div 布局来的快,所以我决定暂时放弃使用 popup,自己编写一个浮动层。
一 问题的来源
设计草图如下(样式主要参照了百度地图的弹出层),主要讲这个弹出层分为了三级:1)location:地理位置信息和定位;2)images:图片集;3)indexs:指数计算;
那么,这篇题外讲的就是在实现功能的过程中遇到的一个小问题——图片的缩略图,在这里先简单介绍一下背景和思路:利用 OL2 中的 popup 的被选中触发的事件,填充已经隐藏在页面中的 POI 弹出层,而数据库中存储的是图片的 URL,图片存储在服务器上,在填充 POI 弹出层的图片部分时,直接插入 <img> 元素,再利用 JS 部分的功能代码对图片进行重定义大小,最终实现将缩略图显示在我们的页面上。
好了,那么问题在哪呢?我们先来看如何实现。
二 实现过程
2-1)利用 html 和 CSS,构建一个 demo,并按照设计实现布局
效果如上,接下来是将图片插入到 image 栏中,我这里使用的图片都是未经过处理的,所以宽和高比例几乎都不相同,所以需要经过处理才能妥善的放到 image 栏中。
2-2)处理图片的尺寸(Resize)
下面这段代码是网络上很常见的代码,当你搜索 "JS"、"缩略图" 等关键字的时候,十有八九会出现这样一段代码:
- //重新定义img的宽和高
- //参数:orginalImage<目标图片的DOM元素>、newWidth<图片元素的容器宽度>、newHeight<图片元素的容器高度>
- function reSizeImage(orginalImage, newWidth, newHeight){
- var image = new Image();
- image.src = orginalImage.src
- if(image.width > 0 && image.height > 0){
- //判断图片的纵横比
- if(image.width/image.height >= newWidth/newHeight){
- //当源图的宽度大于重定义尺寸的宽度时,应压缩高度
- if(image.width > newWidth){
- orginalImage.width = newWidth;
- orginalImage.height = (image.height*newWidth)/image.width;
- }else{
- //当宽度小于或等于重定义宽度时,图片完全显示
- orginalImage.width =image.width ;
- orginalImage.height = image.height;
- }
- }else{
- //同理
- if(image.height > newHeight){
- orginalImage.height = newHeight;
- orginalImage.width = (image.width*newHeight)/image.height;
- }else{
- orginalImage.width = image.width;
- orginalImage.height = image.height;
- }
- }
- }
- }
当然,可能细节上会有出入,但是大体思路是一致的,既然有人造好了轮子,那还能有什么问题呢?
在实现过程中,将这个功能函数应用到某个场景中 (以我刚才上文提到的弹出层为例):
- function createPOIDetail(monitSiteName,monitLon,monitlat,locationStr,imageURL,Species,Yvalue){
- //填充我的弹出层HTML模板
- $("#poi_monitsitename").text(monitSiteName);
- $("#poi_monitsitelonandlat").text(monitLon +"° E,"+ monitlat+"° N");
- $("#poi_location").html("<img src='images/markList_smallsize_opacity0.png' style='width:15px;height:12px;'>"+
- "<a class='a_text' href='' style='font-size:11px; color:#FFFFF'>"+locationStr+"</a>");
- $("#poi_images").html(imageURL);
- $("#poi_dominacespecie").text(Species);
- $("#poi_dominaceYValue").text(Yvalue);
- $("#poi_detail_panel").fadeIn(800);
- //对弹出层模板中已经插入的图片进行resize
- var orginalIMG = document.getElementById("imageFrame");
- var newWidth = $("#poi_images").width();
- var newHeight = $("#poi_images").height()
- reSizeImage(orginalIMG,newWidth,newHeight);
- }
每次触发这个函数的时候,我们预期的效果是,在 Image 栏里出现一个大小适应的缩略图,但奇怪的是,当第一次进入页面,触发该函数时,reSizeImage 方法都没有执行,直接插入了真实大小的图片,导致整个弹出层变形(如下图所示)。
弹出层变形 弹出层正常
但往往在第二次,第三次触发该函数的时候,弹出层又正常了,真的很奇怪!
三 问题定位
从逻辑上看,代码应该没有明显的错误,利用 Firebug 中的断点跟踪之后发现,第一次触发函数,并没有进入 reSizeImage 的 if(image.width> 0 && image.height > 0) 这个分支里,我们可以使用 console.log 去查看当时插入的元素的宽和高,你会发现,第一次触发的时候插入的 <img> 元素的宽高都是 0,但是元素也都插入成功了,并且能看到 src 等属性都是有值的。那为什么一个有 src 的元素会不存在宽高呢?
其实问题很简单,在网页的加载过程中,图片的加载是最后才进行的,所以,虽然此时不空,且已经有了 src 的属性值,但是图片本身还没有加载进来,所以导致了你的代码无法顺利的进入 resize 的过程。
四 解决
知道了问题在哪,那解决方案也很简单,只要我们将 reSizeImage 函数放到目标图片加载完成之后再执行就可以了,也就是说:
var orginalIMG = document.("imageFrame");
var newWidth = $("#poi_images").width();
var newHeight = $("#poi_images").height()
- orginalIMG. = function(){
- reSizeImage(orginalIMG,newWidth,newHeight);
- }
这样一来,你就能保证每次页面加载完成后,触发相应的函数就能够得到一个经过 resize 后的图片了!
参考博客:《img.width 一直是 0》:http://www.cnblogs.com/zqzjs/p/4512988.html
来源: http://www.cnblogs.com/escage/p/6491316.html