【问题标题】:php - Server side marker clusteringphp - 服务器端标记聚类
【发布时间】:2013-12-14 16:53:05
【问题描述】:

我的网站上目前有一张显示 50,000 个标记的地图。由于混乱,这些对用户来说是不可读的,所以我使用谷歌的 markerclusterer 实现了一个集群解决方案。这工作正常,但由于标记的数量,加载速度非常慢。

我想使用 php 形式的服务器端解决方案,但找不到最好的方法。这是我目前的设置

外部php文件标记-xml.php

<?php
$SQL = "SELECT MarkerName, Lat, Lng FROM TableName WHERE MarkerName !=''";
$Query = mysql_query($SQL);
$NumRows = mysql_num_rows($Query);
?>
<markers>
<?php       
for($i = 0; $i < $NumRows; $i++)
{
    $row = mysql_fetch_assoc($Query);
    $Lat = $row['Lat'];
    $Lng = $row['Lng'];
    $MarkerName = $row['MarkerName'];

    echo "<marker Lat='$Lat' Lng='$Lng' MarkerName='$MarkerName'> </marker>\n";
}
?>
</markers>

包含地图的主文件

function initialize(mapvars) {
        var xmldata = "markers-xml.php";

        downloadUrl(xmldata, function(doc) {
            var xml = xmlParse(doc);
            var markersInfo = xml.documentElement.getElementsByTagName("marker");
            var markers = []; 
            var bounds = new google.maps.LatLngBounds();
            for (var i = 0; i < markersInfo.length; i++) {
                var Lat = parseFloat(markersInfo[i].getAttribute("Lat"));
                var Lng = parseFloat(markersInfo[i].getAttribute("Lng"));
                var point = new google.maps.LatLng(Lat,Lng);
                var MarkerName = markersInfo[i].getAttribute("MarkerName");  

                var marker = new google.maps.Marker({
                    position: point,
                    map: map,
                    title: MarkerName,
                    MarkerName: MarkerName
                });

            markers.push(marker);
            bounds.extend(point);
        }

        var markerCluster = new MarkerClusterer(map, markers);
    }

【问题讨论】:

标签: php google-maps google-maps-api-3


【解决方案1】:

我认为服务器端解决方案不会提高性能。可以在每次更改视口时请求过滤数据以减少使用标记的数量,但您总是需要一些时间来请求新数据。

我认为最好的解决方案是使用 FusionTableLayer,它可以毫无问题地处理多达 100000 个标记。


可能的方法(与cmets有关):

当地图的视口发生变化时,将视口的边界和缩放级别发送到服务器。

数据库查询应该

  1. 根据给定的界限过滤结果
  2. 对 lat 和 lng 进行四舍五入(四舍五入的精度必须与缩放级别相关)
  3. 按四舍五入的纬度对结果进行分组
  4. 返回四舍五入的 latLng 和此 latlng 的项目数

将这些数据发送回客户端并创建标记(您可以使用服务器端解决方案来动态创建标记图像或使用自定义叠加层)

【讨论】:

  • 这是一个服务器端集群的例子jory.dk/AreaGMC/MapClustering.html 它有 150,000 多个标记并立即加载。唯一的问题是它是用c#写的,我只知道php
  • 对不起,我想错了方向(仍然返回单个标记,但被视口过滤)。这应该不难实现,我已经更新了我的答案
  • 你的方法是合乎逻辑的,但我不太确定它是如何转换成 php 的。我的 php 技能进一步提升的那一天来得还不够快。
【解决方案2】:

客户端: 生成一个获取请求并传入视口的边界

getclusters.php?&lat2=62_676438&lon2=-63_2085681&lat1=10_6655205&lon1=-135_7183337

服务器端: 将您的 lat lon 数据存储在具有 pk 和 POINT 数据结构的表中,以便您可以使用 mysql 空间索引(它使用 r-trees 而不是 b-trees,因此将 50K 点分组是秒而不是分钟):

CREATE TABLE location (
 id int(11) unsigned NOT NULL
 , p POINT NOT NULL, PRIMARY KEY (id)
 , SPATIAL INDEX(p)) ENGINE=MyISAM;

从另一个表加载:

INSERT INTO location 
select id, PointFromWKB(Point(latitude, longitude))
from table_with_lat_long

从 csv 加载:

LOAD DATA LOCAL INFILE 'data.csv'
INTO TABLE location
COLUMNS TERMINATED BY ',' LINES TERMINATED BY '\r\n'
(id, @dummy, ..., @dummy, @latitude, @longitude)
set p = PointFromText(CONCAT('POINT(',@latitude,' ',@longitude,')'));

通过将视口细分为相等的更小方块或基于视口大小的点之间的一些最小距离,编写适当的 SQL 进行分组。只要您使用的是 SPATIAL 索引,它应该会快速运行

您的客户端集群标记 javascript 应根据计数呈现标记(单个标记为 1,集群为 2 或更多)

【讨论】:

    猜你喜欢
    • 2014-05-25
    • 2010-10-22
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多