3月題外:關於JS實現圖片縮略圖效果的一個小問題


  由於3月可能要結束實習,所以應該不會有特別固定的主題,另外我會在月初陸續補上上個月的番外篇Projection和TMS,作為介紹性的內容對矢量切片部分進行補充,剩下時間不定期寫一些雜燴。

  最近兩天在做一個地圖上popup浮動層的功能,因為之前一直沿用OpenLayers2中自帶的popup組件,但OL2中實在是難以控制浮動層的樣式,遠不及直接在地圖上覆蓋div布局來的快,所以我決定暫時放棄使用popup,自己編寫一個浮動層。

一 問題的來源

  設計草圖如下(樣式主要參照了百度地圖的彈出層),主要講這個彈出層分為了三級:1)location:地理位置信息和定位;2)images:圖片集;3)indexs:指數計算;

  那么,這篇題外講的就是在實現功能的過程中遇到的一個小問題——圖片的縮略圖,在這里先簡單介紹一下背景和思路:利用OL2中的popup的被選中觸發的事件,填充已經隱藏在頁面中的POI彈出層,而數據庫中存儲的是圖片的URL,圖片存儲在服務器上,在填充POI彈出層的圖片部分時,直接插入<img>元素,再利用JS部分的功能代碼對圖片進行重定義大小,最終實現將縮略圖顯示在我們的頁面上。

  PS:其實這算不上是真正意義上的縮略圖,因為頁面在加載的時候,還是會加載完整的圖片,只是顯示的時候是以縮略的形式,並不會對頁面的加載速度有提升,在此只是為了實現這樣一個效果。

  好了,那么問題在哪呢?我們先來看如何實現。

二 實現過程

  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>元素的寬和高,你會發現,第一次觸發的時候插入的<img>元素的寬高都是0,但是<img>元素也都插入成功了,並且能看到src等屬性都是有值的。那為什么一個有src的<img>元素會不存在寬高呢?

  其實問題很簡單,在網頁的加載過程中,圖片的加載是最后才進行的,所以,雖然此時<img>不空,且已經有了src的屬性值,但是圖片本身還沒有加載進來,所以導致了你的代碼無法順利的進入resize的過程。

四 解決

  知道了問題在哪,那解決方案也很簡單,只要我們將reSizeImage函數放到目標圖片加載完成之后再執行就可以了,也就是說:

  var orginalIMG = document.getElementById("imageFrame");
  var newWidth = $("#poi_images").width();
  var newHeight = $("#poi_images").height()

 orginalIMG.onload = function(){
        reSizeImage(orginalIMG,newWidth,newHeight);
    }

 

  這樣一來,你就能保證每次頁面加載完成后,觸發相應的函數就能夠得到一個經過resize后的圖片了!

 

  參考博客:《img.width一直是0》:http://www.cnblogs.com/zqzjs/p/4512988.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM