diff --git a/code/map_data_render.js b/code/map_data_render.js index 38f1e7ef..212c285d 100644 --- a/code/map_data_render.js +++ b/code/map_data_render.js @@ -5,6 +5,14 @@ window.Render = function() { + // when there are lots of portals close together, we only add some of them to the map + // the idea is to keep the impression of the dense set of portals, without rendering them all + this.CLUSTER_SIZE = L.Browser.mobile ? 10 : 4; // the map is divided into squares of this size in pixels for clustering purposes. mobile uses larger markers, so therefore larger clustering areas + this.CLUSTER_PORTAL_LIMIT = 4; // no more than this many portals are drawn in each cluster square + + + this.entityVisibilityZoom = undefined; + this.portalMarkerScale = undefined; } @@ -393,28 +401,113 @@ window.Render.prototype.createLinkEntity = function(ent,faked) { window.Render.prototype.updateEntityVisibility = function() { + if (this.entityVisibilityZoom === undefined || this.entityVisibilityZoom != map.getZoom()) { + this.entityVisibilityZoom = map.getZoom(); - if (this.portalMarkerScale === undefined || this.portalMarkerScale != portalMarkerScale()) { - this.portalMarkerScale = portalMarkerScale(); + this.resetPortalClusters(); - console.log('Render: map zoom '+map.getZoom()+' changes portal scale to '+portalMarkerScale()+' - redrawing all portals'); + if (this.portalMarkerScale === undefined || this.portalMarkerScale != portalMarkerScale()) { + this.portalMarkerScale = portalMarkerScale(); - //NOTE: we're not calling this because it resets highlights - we're calling it as it resets the style (inc size) of all portal markers - resetHighlightedPortals(); + console.log('Render: map zoom '+map.getZoom()+' changes portal scale to '+portalMarkerScale()+' - redrawing all portals'); + + //NOTE: we're not calling this because it resets highlights - we're calling it as it resets the style (inc size) of all portal markers + resetHighlightedPortals(); + } } } +// portal clustering functionality + +window.Render.prototype.resetPortalClusters = function() { + + this.portalClusters = {}; + + // first, place the portals into the clusters + for (var pguid in window.portals) { + var p = window.portals[pguid]; + var cid = this.getPortalClusterID(p); + + if (!(cid in this.portalClusters)) this.portalClusters[cid] = []; + + this.portalClusters[cid].push(pguid); + } + + // now, for each cluster, sort by some arbitrary data (the level+guid will do), and display the first CLUSTER_PORTAL_LIMIT + for (var cid in this.portalClusters) { + var c = this.portalClusters[cid]; + + c.sort(function(a,b) { + var ka = (8-portals[a].options.level)+a; + var kb = (8-portals[b].options.level)+b; + if (kakb) return 1; + else return 0; + }); + + for (var i=0; i= 0) { + this.portalClusters[cid].splice(index,1); + // FIXME? if this portal was in on the screen (in the first 10), and we still have 10+ portals, add the new 10to to the screen? + } + } +} + +window.Render.prototype.getPortalClusterID = function(portal) { + // project the lat/lng into absolute map pixels + var z = map.getZoom(); + + var point = map.project(portal.getLatLng(), z); + + var clusterpoint = point.divideBy(this.CLUSTER_SIZE).round(); + + return z+":"+clusterpoint.x+":"+clusterpoint.y; }