New vector rendering for better performance and less renderer specific limitations. r=elemoine (closes #1675, closes #1656, closes #1631, closes #1431, closes #1709)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@7930 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -107,6 +107,13 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
*/
|
||||
selectedFeatures: null,
|
||||
|
||||
/**
|
||||
* Property: unrenderedFeatures
|
||||
* {Object} hash of features, keyed by feature.id, that the renderer
|
||||
* failed to draw
|
||||
*/
|
||||
unrenderedFeatures: null,
|
||||
|
||||
/**
|
||||
* APIProperty: reportError
|
||||
* {Boolean} report friendly error message when loading of renderer
|
||||
@@ -213,6 +220,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
|
||||
this.features = [];
|
||||
this.selectedFeatures = [];
|
||||
this.unrenderedFeatures = {};
|
||||
|
||||
// Allow for custom layer behavior
|
||||
if(this.strategies){
|
||||
@@ -247,6 +255,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
this.destroyFeatures();
|
||||
this.features = null;
|
||||
this.selectedFeatures = null;
|
||||
this.unrenderedFeatures = null;
|
||||
if (this.renderer) {
|
||||
this.renderer.destroy();
|
||||
}
|
||||
@@ -360,13 +369,15 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
moveTo: function(bounds, zoomChanged, dragging) {
|
||||
OpenLayers.Layer.prototype.moveTo.apply(this, arguments);
|
||||
|
||||
var coordSysUnchanged = true;
|
||||
|
||||
if (!dragging) {
|
||||
this.renderer.root.style.visibility = "hidden";
|
||||
|
||||
this.div.style.left = -parseInt(this.map.layerContainerDiv.style.left) + "px";
|
||||
this.div.style.top = -parseInt(this.map.layerContainerDiv.style.top) + "px";
|
||||
var extent = this.map.getExtent();
|
||||
this.renderer.setExtent(extent);
|
||||
coordSysUnchanged = this.renderer.setExtent(extent, zoomChanged);
|
||||
|
||||
this.renderer.root.style.visibility = "visible";
|
||||
|
||||
@@ -376,17 +387,33 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
if (navigator.userAgent.toLowerCase().indexOf("gecko") != -1) {
|
||||
this.div.scrollLeft = this.div.scrollLeft;
|
||||
}
|
||||
|
||||
if(!zoomChanged && coordSysUnchanged) {
|
||||
var unrenderedFeatures = {};
|
||||
for(var i in this.unrenderedFeatures) {
|
||||
var feature = this.unrenderedFeatures[i];
|
||||
if(!this.drawFeature(feature)) {
|
||||
unrenderedFeatures[i] = feature;
|
||||
}
|
||||
}
|
||||
this.unrenderedFeatures = unrenderedFeatures;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.drawn || zoomChanged) {
|
||||
if (!this.drawn || zoomChanged || !coordSysUnchanged) {
|
||||
this.unrenderedFeatures = {};
|
||||
this.drawn = true;
|
||||
var feature;
|
||||
for(var i=0, len=this.features.length; i<len; i++) {
|
||||
if (i != (this.features.length - 1)) {
|
||||
this.renderer.locked = true;
|
||||
} else {
|
||||
this.renderer.locked = false;
|
||||
}
|
||||
this.drawFeature(this.features[i]);
|
||||
feature = this.features[i];
|
||||
if (!this.drawFeature(feature)) {
|
||||
this.unrenderedFeatures[feature.id] = feature;
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -438,7 +465,9 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
}
|
||||
|
||||
if (this.drawn) {
|
||||
this.drawFeature(feature);
|
||||
if(!this.drawFeature(feature)) {
|
||||
this.unrenderedFeatures[feature.id] = feature;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify) {
|
||||
@@ -488,6 +517,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
}
|
||||
|
||||
var feature = features[i];
|
||||
delete this.unrenderedFeatures[feature.id];
|
||||
|
||||
if (notify) {
|
||||
this.events.triggerEvent("beforefeatureremoved", {
|
||||
@@ -553,6 +583,10 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
* Parameters:
|
||||
* feature - {<OpenLayers.Feature.Vector>}
|
||||
* style - {Object} Symbolizer hash or {String} renderIntent
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true if the renderer was able to draw the feature, false
|
||||
* otherwise
|
||||
*/
|
||||
drawFeature: function(feature, style) {
|
||||
if (typeof style != "object") {
|
||||
@@ -564,7 +598,7 @@ OpenLayers.Layer.Vector = OpenLayers.Class(OpenLayers.Layer, {
|
||||
}
|
||||
}
|
||||
|
||||
this.renderer.drawFeature(feature, style);
|
||||
return this.renderer.drawFeature(feature, style);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,13 +103,19 @@ OpenLayers.Renderer = OpenLayers.Class({
|
||||
* Resolution has probably changed, so we nullify the resolution
|
||||
* cache (this.resolution) -- this way it will be re-computed when
|
||||
* next it is needed.
|
||||
* We nullify the resolution cache (this.resolution) if resolutionChanged
|
||||
* is set to true - this way it will be re-computed on the next
|
||||
* getResolution() request.
|
||||
*
|
||||
* Parameters:
|
||||
* extent - {<OpenLayers.Bounds>}
|
||||
* resolutionChanged - {Boolean}
|
||||
*/
|
||||
setExtent: function(extent) {
|
||||
setExtent: function(extent, resolutionChanged) {
|
||||
this.extent = extent.clone();
|
||||
if (resolutionChanged) {
|
||||
this.resolution = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -149,13 +155,20 @@ OpenLayers.Renderer = OpenLayers.Class({
|
||||
* Parameters:
|
||||
* feature - {<OpenLayers.Feature.Vector>}
|
||||
* style - {<Object>}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true if the feature has been drawn completely, false if not,
|
||||
* undefined if the feature had no geometry
|
||||
*/
|
||||
drawFeature: function(feature, style) {
|
||||
if(style == null) {
|
||||
style = feature.style;
|
||||
}
|
||||
if (feature.geometry) {
|
||||
this.drawGeometry(feature.geometry, style, feature.id);
|
||||
if (!feature.geometry.getBounds().intersectsBounds(this.extent)) {
|
||||
style = {display: "none"};
|
||||
}
|
||||
return this.drawGeometry(feature.geometry, style, feature.id);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -450,26 +450,36 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
* featureId - {String}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true if the geometry has been drawn completely; null if
|
||||
* incomplete; false otherwise
|
||||
*/
|
||||
drawGeometry: function(geometry, style, featureId) {
|
||||
var className = geometry.CLASS_NAME;
|
||||
var rendered = true;
|
||||
if ((className == "OpenLayers.Geometry.Collection") ||
|
||||
(className == "OpenLayers.Geometry.MultiPoint") ||
|
||||
(className == "OpenLayers.Geometry.MultiLineString") ||
|
||||
(className == "OpenLayers.Geometry.MultiPolygon")) {
|
||||
for (var i = 0, len=geometry.components.length; i<len; i++) {
|
||||
this.drawGeometry(geometry.components[i], style, featureId);
|
||||
rendered = rendered && this.drawGeometry(
|
||||
geometry.components[i], style, featureId);
|
||||
}
|
||||
return;
|
||||
return rendered;
|
||||
};
|
||||
|
||||
rendered = false;
|
||||
if (style.display != "none") {
|
||||
if (style.backgroundGraphic) {
|
||||
this.redrawBackgroundNode(geometry.id, geometry, style, featureId);
|
||||
this.redrawBackgroundNode(geometry.id, geometry, style,
|
||||
featureId);
|
||||
}
|
||||
this.redrawNode(geometry.id, geometry, style, featureId);
|
||||
} else {
|
||||
var node = OpenLayers.Util.getElement(geometry.id);
|
||||
rendered = this.redrawNode(geometry.id, geometry, style,
|
||||
featureId);
|
||||
}
|
||||
if (rendered == false) {
|
||||
var node = document.getElementById(geometry.id);
|
||||
if (node) {
|
||||
if (node._style.backgroundGraphic) {
|
||||
node.parentNode.removeChild(document.getElementById(
|
||||
@@ -478,6 +488,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
node.parentNode.removeChild(node);
|
||||
}
|
||||
}
|
||||
return rendered;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -488,6 +499,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
* featureId - {String}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true if the complete geometry could be drawn, null if parts of
|
||||
* the geometry could not be drawn, false otherwise
|
||||
*/
|
||||
redrawNode: function(id, geometry, style, featureId) {
|
||||
// Get the node if it's already on the map.
|
||||
@@ -508,7 +523,13 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
newNode._geometry = geometry;
|
||||
newNode._geometryClass = geometry.CLASS_NAME;
|
||||
newNode._style = style;
|
||||
newNode = this.drawGeometryNode(newNode, geometry, style);
|
||||
|
||||
var drawResult = this.drawGeometryNode(newNode, geometry, style);
|
||||
if(drawResult === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
newNode = drawResult.node;
|
||||
|
||||
// Insert the node into the indexer so it can show us where to
|
||||
// place it. Note that this operation is O(log(n)). If there's a
|
||||
@@ -523,6 +544,8 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
}
|
||||
|
||||
this.postDraw(newNode);
|
||||
|
||||
return drawResult.complete;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -540,6 +563,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
* featureId - {String}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true if the complete geometry could be drawn, null if parts of
|
||||
* the geometry could not be drawn, false otherwise
|
||||
*/
|
||||
redrawBackgroundNode: function(id, geometry, style, featureId) {
|
||||
var backgroundStyle = OpenLayers.Util.extend({}, style);
|
||||
@@ -556,7 +583,7 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
backgroundStyle.backgroundYOffset = null;
|
||||
backgroundStyle.backgroundGraphicZIndex = null;
|
||||
|
||||
this.redrawNode(
|
||||
return this.redrawNode(
|
||||
id + this.BACKGROUND_ID_SUFFIX,
|
||||
geometry,
|
||||
backgroundStyle,
|
||||
@@ -574,6 +601,11 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* style - {Object}
|
||||
*
|
||||
* Returns:
|
||||
* {Object} a hash with properties "node" (the drawn node) and "complete"
|
||||
* (null if parts of the geometry could not be drawn, false if nothing
|
||||
* could be drawn)
|
||||
*/
|
||||
drawGeometryNode: function(node, geometry, style) {
|
||||
style = style || node._style;
|
||||
@@ -583,25 +615,26 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
'isFilled': true,
|
||||
'isStroked': !!style.strokeWidth
|
||||
};
|
||||
var drawn;
|
||||
switch (geometry.CLASS_NAME) {
|
||||
case "OpenLayers.Geometry.Point":
|
||||
this.drawPoint(node, geometry);
|
||||
drawn = this.drawPoint(node, geometry);
|
||||
break;
|
||||
case "OpenLayers.Geometry.LineString":
|
||||
options.isFilled = false;
|
||||
this.drawLineString(node, geometry);
|
||||
drawn = this.drawLineString(node, geometry);
|
||||
break;
|
||||
case "OpenLayers.Geometry.LinearRing":
|
||||
this.drawLinearRing(node, geometry);
|
||||
drawn = this.drawLinearRing(node, geometry);
|
||||
break;
|
||||
case "OpenLayers.Geometry.Polygon":
|
||||
this.drawPolygon(node, geometry);
|
||||
drawn = this.drawPolygon(node, geometry);
|
||||
break;
|
||||
case "OpenLayers.Geometry.Surface":
|
||||
this.drawSurface(node, geometry);
|
||||
drawn = this.drawSurface(node, geometry);
|
||||
break;
|
||||
case "OpenLayers.Geometry.Rectangle":
|
||||
this.drawRectangle(node, geometry);
|
||||
drawn = this.drawRectangle(node, geometry);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -612,7 +645,14 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
|
||||
//set style
|
||||
//TBD simplify this
|
||||
return this.setStyle(node, style, options, geometry);
|
||||
if (drawn != false) {
|
||||
return {
|
||||
node: this.setStyle(node, style, options, geometry),
|
||||
complete: drawn
|
||||
};
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -634,6 +674,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the point
|
||||
*/
|
||||
drawPoint: function(node, geometry) {},
|
||||
|
||||
@@ -646,6 +689,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components of
|
||||
* the linestring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLineString: function(node, geometry) {},
|
||||
|
||||
@@ -658,6 +705,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the linear ring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLinearRing: function(node, geometry) {},
|
||||
|
||||
@@ -670,6 +721,10 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the polygon, or false if nothing could be drawn
|
||||
*/
|
||||
drawPolygon: function(node, geometry) {},
|
||||
|
||||
@@ -682,6 +737,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the rectangle
|
||||
*/
|
||||
drawRectangle: function(node, geometry) {},
|
||||
|
||||
@@ -694,6 +752,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the circle
|
||||
*/
|
||||
drawCircle: function(node, geometry) {},
|
||||
|
||||
@@ -706,6 +767,9 @@ OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the surface
|
||||
*/
|
||||
drawSurface: function(node, geometry) {},
|
||||
|
||||
|
||||
@@ -35,10 +35,10 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
MAX_PIXEL: 15000,
|
||||
|
||||
/**
|
||||
* Property: localResolution
|
||||
* {Float}
|
||||
* Property: translationParameters
|
||||
* {Object} Hash with "x" and "y" properties
|
||||
*/
|
||||
localResolution: null,
|
||||
translationParameters: null,
|
||||
|
||||
/**
|
||||
* Property: symbolSize
|
||||
@@ -58,6 +58,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
}
|
||||
OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
|
||||
arguments);
|
||||
this.translationParameters = {x: 0, y: 0};
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -88,14 +89,18 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* x - {Integer}
|
||||
* y - {Integer}
|
||||
* xyOnly - {Boolean} whether or not to just check for x and y, which means
|
||||
* to not take the current translation parameters into account if true.
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} Whether or not the 'x' and 'y' coordinates are in the
|
||||
* valid range.
|
||||
*/
|
||||
inValidRange: function(x, y) {
|
||||
return (x >= -this.MAX_PIXEL && x <= this.MAX_PIXEL &&
|
||||
y >= -this.MAX_PIXEL && y <= this.MAX_PIXEL);
|
||||
inValidRange: function(x, y, xyOnly) {
|
||||
var left = x + (xyOnly ? 0 : this.translationParameters.x);
|
||||
var top = y + (xyOnly ? 0 : this.translationParameters.y);
|
||||
return (left >= -this.MAX_PIXEL && left <= this.MAX_PIXEL &&
|
||||
top >= -this.MAX_PIXEL && top <= this.MAX_PIXEL);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -103,39 +108,66 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
*
|
||||
* Parameters:
|
||||
* extent - {<OpenLayers.Bounds>}
|
||||
* resolutionChanged - {Boolean}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true to notify the layer that the new extent does not exceed
|
||||
* the coordinate range, and the features will not need to be redrawn.
|
||||
* False otherwise.
|
||||
*/
|
||||
setExtent: function(extent) {
|
||||
setExtent: function(extent, resolutionChanged) {
|
||||
OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,
|
||||
arguments);
|
||||
|
||||
var resolution = this.getResolution();
|
||||
var left = -extent.left / resolution;
|
||||
var top = extent.top / resolution;
|
||||
|
||||
// If the resolution has changed, start over changing the corner, because
|
||||
// the features will redraw.
|
||||
if (!this.localResolution || resolution != this.localResolution) {
|
||||
this.left = -extent.left / resolution;
|
||||
this.top = extent.top / resolution;
|
||||
}
|
||||
if (resolutionChanged) {
|
||||
this.left = left;
|
||||
this.top = top;
|
||||
// Set the viewbox
|
||||
var extentString = "0 0 " + this.size.w + " " + this.size.h;
|
||||
|
||||
var left = 0;
|
||||
var top = 0;
|
||||
|
||||
// If the resolution has not changed, we already have features, and we need
|
||||
// to adjust the viewbox to fit them.
|
||||
if (this.localResolution && resolution == this.localResolution) {
|
||||
left = (this.left) - (-extent.left / resolution);
|
||||
top = (this.top) - (extent.top / resolution);
|
||||
}
|
||||
|
||||
// Store resolution for use later.
|
||||
this.localResolution = resolution;
|
||||
|
||||
// Set the viewbox -- the left/top will be pixels-dragged-since-res change,
|
||||
// the width/height will be pixels.
|
||||
var extentString = left + " " + top + " " +
|
||||
this.size.w + " " + this.size.h;
|
||||
//var extentString = extent.left / resolution + " " + -extent.top / resolution + " " +
|
||||
this.rendererRoot.setAttributeNS(null, "viewBox", extentString);
|
||||
this.translate(0, 0);
|
||||
return true;
|
||||
} else {
|
||||
var inRange = this.translate(left - this.left, top - this.top);
|
||||
if (!inRange) {
|
||||
// recenter the coordinate system
|
||||
this.setExtent(extent, true);
|
||||
}
|
||||
return inRange;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: translate
|
||||
* Transforms the SVG coordinate system
|
||||
*
|
||||
* Parameters:
|
||||
* x - {Float}
|
||||
* y - {Float}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true if the translation parameters ar in the valid coordinates
|
||||
* range, false otherwise.
|
||||
*/
|
||||
translate: function(x, y) {
|
||||
if (!this.inValidRange(x, y, true)) {
|
||||
return false;
|
||||
} else {
|
||||
var transformString = "";
|
||||
if (x || y) {
|
||||
transformString = "translate(" + x + "," + y + ")";
|
||||
}
|
||||
this.root.setAttributeNS(null, "transform", transformString);
|
||||
this.translationParameters = {x: x, y: y};
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -413,9 +445,12 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the point
|
||||
*/
|
||||
drawPoint: function(node, geometry) {
|
||||
this.drawCircle(node, geometry, 1);
|
||||
return this.drawCircle(node, geometry, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -426,6 +461,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* radius - {Float}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the circle
|
||||
*/
|
||||
drawCircle: function(node, geometry, radius) {
|
||||
var resolution = this.getResolution();
|
||||
@@ -436,10 +474,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
node.setAttributeNS(null, "cx", x);
|
||||
node.setAttributeNS(null, "cy", y);
|
||||
node.setAttributeNS(null, "r", radius);
|
||||
return node;
|
||||
} else {
|
||||
node.setAttributeNS(null, "cx", "");
|
||||
node.setAttributeNS(null, "cy", "");
|
||||
node.setAttributeNS(null, "r", 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
},
|
||||
@@ -451,23 +488,41 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components of
|
||||
* the linestring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLineString: function(node, geometry) {
|
||||
node.setAttributeNS(null, "points",
|
||||
this.getComponentsString(geometry.components));
|
||||
var componentsResult = this.getComponentsString(geometry.components);
|
||||
if (componentsResult.path) {
|
||||
node.setAttributeNS(null, "points", componentsResult.path);
|
||||
return (componentsResult.complete ? node : null);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**v
|
||||
/**
|
||||
* Method: drawLinearRing
|
||||
* This method is only called by the renderer itself.
|
||||
*
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the linear ring, or false if nothing could be drawn
|
||||
*/
|
||||
drawLinearRing: function(node, geometry) {
|
||||
node.setAttributeNS(null, "points",
|
||||
this.getComponentsString(geometry.components));
|
||||
var componentsResult = this.getComponentsString(geometry.components);
|
||||
if (componentsResult.path) {
|
||||
node.setAttributeNS(null, "points", componentsResult.path);
|
||||
return (componentsResult.complete ? node : null);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -477,28 +532,35 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or null if the renderer could not draw all components
|
||||
* of the polygon, or false if nothing could be drawn
|
||||
*/
|
||||
drawPolygon: function(node, geometry) {
|
||||
var d = "";
|
||||
var draw = true;
|
||||
var complete = true;
|
||||
var linearRingResult, path;
|
||||
for (var j=0, len=geometry.components.length; j<len; j++) {
|
||||
var linearRing = geometry.components[j];
|
||||
d += " M";
|
||||
for (var i=0, ilen=linearRing.components.length; i<ilen; i++) {
|
||||
var component = this.getShortString(linearRing.components[i]);
|
||||
if (component) {
|
||||
d += " " + component;
|
||||
linearRingResult = this.getComponentsString(
|
||||
geometry.components[j].components, " ");
|
||||
path = linearRingResult.path;
|
||||
if (path) {
|
||||
d += " " + path;
|
||||
complete = linearRingResult.complete && complete;
|
||||
} else {
|
||||
draw = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
d += " z";
|
||||
if (draw) {
|
||||
node.setAttributeNS(null, "d", d);
|
||||
node.setAttributeNS(null, "fill-rule", "evenodd");
|
||||
return complete ? node : null;
|
||||
} else {
|
||||
node.setAttributeNS(null, "d", "");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -509,6 +571,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the rectangle
|
||||
*/
|
||||
drawRectangle: function(node, geometry) {
|
||||
var resolution = this.getResolution();
|
||||
@@ -520,11 +585,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
node.setAttributeNS(null, "y", y);
|
||||
node.setAttributeNS(null, "width", geometry.width / resolution);
|
||||
node.setAttributeNS(null, "height", geometry.height / resolution);
|
||||
return node;
|
||||
} else {
|
||||
node.setAttributeNS(null, "x", "");
|
||||
node.setAttributeNS(null, "y", "");
|
||||
node.setAttributeNS(null, "width", 0);
|
||||
node.setAttributeNS(null, "height", 0);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -535,6 +598,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the renderer could not draw the surface
|
||||
*/
|
||||
drawSurface: function(node, geometry) {
|
||||
|
||||
@@ -559,8 +625,9 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
d += " Z";
|
||||
if (draw) {
|
||||
node.setAttributeNS(null, "d", d);
|
||||
return node;
|
||||
} else {
|
||||
node.setAttributeNS(null, "d", "");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -569,18 +636,92 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
*
|
||||
* Parameters:
|
||||
* components - {Array(<OpenLayers.Geometry.Point>)} Array of points
|
||||
* separator - {String} character between coordinate pairs. Defaults to ","
|
||||
*
|
||||
* Returns:
|
||||
* {Object} hash with properties "path" (the string created from the
|
||||
* components and "complete" (false if the renderer was unable to
|
||||
* draw all components)
|
||||
*/
|
||||
getComponentsString: function(components) {
|
||||
getComponentsString: function(components, separator) {
|
||||
var renderCmp = [];
|
||||
var complete = true;
|
||||
var len = components.length;
|
||||
var strings = [];
|
||||
for(var i=0, len=components.length; i<len; i++) {
|
||||
var component = this.getShortString(components[i]);
|
||||
if (component) {
|
||||
strings.push(component);
|
||||
var str, component, j;
|
||||
for(var i=0; i<len; i++) {
|
||||
component = components[i];
|
||||
renderCmp.push(component);
|
||||
str = this.getShortString(component);
|
||||
if (str) {
|
||||
strings.push(str);
|
||||
} else {
|
||||
// The current component is outside the valid range. Let's
|
||||
// see if the previous or next component is inside the range.
|
||||
// If so, add the coordinate of the intersection with the
|
||||
// valid range bounds.
|
||||
if (i > 0) {
|
||||
if (this.getShortString(components[i + 1])) {
|
||||
strings.push(this.clipLine(components[i],
|
||||
components[i-1]));
|
||||
}
|
||||
}
|
||||
return strings.join(",");
|
||||
if (i < len - 1) {
|
||||
if (this.getShortString(components[i + 1])) {
|
||||
strings.push(this.clipLine(components[i],
|
||||
components[i+1]));
|
||||
}
|
||||
}
|
||||
complete = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
path: strings.join(separator || ","),
|
||||
complete: complete
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: clipLine
|
||||
* Given two points (one inside the valid range, and one outside),
|
||||
* clips the line betweeen the two points so that the new points are both
|
||||
* inside the valid range.
|
||||
*
|
||||
* Parameters:
|
||||
* badComponent - {<OpenLayers.Geometry.Point>)} original geometry of the
|
||||
* invalid point
|
||||
* goodComponent - {<OpenLayers.Geometry.Point>)} original geometry of the
|
||||
* valid point
|
||||
* Returns
|
||||
* {String} the SVG coordinate pair of the clipped point (like
|
||||
* getShortString), or an empty string if both passed componets are at
|
||||
* the same point.
|
||||
*/
|
||||
clipLine: function(badComponent, goodComponent) {
|
||||
if (goodComponent.equals(badComponent)) {
|
||||
return "";
|
||||
}
|
||||
var resolution = this.getResolution();
|
||||
var maxX = this.MAX_PIXEL - this.translationParameters.x;
|
||||
var maxY = this.MAX_PIXEL - this.translationParameters.y;
|
||||
var x1 = goodComponent.x / resolution + this.left;
|
||||
var y1 = this.top - goodComponent.y / resolution;
|
||||
var x2 = badComponent.x / resolution + this.left;
|
||||
var y2 = this.top - badComponent.y / resolution;
|
||||
var k;
|
||||
if (x2 < -maxX || x2 > maxX) {
|
||||
k = (y2 - y1) / (x2 - x1);
|
||||
x2 = x2 < 0 ? -maxX : maxX;
|
||||
y2 = y1 + (x2 - x1) * k;
|
||||
}
|
||||
if (y2 < -maxY || y2 > maxY) {
|
||||
k = (x2 - x1) / (y2 - y1);
|
||||
y2 = y2 < 0 ? -maxY : maxY;
|
||||
x2 = x1 + (y2 - y1) * k;
|
||||
}
|
||||
return x2 + "," + y2;
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: getShortString
|
||||
@@ -589,7 +730,7 @@ OpenLayers.Renderer.SVG = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* point - {<OpenLayers.Geometry.Point>}
|
||||
*
|
||||
* Returns:
|
||||
* {String}
|
||||
* {String} or false if point is outside the valid range
|
||||
*/
|
||||
getShortString: function(point) {
|
||||
var resolution = this.getResolution();
|
||||
|
||||
@@ -79,8 +79,13 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
*
|
||||
* Parameters:
|
||||
* extent - {<OpenLayers.Bounds>}
|
||||
* resolutionChanged - {Boolean}
|
||||
*
|
||||
* Returns:
|
||||
* {Boolean} true to notify the layer that the new extent does not exceed
|
||||
* the coordinate range, and the features will not need to be redrawn.
|
||||
*/
|
||||
setExtent: function(extent) {
|
||||
setExtent: function(extent, resolutionChanged) {
|
||||
OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,
|
||||
arguments);
|
||||
var resolution = this.getResolution();
|
||||
@@ -95,6 +100,8 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
// flip the VML display Y axis upside down so it
|
||||
// matches the display Y axis of the map
|
||||
this.root.style.flip = "y";
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
|
||||
@@ -569,23 +576,6 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
return this.nodeFactory(this.container.id + "_root", "olv:group");
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: drawFeature
|
||||
* Overrides the superclass's drawFeature method to take care of features
|
||||
* that are outside the viewport.
|
||||
*
|
||||
* Parameters:
|
||||
* feature - {<OpenLayers.Feature.Vector>}
|
||||
* style - {<Object>}
|
||||
*/
|
||||
drawFeature: function(feature, style) {
|
||||
if (!feature.geometry.getBounds().intersectsBounds(this.extent)) {
|
||||
style = {display: "none"};
|
||||
}
|
||||
OpenLayers.Renderer.Elements.prototype.drawFeature.apply(this,
|
||||
[feature, style]);
|
||||
},
|
||||
|
||||
/**************************************
|
||||
* *
|
||||
* GEOMETRY DRAWING FUNCTIONS *
|
||||
@@ -599,9 +589,12 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the point could not be drawn
|
||||
*/
|
||||
drawPoint: function(node, geometry) {
|
||||
this.drawCircle(node, geometry, 1);
|
||||
return this.drawCircle(node, geometry, 1);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -613,6 +606,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* radius - {float}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement} or false if the circle could not ne drawn
|
||||
*/
|
||||
drawCircle: function(node, geometry, radius) {
|
||||
if(!isNaN(geometry.x)&& !isNaN(geometry.y)) {
|
||||
@@ -625,7 +621,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
|
||||
node.style.width = diameter + "px";
|
||||
node.style.height = diameter + "px";
|
||||
return node;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
@@ -636,9 +634,12 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
drawLineString: function(node, geometry) {
|
||||
this.drawLine(node, geometry, false);
|
||||
return this.drawLine(node, geometry, false);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -648,9 +649,12 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
drawLinearRing: function(node, geometry) {
|
||||
this.drawLine(node, geometry, true);
|
||||
return this.drawLine(node, geometry, true);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -661,6 +665,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
* closeLine - {Boolean} Close the line? (make it a ring?)
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
drawLine: function(node, geometry, closeLine) {
|
||||
|
||||
@@ -679,6 +686,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
}
|
||||
var end = (closeLine) ? " x e" : " e";
|
||||
node.path = "m" + parts.join("") + end;
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -688,6 +696,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
drawPolygon: function(node, geometry) {
|
||||
this.setNodeDimension(node, geometry);
|
||||
@@ -713,6 +724,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
}
|
||||
path.push("e");
|
||||
node.path = path.join("");
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -722,6 +734,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
drawRectangle: function(node, geometry) {
|
||||
var resolution = this.getResolution();
|
||||
@@ -730,6 +745,8 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
node.style.top = geometry.y/resolution + "px";
|
||||
node.style.width = geometry.width/resolution + "px";
|
||||
node.style.height = geometry.height/resolution + "px";
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -738,6 +755,9 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
* Parameters:
|
||||
* node - {DOMElement}
|
||||
* geometry - {<OpenLayers.Geometry>}
|
||||
*
|
||||
* Returns:
|
||||
* {DOMElement}
|
||||
*/
|
||||
drawSurface: function(node, geometry) {
|
||||
|
||||
@@ -761,6 +781,7 @@ OpenLayers.Renderer.VML = OpenLayers.Class(OpenLayers.Renderer.Elements, {
|
||||
path.push(" x e");
|
||||
|
||||
node.path = path.join("");
|
||||
return node;
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -126,23 +126,28 @@
|
||||
}
|
||||
|
||||
function test_Layer_Vector_drawFeature(t) {
|
||||
t.plan(4);
|
||||
var layer = new OpenLayers.Layer.Vector("Test Layer");
|
||||
var map = new OpenLayers.Map('map');
|
||||
t.plan(6);
|
||||
var layer = new OpenLayers.Layer.Vector("Test Layer", {isBaseLayer: true});
|
||||
var map = new OpenLayers.Map('map', {
|
||||
maxExtent: new OpenLayers.Bounds(-100, -100, 100, 100)
|
||||
});
|
||||
map.addLayer(layer);
|
||||
var geometry = new OpenLayers.Geometry.Point(10, 10);
|
||||
var feature = new OpenLayers.Feature.Vector(geometry);
|
||||
|
||||
var f, s;
|
||||
|
||||
// Layer renderer needs a destroy, and draw, for functional tests.
|
||||
// Bogus layer renderer needs some methods
|
||||
// for functional tests.
|
||||
layer.renderer = {
|
||||
drawFeature: function(feature, style) {
|
||||
f = feature;
|
||||
s = style;
|
||||
},
|
||||
root: document.createElement("div"),
|
||||
destroy: function() { },
|
||||
eraseFeatures: function() {}
|
||||
eraseFeatures: function() {},
|
||||
setExtent: function() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -168,6 +173,17 @@
|
||||
t.eq(customStyle.foo, s.foo,
|
||||
"given a custom style, renders with that");
|
||||
|
||||
// the real renderer's drawFeature method is tested in Renderer.html
|
||||
layer.renderer.drawFeature = function(feature) {
|
||||
return(feature.geometry.getBounds().intersectsBounds(map.getExtent()));
|
||||
}
|
||||
layer.addFeatures([feature]);
|
||||
map.setCenter(new OpenLayers.Bounds(0, 0, 0, 0), 6);
|
||||
t.ok(layer.unrenderedFeatures[feature.id], "Did not render feature outside the viewport.");
|
||||
map.panTo(new OpenLayers.LonLat(10, 10));
|
||||
t.ok(!layer.unrenderedFeatures[feature.id], "Rendered feature inside the viewport.");
|
||||
|
||||
layer.features = [];
|
||||
}
|
||||
|
||||
function test_Layer_Vector_eraseFeatures(t) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
var r = new OpenLayers.Renderer();
|
||||
var extent = new OpenLayers.Bounds(1,2,3,4);
|
||||
r.resolution = 1;
|
||||
r.setExtent(extent);
|
||||
r.setExtent(extent, true);
|
||||
t.ok(r.extent.equals(extent), "extent is correctly set");
|
||||
t.eq(r.resolution, null, "resolution nullified");
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@
|
||||
var r = create_renderer();
|
||||
|
||||
var element = document.createElement("div");
|
||||
document.body.appendChild(element);
|
||||
r.root = element;
|
||||
|
||||
r.nodeFactory = function(id, type) {
|
||||
@@ -142,14 +141,15 @@
|
||||
return element;
|
||||
};
|
||||
var g_Node = null;
|
||||
var b_Node = null;
|
||||
r.drawGeometryNode = function(node, geometry, style) {
|
||||
g_Node = node;
|
||||
return node;
|
||||
return {node: node, complete: true};
|
||||
};
|
||||
r.redrawBackgroundNode = function(id, geometry, style, featureId) {
|
||||
var el = r.nodeFactory();
|
||||
el.id = "foo_background";
|
||||
r.root.appendChild(el);
|
||||
b_Node = r.nodeFactory();
|
||||
b_Node.id = "foo_background";
|
||||
r.root.appendChild(b_Node);
|
||||
};
|
||||
|
||||
r.getNodeType = function(geometry, style) {
|
||||
@@ -163,20 +163,25 @@
|
||||
var featureId = 'dude';
|
||||
r.drawGeometry(geometry, style, featureId);
|
||||
t.ok(g_Node.parentNode == r.root, "node is correctly appended to root");
|
||||
t.eq(r.root.childNodes.length, 2, "redrawBackgroundNode appended background node");
|
||||
t.ok(b_Node.parentNode == r.root, "redrawBackgroundNode appended background node");
|
||||
t.eq(g_Node._featureId, 'dude', "_featureId is correct");
|
||||
t.eq(g_Node._style.backgroundGraphic, "foo", "_style is correct");
|
||||
t.eq(g_Node._geometryClass, 'bar', "_geometryClass is correct");
|
||||
|
||||
var _getElement = OpenLayers.Util.getElement;
|
||||
OpenLayers.Util.getElement = function(id) {
|
||||
return g_Node;
|
||||
var returnNode = function(id) {
|
||||
return id == "foo_background" ? b_Node : g_Node;
|
||||
}
|
||||
|
||||
var _getElement = document.getElementById;
|
||||
document.getElementById = returnNode;
|
||||
OpenLayers.Util.getElement = returnNode;
|
||||
|
||||
style = {'display':'none'};
|
||||
r.drawGeometry(geometry, style, featureId);
|
||||
t.ok(g_Node.parentNode != r.root, "node is correctly removed");
|
||||
t.ok(!document.getElementById("foo_background"), "background node correctly removed")
|
||||
t.ok(b_Node.parentNode != r.root, "background node correctly removed")
|
||||
|
||||
document.getElementById = _getElement;
|
||||
|
||||
tearDown();
|
||||
}
|
||||
@@ -216,7 +221,7 @@
|
||||
properDraw = true;
|
||||
return {};
|
||||
};
|
||||
geometry = {CLASS_NAME: 'OpenLayers.Geometry.LineString'};
|
||||
geometry = {id: "foo", CLASS_NAME: 'OpenLayers.Geometry.LineString'};
|
||||
style = true;
|
||||
r.drawGeometry(geometry, style);
|
||||
t.ok(properDraw, "drawGeometry called drawLineString when passed a line string");
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
// test extent changes
|
||||
var extent = new OpenLayers.Bounds(4,3,2,1);
|
||||
r.setExtent(extent);
|
||||
t.eq(r.rendererRoot.getAttributeNS(null, "viewBox"), "6 6 4 4", "rendererRoot viewBox is correct after a new setExtent");
|
||||
t.eq(r.root.getAttributeNS(null, "transform").replace(/ /g, ""), "translate(-6,-6)", "rendererRoot viewBox is correct after a new setExtent");
|
||||
|
||||
OpenLayers.Renderer.Elements.prototype.setExtent =
|
||||
OpenLayers.Renderer.Elements.prototype._setExtent;
|
||||
@@ -128,7 +128,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
t.plan(6);
|
||||
t.plan(5);
|
||||
|
||||
var r = new OpenLayers.Renderer.SVG(document.body);
|
||||
r.resolution = 0.5;
|
||||
@@ -151,14 +151,22 @@
|
||||
// #1274: out of bound node fails when first added
|
||||
var geometry = {
|
||||
x: 10000000,
|
||||
y: 200000000
|
||||
y: 200000000,
|
||||
CLASS_NAME: "OpenLayers.Geometry.Point",
|
||||
id: "foo"
|
||||
}
|
||||
node.id = geometry.id;
|
||||
r.root.appendChild(node);
|
||||
|
||||
var drawCircleCalled = false;
|
||||
r.drawCircle = function() {
|
||||
drawCircleCalled = true;
|
||||
return OpenLayers.Renderer.SVG.prototype.drawCircle.apply(r, arguments);
|
||||
}
|
||||
|
||||
r.drawCircle(node, geometry, "blah_4000");
|
||||
|
||||
t.eq(node.getAttributeNS(null, 'cx'), '', "cx is correct");
|
||||
t.eq(node.getAttributeNS(null, 'cy'), '', "cy is correct");
|
||||
t.eq(node.getAttributeNS(null, 'r'), '0', "r is correct");
|
||||
r.drawGeometry(geometry, {pointRadius: 3}, "blah_4000");
|
||||
t.eq(drawCircleCalled, true, "drawCircle called on drawGeometry for a point geometry.")
|
||||
t.ok(node.parentNode != r.root, "circle will not be drawn when coordinates are outside the valid range");
|
||||
}
|
||||
|
||||
function test_SVG_drawlinestring(t) {
|
||||
@@ -181,7 +189,7 @@
|
||||
r.getComponentsString = function(c) {
|
||||
g_GetString = true;
|
||||
g_Components = c;
|
||||
return "bar";
|
||||
return {path: "bar", complete: true};
|
||||
}
|
||||
|
||||
r.drawLineString(node, geometry);
|
||||
@@ -210,7 +218,7 @@
|
||||
r.getComponentsString = function(c) {
|
||||
g_GetString = true;
|
||||
g_Components = c;
|
||||
return "bar";
|
||||
return {path: "bar", complete: true};
|
||||
}
|
||||
|
||||
r.drawLinearRing(node, geometry);
|
||||
@@ -255,8 +263,7 @@
|
||||
r.getShortString = function(c) {
|
||||
return false;
|
||||
}
|
||||
r.drawPolygon(node, geometry);
|
||||
t.eq(node.getAttributeNS(null, "d"), "", "d attribute is empty if one linearRing cannot be drawn");
|
||||
t.eq(r.drawPolygon(node, geometry), false, "drawPolygon returns false if one linearRing cannot be drawn");
|
||||
}
|
||||
|
||||
function test_SVG_drawrectangle(t) {
|
||||
@@ -319,8 +326,8 @@
|
||||
r.getShortString = function(c) {
|
||||
return false;
|
||||
}
|
||||
r.drawSurface(node, geometry);
|
||||
t.eq(node.getAttributeNS(null, "d"), "", "d attribute is empty if one linearRing cannot be drawn");
|
||||
|
||||
t.eq(r.drawSurface(node, geometry), false, "drawSurface returns false if one linearRing cannot be drawn");
|
||||
}
|
||||
|
||||
function test_SVG_getcomponentsstring(t) {
|
||||
@@ -340,7 +347,7 @@
|
||||
return p;
|
||||
};
|
||||
|
||||
var string = OpenLayers.Renderer.SVG.prototype.getComponentsString(components);
|
||||
var string = OpenLayers.Renderer.SVG.prototype.getComponentsString(components).path;
|
||||
t.eq(string, "foo,bar", "returned string is correct");
|
||||
|
||||
OpenLayers.Renderer.SVG.prototype.getShortString =
|
||||
@@ -424,6 +431,35 @@
|
||||
t.eq(r.dashStyle({strokeWidth: 1, strokeDashstyle: "longdashdot"}, 1), "8,4,1,4", "dashdot dasharray created correctly");
|
||||
}
|
||||
|
||||
function test_svg_clipline(t) {
|
||||
if (!OpenLayers.Renderer.SVG.prototype.supported()) {
|
||||
t.plan(0);
|
||||
return;
|
||||
}
|
||||
|
||||
t.plan(1);
|
||||
|
||||
var r = new OpenLayers.Renderer.SVG(document.body);
|
||||
r.setSize(new OpenLayers.Size(0, 0));
|
||||
r.map = {
|
||||
getResolution: function() {
|
||||
return 0.5;
|
||||
}
|
||||
}
|
||||
r.setExtent(new OpenLayers.Bounds(0, 0, 0, 0));
|
||||
|
||||
var geometry = new OpenLayers.Geometry.LineString([
|
||||
new OpenLayers.Geometry.Point(0, -5000),
|
||||
new OpenLayers.Geometry.Point(10000, 0),
|
||||
new OpenLayers.Geometry.Point(0, 5000)
|
||||
]);
|
||||
|
||||
var node = document.createElement('div');
|
||||
|
||||
r.drawLineString(node, geometry);
|
||||
t.eq(node.getAttribute("points"), "0,10000,15000,2500,15000,-2500,0,-10000", "Geometry correctly clipped at inValidRange bounds");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
123
tests/manual/clip-features-svg.html
Normal file
123
tests/manual/clip-features-svg.html
Normal file
@@ -0,0 +1,123 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>SVG inValidRange Test Case</title><link
|
||||
href="../../theme/default/style.css"
|
||||
rel="stylesheet" type="text/css">
|
||||
<style>
|
||||
#map {
|
||||
width: 512px;
|
||||
height: 512px;
|
||||
border: 1px solid #4B3624;
|
||||
background: White;
|
||||
}
|
||||
.olControlAttribution { bottom: 0px!important }
|
||||
</style>
|
||||
<script src="../../lib/OpenLayers.js"
|
||||
type="text/javascript"></script>
|
||||
<script type="text/javascript">var map;
|
||||
|
||||
// avoid pink tiles
|
||||
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
|
||||
OpenLayers.Util.onImageLoadErrorColor = "transparent";
|
||||
|
||||
var vectorLayer;
|
||||
var markerLayer, boxes, newPoint;
|
||||
|
||||
function init(){
|
||||
var options = {
|
||||
projection: new OpenLayers.Projection("EPSG:900913"),
|
||||
units: "m",
|
||||
numZoomLevels: 19,
|
||||
maxResolution: 156543.0339,
|
||||
maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
|
||||
20037508, 20037508.34)
|
||||
};
|
||||
map = new OpenLayers.Map('map', options);
|
||||
|
||||
map.addControl(new OpenLayers.Control.MousePosition());
|
||||
|
||||
vectorLayer = new OpenLayers.Layer.Vector("Trails", {isBaseLayer: true});
|
||||
markerLayer = new OpenLayers.Layer.Markers("WayPoints");
|
||||
|
||||
map.addLayers([vectorLayer,markerLayer]);
|
||||
|
||||
var style_trail = OpenLayers.Util.extend({},
|
||||
OpenLayers.Feature.Vector.style['default']);
|
||||
style_trail.strokeColor = "green";
|
||||
style_trail.strokeWidth = 5;
|
||||
|
||||
var pointList = [];
|
||||
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653735.8487833,5726045.3578081);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653731.3960036,5726056.5070679);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653730.8394062,5726044.7207079);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653743.1958697,5726043.9243328);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653754.1051798,5726046.9505586);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653760.4503907,5726056.5070679);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653767.4635187,5726065.5857612);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653830.136392,5726052.2066375);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-13653846.5003571,5726042.3315828);
|
||||
pointList.push(newPoint);
|
||||
|
||||
var lineFeature = new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.LineString(pointList));
|
||||
lineFeature.fid = 52730;
|
||||
vectorLayer.addFeatures(lineFeature);
|
||||
|
||||
pointList = [];
|
||||
|
||||
newPoint = new OpenLayers.Geometry.Point(-12250153.3626406,4852001.6114048);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-12194315.5060664,4800503.5113048);
|
||||
pointList.push(newPoint);
|
||||
newPoint = new OpenLayers.Geometry.Point(-12180445.0975155,4873109.008858);
|
||||
pointList.push(newPoint);
|
||||
|
||||
lineFeature = new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.LineString(pointList),null,style_trail);
|
||||
lineFeature.fid = 52751;
|
||||
vectorLayer.addFeatures([lineFeature]);
|
||||
|
||||
var size = new OpenLayers.Size(15, 15);
|
||||
var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
|
||||
var icon = new OpenLayers.Icon('../../img/marker.png', size, offset);
|
||||
markerLayer.addMarker(new OpenLayers.Marker(
|
||||
new OpenLayers.LonLat((newPoint.x + 400), (newPoint.y - 400)), icon));
|
||||
|
||||
map.setCenter(new OpenLayers.LonLat(newPoint.x, newPoint.y), 13)
|
||||
}
|
||||
|
||||
function zoomToScale(zoom) {
|
||||
if (zoom == 8) map.zoomToScale(3385.5001275);
|
||||
else if(zoom == 7) map.zoomToScale(6771.000255);
|
||||
else if (zoom == 6) map.zoomToScale(13542);
|
||||
else if (zoom == 5) map.zoomToScale(27084.001020);
|
||||
else if (zoom == 4) map.zoomToScale(54168.001020);
|
||||
else if (zoom == 3) map.zoomToScale(108337);
|
||||
else if (zoom == 2) map.zoomToScale(3466752.1306573446);
|
||||
else if (zoom == 1) map.zoomToScale(13867008.522629378);
|
||||
else if (zoom == 0) map.zoomToScale(55468034.09051751);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onLoad="init()">
|
||||
<h1 id="title">SVG inValidRange Clipping Test Case</h1>
|
||||
<p>Behavior before fixing #1631: Push Zoom 5. You see lines. Push
|
||||
Zoom 6. No lines.</p>
|
||||
<div id="map">
|
||||
</div>
|
||||
<button onClick="zoomToScale(5);">Zoom 5</button>
|
||||
<button onClick="zoomToScale(6);">Zoom 6</button>
|
||||
<button onClick="zoomToScale(7);">Zoom 7</button>
|
||||
<button onClick="zoomToScale(8);">Zoom 8</button>
|
||||
</body>
|
||||
</html>
|
||||
58
tests/manual/pan-redraw-svg.html
Normal file
58
tests/manual/pan-redraw-svg.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../theme/default/style.css" type="text/css" />
|
||||
<style type="text/css">
|
||||
#map {
|
||||
width: 512px;
|
||||
height: 512px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="../../lib/OpenLayers.js"></script>
|
||||
<script type="text/javascript">
|
||||
var map, point;
|
||||
|
||||
function init(){
|
||||
var options = {
|
||||
projection: new OpenLayers.Projection("EPSG:900913"),
|
||||
displayProjection: new OpenLayers.Projection("EPSG:4326"),
|
||||
units: "m",
|
||||
maxResolution: 20, //0.07464553542137146,
|
||||
maxExtent: new OpenLayers.Bounds(-20037508, -20037508,
|
||||
20037508, 20037508.34)
|
||||
};
|
||||
map = new OpenLayers.Map('map', options);
|
||||
var vector = new OpenLayers.Layer.Vector(
|
||||
"Vectors",
|
||||
{isBaseLayer: true}
|
||||
);
|
||||
map.addLayer(vector);
|
||||
|
||||
var x = -20000;//4.33791754;
|
||||
var y = 20000;
|
||||
point = new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.Point(x, y)
|
||||
);
|
||||
|
||||
map.addLayer(vector);
|
||||
vector.addFeatures([point]);
|
||||
map.setCenter(new OpenLayers.LonLat(0, 0), 5);
|
||||
}
|
||||
|
||||
function pan(){
|
||||
map.panTo(point.geometry.getBounds().getCenterLonLat());
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<h3 id="title">SVG inValidRange Redraw Test Case</h3>
|
||||
<p>Before fixing #1631, after klicking Go! no point would have appeared. The Go! button
|
||||
pans the map over a long distance. Before dragging, the point would have been
|
||||
outside the valid range, and the pan operation would not have triggered the SVG
|
||||
coordinate system to be recreated. The new vector rendering takes care of all this. </p>
|
||||
<div id="map"></div>
|
||||
<input type="button" value="Go!" onclick="pan();"></input>
|
||||
</body>
|
||||
</html>
|
||||
@@ -73,7 +73,7 @@
|
||||
}
|
||||
|
||||
function vectorTestNew() {
|
||||
vectorLayer.renderer.drawFeature = drawFeature;
|
||||
vectorLayer.renderer.drawFeature = OpenLayers.Renderer[vectorLayer.renderer.CLASS_NAME.split(".")[2]].prototype.drawFeature;
|
||||
|
||||
console.time("addFeatures");
|
||||
vectorLayer.addFeatures(features);
|
||||
@@ -89,17 +89,25 @@
|
||||
map.addControl(new OpenLayers.Control.MousePosition());
|
||||
map.setCenter(new OpenLayers.LonLat(-22.5, -22.5), 3);
|
||||
|
||||
drawFeature = vectorLayer.renderer.drawFeature;
|
||||
|
||||
vectorLayer.events.register("featuresadded", this, nextRun);
|
||||
|
||||
features = new Array(100);
|
||||
features = new Array(200);
|
||||
var x, y
|
||||
for (var i = 0; i < 100; i++) {
|
||||
for (var i = 0; i < 200; i++) {
|
||||
x = -Math.random()*45;
|
||||
y = -Math.random()*45;
|
||||
features[i] = new OpenLayers.Feature.Vector(
|
||||
new OpenLayers.Geometry.LinearRing([
|
||||
new OpenLayers.Geometry.Point(
|
||||
-Math.random()*5+x, -Math.random()*5+y),
|
||||
new OpenLayers.Geometry.Point(
|
||||
-Math.random()*5+x, -Math.random()*5+y),
|
||||
new OpenLayers.Geometry.Point(
|
||||
-Math.random()*5+x, -Math.random()*5+y),
|
||||
new OpenLayers.Geometry.Point(
|
||||
-Math.random()*5+x, -Math.random()*5+y),
|
||||
new OpenLayers.Geometry.Point(
|
||||
-Math.random()*5+x, -Math.random()*5+y),
|
||||
new OpenLayers.Geometry.Point(
|
||||
-Math.random()*5+x, -Math.random()*5+y),
|
||||
new OpenLayers.Geometry.Point(
|
||||
@@ -119,14 +127,16 @@
|
||||
</script>
|
||||
</head>
|
||||
<body onload="init()">
|
||||
<h1 id="title">Vector Features Performance Test</h1>
|
||||
<h1 id="title">New Rendering - Vector Features Performance Test</h1>
|
||||
<div id="map"></div>
|
||||
<p>
|
||||
|
||||
This test examines if checking for a feature being inside the visible
|
||||
extent before rendering it has an impact on performance. Make sure that
|
||||
the Firebug console is visible when running this test to see the results.
|
||||
|
||||
extent before rendering it has an impact on performance. Open the Firebug
|
||||
console after running this test (hit F12) to see the results.
|
||||
<br/>
|
||||
After the performance test, you can drag around the map to see how the new
|
||||
vector rendering feels where features get rendered only when they are visible
|
||||
inside the map extent.
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user