]> dev.renevier.net Git - syp.git/blobdiff - js/syp.js
when selecting a cluster, zoom until features are detached
[syp.git] / js / syp.js
index e9d3f41431ccc8bb68254d4a9c30debe04535731..0f7785491f15a681bc556a81d0e089e7e39376a3 100644 (file)
--- a/js/syp.js
+++ b/js/syp.js
@@ -1,6 +1,73 @@
 /* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD
  * license. */
 
+/*
+ * With canvas rendering engine, externalgraphics are drawn by loading and
+ * Image javascript object and drawing it with drawImage once it has been
+ * loaded. If matching feature is deleted while image is loading, redraw
+ * function will be called before drawImage and therefore, feature is removed,
+ * but image is still drawn on the screen. We fix it with locks: when an image is
+ * loading, we defer redraw method.
+ */
+OpenLayers.Renderer.Canvas.prototype = OpenLayers.Util.extend({
+    needsRedraw: false,
+    imagesLoading: 0
+}, OpenLayers.Renderer.Canvas.prototype);
+OpenLayers.Renderer.Canvas.prototype.oldRedraw = OpenLayers.Renderer.Canvas.prototype.redraw;
+OpenLayers.Renderer.Canvas.prototype.redraw = function() {
+    if (this.imagesLoading > 0) {
+        this.needsRedraw = true;
+        return;
+    }
+    OpenLayers.Renderer.Canvas.prototype.oldRedraw.apply(this, arguments);
+}
+OpenLayers.Renderer.Canvas.prototype.drawExternalGraphic = function(pt, style) {
+    var img = new Image();
+    img.src = style.externalGraphic;
+
+    if(style.graphicTitle) {
+        img.title=style.graphicTitle;           
+    }
+
+    var width = style.graphicWidth || style.graphicHeight;
+    var height = style.graphicHeight || style.graphicWidth;
+    width = width ? width : style.pointRadius*2;
+    height = height ? height : style.pointRadius*2;
+    var xOffset = (style.graphicXOffset != undefined) ?
+        style.graphicXOffset : -(0.5 * width);
+   var yOffset = (style.graphicYOffset != undefined) ?
+       style.graphicYOffset : -(0.5 * height);
+   var opacity = style.graphicOpacity || style.fillOpacity;
+
+   var context = { img: img, 
+                   x: (pt[0]+xOffset), 
+                   y: (pt[1]+yOffset), 
+                   width: width, 
+                   height: height, 
+                   canvas: this.canvas };
+
+   var self = this;
+   this.imagesLoading++;
+   img.onerror = function() {
+       self.imagesLoading--;
+       if ((self.imagesLoading == 0) && (self.needsRedraw)) {
+           self.needsRedraw = false;
+           self.redraw();
+       }
+   }
+   img.onload = OpenLayers.Function.bind( function() {
+       self.imagesLoading--;
+       if ((self.imagesLoading == 0) && (self.needsRedraw)) {
+           self.needsRedraw = false;
+           self.redraw();
+       } else {
+            this.canvas.drawImage(this.img, this.x, 
+                             this.y, this.width, this.height);
+       }
+   }, context);   
+}
+
+
 OpenLayers.Control.SypAttribution = OpenLayers.Class (OpenLayers.Control.Attribution, {
     updateAttribution: function() {
         var attributions = [SypStrings.poweredByLink];
@@ -60,13 +127,23 @@ var SYP = {
     createDataLayer: function(map) {
         var defaultStyle = new OpenLayers.Style({
             externalGraphic: this.Markers.ICON,
-            graphicHeight: "${height}"
+            graphicHeight: "${height}",
+            label: "${label}",
+            fontColor: "white",
+            fontWeight: "bold"
         }, {
             context: {
                 height: function(feature) {
                     var defaultHeight = SYP.Markers.HEIGHT || 32;
                     var increase = 4 * (feature.attributes.count - 1);
                     return Math.min(defaultHeight + increase, 50);
+                },
+                label: function(feature) {
+                    var renderer = feature.layer.renderer;
+                    if (renderer.CLASS_NAME == "OpenLayers.Renderer.Canvas") {
+                        return ""; // canvas backend cannot draw text above an external Image
+                    }
+                    return (feature.attributes.count > 1) ? feature.attributes.count: "";
                 }
             }
         });
@@ -169,11 +246,36 @@ var SYP = {
         }
     },
 
+    onZoomClusterEnd: function(arg) {
+        var map = arg.object;
+        var point = new OpenLayers.Geometry.Point(this.lonlat.lon, this.lonlat.lat);
+        var center = map.getCenter();
+        for (var i = this.layer.features.length; i-->0;) {
+            var feature = this.layer.features[i];
+            if (feature.geometry.equals(point) && 
+                (feature.attributes.count == this.count)) {
+                   var self = this;
+                   window.setTimeout(function() { map.setCenter(self.lonlat, map.zoom + 1)}, 500);
+                   return;
+            }
+        }
+        SYP.selectControl.activate();
+        map.events.unregister("zoomend", this, SYP.onZoomClusterEnd);
+    },
+
     onFeatureSelect: function(feature) {
         var map = feature.layer.map;
+
         if (feature.attributes.count > 1) {
             this.unselect(feature);
             var lonlat = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y);
+            var args = {
+                lonlat: lonlat,
+                layer: feature.layer,
+                count: feature.attributes.count
+            }
+            map.events.register("zoomend", args, SYP.onZoomClusterEnd);
+            SYP.selectControl.deactivate();
             map.setCenter(lonlat, map.zoom + 1);
             return;
         }
@@ -265,9 +367,18 @@ var SYP = {
                 }
             }
 
+            var offsetTop = this.offsetTop;
+            var offsetLeft = this.offsetLeft;
+            var par = this.offsetParent;
+            var ismsie = OpenLayers.Util.getBrowserName() == "msie";
+            while (par && !ismsie) {
+                offsetTop += par.offsetTop;
+                offsetLeft += par.offsetLeft;
+                par = par.offsetParent;
+            }
             var icon = document.getElementById('bigimg_close');
-            icon.style.top = this.offsetTop;
-            icon.style.left = this.offsetLeft + this.clientWidth - icon.clientWidth;
+            icon.style.top = offsetTop;
+            icon.style.left = offsetLeft + this.clientWidth - icon.clientWidth;
 
         };
         document.getElementById('bigimg').src = href;