X-Git-Url: https://dev.renevier.net/gitweb.cgi?p=syp.git;a=blobdiff_plain;f=js%2Fsyp.js;h=0f7785491f15a681bc556a81d0e089e7e39376a3;hp=1f4d632d087c5f2f8afa1108e1e3784329f28bed;hb=42ad41096b29573ca0429b316d364195eac02e8e;hpb=5c3bb419eb4f9728849969fe7cff84f0260066c8 diff --git a/js/syp.js b/js/syp.js index 1f4d632..0f77854 100644 --- 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; @@ -419,45 +530,49 @@ OpenLayers.Console.userError = function(error) { // least as big as content. To achieve that, we need to override // OpenLayers.Popup.Anchored.prototype.updateSize to modify it slightly. OpenLayers.Popup.Anchored.prototype.updateSize = function() { - // determine actual render dimensions of the contents by putting its - // contents into a fake contentDiv (for the CSS) and then measuring it - var preparedHTML = "
" + - this.contentDiv.innerHTML + - "
"; - - var containerElement = (this.map) ? this.map.layerContainerDiv - : document.body; - var realSize = OpenLayers.Util.getRenderedDimensions( - preparedHTML, null, { - displayClass: this.displayClass, - containerElement: containerElement + var self = this; + + window.setTimeout(function() { // timeout added by SYP + + // determine actual render dimensions of the contents by putting its + // contents into a fake contentDiv (for the CSS) and then measuring it + var preparedHTML = "
" + + self.contentDiv.innerHTML + + "
"; + + var containerElement = (self.map) ? self.map.layerContainerDiv + : document.body; + var realSize = OpenLayers.Util.getRenderedDimensions( + preparedHTML, null, { + displayClass: self.displayClass, + containerElement: containerElement + } + ); + + /* + * XXX: next four lines are added by SYP! + */ + if (self.contentDiv) { + realSize.w = Math.max (realSize.w, self.contentDiv.scrollWidth); + realSize.h = Math.max (realSize.h, self.contentDiv.scrollHeight); } - ); - - /* - * XXX: next four lines are added by SYP! - */ - if (this.contentDiv) { - realSize.w = Math.max (realSize.w, this.contentDiv.scrollWidth); - realSize.h = Math.max (realSize.h, this.contentDiv.scrollHeight); - } - // is the "real" size of the div is safe to display in our map? - var safeSize = this.getSafeContentSize(realSize); + // is the "real" size of the div is safe to display in our map? + var safeSize = self.getSafeContentSize(realSize); - var newSize = null; - if (safeSize.equals(realSize)) { - //real size of content is small enough to fit on the map, - // so we use real size. - newSize = realSize; + var newSize = null; + if (safeSize.equals(realSize)) { + //real size of content is small enough to fit on the map, + // so we use real size. + newSize = realSize; - } else { + } else { - //make a new OL.Size object with the clipped dimensions - // set or null if not clipped. - var fixedSize = new OpenLayers.Size(); - fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null; - fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null; + //make a new OL.Size object with the clipped dimensions + // set or null if not clipped. + var fixedSize = new OpenLayers.Size(); + fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null; + fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null; if (fixedSize.w && fixedSize.h) { //content is too big in both directions, so we will use @@ -469,7 +584,7 @@ OpenLayers.Popup.Anchored.prototype.updateSize = function() { // run getRenderedDimensions() again with a fixed dimension var clippedSize = OpenLayers.Util.getRenderedDimensions( preparedHTML, fixedSize, { - displayClass: this.contentDisplayClass, + displayClass: self.contentDisplayClass, containerElement: containerElement } ); @@ -481,7 +596,7 @@ OpenLayers.Popup.Anchored.prototype.updateSize = function() { // adjust for that. // var currentOverflow = OpenLayers.Element.getStyle( - this.contentDiv, "overflow" + self.contentDiv, "overflow" ); if ( (currentOverflow != "hidden") && (clippedSize.equals(safeSize)) ) { @@ -493,8 +608,9 @@ OpenLayers.Popup.Anchored.prototype.updateSize = function() { } } - newSize = this.getSafeContentSize(clippedSize); + newSize = self.getSafeContentSize(clippedSize); } } - this.setSize(newSize); + self.setSize(newSize); + }, 0); }