2012-06-09 70 views
1

我有一個jQuery移動列表。我已經添加了代碼來根據我所處的最近狀態來列表。由於某種原因,我的邏輯不起作用。任何想法爲什麼?滾動時列表也非常緩慢。基於地理位置的列表排序

檢查此鏈接並點擊查找左上最近的位置按鈕

http://www.jm.bugs3.com/gl/state.html

<script> 
function findMe(){ 

    if (navigator.geolocation !=undefined){ 
     navigator.geolocation.watchPosition(onFound, handleError); 
    } 
} 
function onFound(position){ 
    var userLat = position.coords.latitude; 
    var userLong = position.coords.longitude; 
    $('ul li').each(function (index){ 
     var locationLat = $(this).find('.lat').html(); 
     var locationLong = $(this).find('.long').html(); 
     var distance = getDistance(userLat, locationLat, userLong, locationLong); 
     $(this).data("distance", distance); 
    }) 

    reOrder(); 
} 



function handleError(error){ 
    alert ("Could not find location"); 
} 

function reOrder(){ 
    $('ul li').sort(sortAlpha).appendTo('ul'); 
} 

function sortAlpha(a, b){ 
    return $(a).data('distance') > $(b).data('distance') ? 1 : -1; //if True or false 1 or -1 
}; 
//Calculate the shortest distance based on lat and long 
function getDistance(lat1, lat2, lon1, lon2){ 
    var R = 6371; //KM 
    var d = Math.acos(Math.sin(lat1) * Math.sin(lat2) + 
      Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1)) * R 
     return d  
}; 

//下面是與緯度和經度座標列表中的代碼

<div data-role="content"> 
     <ul data-role="listview" data-inset="true"> 
      <li> 
       <a href="#page2" data-transition="slide" >Alabama</a> 
       <div class="lat" style="visibility:hidden">31.375626</div> 
       <div class="long" style="visibility:hidden">-86.299592</div> 
      </li> 
      <li> 
       <a href="#page3" data-transition="slide">Alaska</a> 
       <div class="lat" style="visibility:hidden">60.216736</div> 
       <div class="long" style="visibility:hidden">-149.882995</div> 
      </li> 
      <li> 
       <a href="#page4" data-transition="slide">Arizona</a> 
       <div class="lat" style="visibility:hidden">32.447659</div> 
       <div class="long" style="visibility:hidden">-112.134568</div> 
      </li> 
      <li> 
       <a href="#page5" data-transition="slide" >Arkansas</a> 
       <div class="lat" style="visibility:hidden">33.678252</div> 
       <div class="long" style="visibility:hidden">-92.340846</div> 
      </li> 
      <li> 
       <a href="#page6" data-transition="slide" >Boston</a> 
       <div class="lat" style="visibility:hidden">41.358431</div> 
       <div class="long" style="visibility:hidden">-71.059773</div> 
      </li> 
+0

該鏈接已死亡。不在這裏打開。 – nunespascal

回答

0

賀喜,

「......根據我在最近的狀態」,是難以解釋的原因如下一點點:

  • 簡單地說,「最近的狀態我在「是」我所在的州「
  • 」最近的州的地理中心「可能不是」我所在的州「的州(例如,如果我在佛羅里達州的西端Pan Handle,那麼「最接近的州」是阿拉巴馬州,而不是佛羅里達州)
  • 我可能不在狀態(例如,我在海上)。

儘管有這些困難,並且相信自己的代碼正確地反映了應有之義,並從@ ddotsenko的回答工作作爲一個起始點,那麼下面加以改進的:

  • 一個真正的排序操作可以可以通過將<li>引用加載到數組中而不是通過距離(舍入)索引的對象來避免。這將以正確的順序給出一個稀疏數組。
  • <li>元素可以在其原始<ul>內重新排序,從而避免在每種類型中需要新的<ul>元素。

以板載這些點,ddotsenko的代碼修改後的版本將如下所示:

function onFound(position) { 
    var userLat = position.coords.latitude, 
     userLong = position.coords.longitude, 
     arr = [], 
     $ul = $("ul");//a more specific selector would be good 
    $ul.find('li').each(function (index) { 
     var $this = $(this), 
      lat = Number($this.data("latitude")), 
      lng = Number($this.data('longitude')), 
      dist = Math.round(getDistance(userLat, lat, userLong, lng)); 
     arr[dist] = this; 
    }); 
    //At this point, arr is a sparse array of li elements indexed by distance, hence in distance order. 
    for(var item in arr) { 
     //Ref: "Iterating over sparse arrays", //http://hexmen.com/blog/2006/12/iterating-over-sparse-arrays/ 
     if (String(item >>> 0) == item && item >>> 0 != 0xffffffff) { 
      $ul.append(item); 
     } 
    }; 
} 

這應該是明顯更快。

關於緩慢滾動,您可能會更好,DOM中的元素較少。在ddotsenko的代碼javasctipt指示以下格式的<li>s

<li data-latitude="31.375626" data-longitude="-86.299592"> 
    <a href="#page2" data-transition="slide" >Alabama</a> 
</li> 

這應該是隱蔽得比較好的div來保存數據。

更妙的是讓所有的經/緯對硬編碼在JavaScript中,從而避免從DOM慢retreival,例如:

var stateLocations = { 
    "Alabama": {lat: 31.375626, lng: -86.299592}, 
    "Alaska": {lat: 60.216736, lng: -149.882995}, 
    "Arizona": {lat: 32.447659, lng: -112.134568}, 
    "Arkansas": {lat: 33.678252, lng: -92.340846}, 
    ... 
}; 

然後查找相應。

順便說一句,波士頓是一個城市,而不是一個州。美國沒有一個以「B」開頭

1

JavaScript的排序是O(n) - 換句話說,它觸及每個元素不止一次。這意味着你做的。數據(在同一ELEM電話很多次,你多次移動它,以及,引發了瀏覽器每次重繪。

不要元素進行排序的「距離」數組進行排序。

然後,從視圖中刪除整個UL, 遍歷距離陣列, 地圖的每個值回李 從原來的UL摘下它, 其追加到新的UL。 代替舊的UL提出了新的UL。

這種方式瀏覽器重畫只發生一次,你使用已經計算的值(而不是挖掘elem attrs)在排序功能中。

另外,使用數據attr比.find('div with class')拉​​動lat,lon要快。

下面不會隱藏/顯示舊的/新的UL,這意味着在每個LI被移動後您會重繪,但後端計算的數量會大大減少。

var distance_to_li_map = {} 
$('ul li').each(function (index){ 
    var $this = $(this) 
    , locationLat = $this.data("latitude") 
    , locationLong = $this.data('longitude') 
    , distance = getDistance(userLat, locationLat, userLong, locationLong) 

    // store LI elem pointers into map 
    distance_to_li_map[distance] = this 
}) 

var distances = Object.keys(distance_to_li_map) 

distances.sort() 

var newUL = $('<ul></ul>').insertBefore('ul' /*the old UL*/)[0] 

for (var i = 0; i < distances.length; i++) { 
    newUL.appendChild(distance_to_li_map[distances[i]]) 
}; 
+0

感謝代碼,但它的方式更慢,我的原始問題是尋找最近狀態的邏輯。 – hershey

+0

還發現,如果我刪除每個李的div類,列表滾動更好。 {

} – hershey

+0

由於「此代碼速度較慢」,這非常接近這裏描述的排序http://blog.rodneyrehm.de/archives/14-Sorting-Were-Doing-It-Wrong.html並且已經證明比原始示例中的代碼更有效。只要看到鏈接並儘可能地遵守建議即可。 – ddotsenko