diff options
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/static/js/ishtar-map.js | 125 | ||||
-rw-r--r-- | ishtar_common/static/media/images/marker-cluster.png | bin | 0 -> 1211 bytes | |||
-rw-r--r-- | ishtar_common/views_item.py | 21 |
3 files changed, 136 insertions, 10 deletions
diff --git a/ishtar_common/static/js/ishtar-map.js b/ishtar_common/static/js/ishtar-map.js index 402284da3..3cce09fcb 100644 --- a/ishtar_common/static/js/ishtar-map.js +++ b/ishtar_common/static/js/ishtar-map.js @@ -2,6 +2,7 @@ var default_pointer = "/media/images/default-pointer.png"; +var marker_cluster = "/media/images/marker-cluster.png"; var view_projection = 'EPSG:3857'; @@ -40,8 +41,6 @@ var get_markers = function(points){ /* styles */ var get_style = function(feature){ - properties = feature.getProperties(); - console.log(properties); return new ol.style.Style({ image: new ol.style.Icon({ anchor: [17, 50], @@ -53,10 +52,127 @@ var get_style = function(feature){ }); }; +/* clustering */ + +var invisible_style_icon; +var _styleCache; +var _remindOldStyle; +var _remindUpdated; +var _currentRemind; +var _revision = 1; +var cluster_source; +var cluster_layer; + +var enable_clustering = function(){ + + if (!invisible_style_icon){ + invisible_style_icon = new ol.style.Style({ + image: new ol.style.Icon({ + //still need something even if it's invisible + src : static_path + marker_cluster, + opacity : 0 + }) + }); + } + + // Style clusters and hide items inside clusters + _styleCache = {}; + _remindOldStyle = {}; + _remindUpdated = {}; + _currentRemind = -1; + + function cluster_get_style (feature, resolution){ + feature.set('key', 'cluster'); + var features = feature.get('features'); + + var size = features.length; + feature.set('size', size); + var style = _styleCache[size]; + + // no cluster for lonely marker + if (!style && size > 1){ + var color = size > 25 ? "192,0,0" : size > 8 ? "255,128,0" : "0,128,0"; + var radius = Math.max(8, Math.min(size * 0.75, 20)); + var lbl = size.toString(); + style = _styleCache[size] = [ + new ol.style.Style({ + image: new ol.style.Circle({ + radius: radius, + stroke: new ol.style.Stroke({ + color:"rgba("+color+",0.5)", + width:15 + }), + fill: new ol.style.Fill({ + color:"rgba("+color+",1)" + }) + }), + text: new ol.style.Text({ + text: lbl, + fill: new ol.style.Fill({ + color: '#fff' + }) + }) + }) + ]; + } + // don't reapply the style when no modif have been opered + if (_currentRemind != _revision){ + _remindUpdated = []; + _currentRemind = _revision; + } + if (size > 1){ + // marker himself disappear + for (idx in features){ + var feat = features[idx]; + if (!_remindUpdated[feat.getProperties()['id']]){ + if (!_remindOldStyle[feat.getProperties()['id']]){ + _remindOldStyle[feat.getProperties()['id']] = feat.getStyle(); + } + feat.setStyle(invisible_style_icon); + _remindUpdated[feat.getProperties()['id']] = 1; + } + } + } else { + // or re-appear + var feat = features[0]; + if (!_remindUpdated[feat.getProperties()['id']] && + _remindOldStyle[feat.getProperties()['id']]){ + feat.setStyle(_remindOldStyle[feat.getProperties()['id']]); + _remindUpdated[feat.getProperties()['id']] = 1; + } + } + return style; + } + + // Cluster Source + cluster_source = new ol.source.Cluster({ + distance: 40, + source: new ol.source.Vector() + }); + // Animated cluster layer + cluster_layer = new ol.layer.Vector({ + name: 'Cluster', + source: cluster_source, + // Cluster style + style: cluster_get_style + }); + map.addLayer(cluster_layer); +}; + +var reinit_clustering = function(){ + cluster_source.getSource().clear(); + _styleCache = {}; + _remindOldStyle = {}; + _remindUpdated = {}; + _currentRemind = -1; +}; + + /* display map */ var vector_source; var vector_layer; var center; +var point_features; var map; var map_view; var map_layers; @@ -110,8 +226,9 @@ var display_map = function(map_id, points, layers){ } else { initialize_map(map_id, layers); } + point_features = geojson_format.readFeatures(points); vector_source.clear(); - vector_source.addFeatures(geojson_format.readFeatures(points)); + vector_source.addFeatures(point_features); map.updateSize(); if (points.features.length){ @@ -121,5 +238,7 @@ var display_map = function(map_id, points, layers){ } } + enable_clustering(); + cluster_source.getSource().addFeatures(point_features); } diff --git a/ishtar_common/static/media/images/marker-cluster.png b/ishtar_common/static/media/images/marker-cluster.png Binary files differnew file mode 100644 index 000000000..73b41464c --- /dev/null +++ b/ishtar_common/static/media/images/marker-cluster.png diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index f019fbcb3..72381ed8b 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -1006,16 +1006,20 @@ def _format_geojson(rows): if not rows: return data geo_attr, name_attr = None, None - for attr in rows[0]: - if attr.endswith('point_2d'): - geo_attr = attr - if attr in ['name', 'cached_label']: - name_attr = attr + full, idx = len(rows), 0 + while not geo_attr and idx < full: + row = rows[idx] + for attr in row: + if attr.endswith('point_2d'): + geo_attr = attr + if attr in ['name', 'cached_label']: + name_attr = attr + idx += 1 if not geo_attr or not name_attr: return data for row in rows: feat = {'name': row[name_attr], 'id': row['id']} - if not row[geo_attr]: + if not row.get(geo_attr, None): data['no-geo'].append(feat) continue feature = {'type': 'Feature'} @@ -1206,6 +1210,9 @@ def get_item(model, func_name, default_name, extra_request_keys=None, except (ValueError, TypeError): row_nb = DEFAULT_ROW_NUMBER + if data_type == 'jso # no limit for mapn-map': # no limit for map + row_nb = None + dct_request_items = {} # filter requested fields @@ -1610,7 +1617,7 @@ def get_item(model, func_name, default_name, extra_request_keys=None, try: lnk_template = link_template lnk = lnk_template % reverse('show-' + default_name, - args=[data[0], '']) + args=[data[0], '']) except NoReverseMatch: logger.warning( '**WARN "show-' + default_name + '" args (' |