Files
openlayers/lib/OpenLayers/Renderer/VML.js
crschmidt df65488d3a Commit #637, "add cursor property in Feature.Vector" from pgiraud, with
minor modification: because features by default do nothing at all, change
the default cursor property (keep it at null) so that users aren't confused
when clicking has no affect. Thanks for the patch.


git-svn-id: http://svn.openlayers.org/trunk/openlayers@3040 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2007-04-10 10:19:13 +00:00

449 lines
13 KiB
JavaScript

/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @class
*
* Note that for all calculations in this class, we use toFixed() to round a
* float value to an integer. This is done because it seems that VML doesn't
* support float values.
*
* @requires OpenLayers/Renderer/Elements.js
*/
OpenLayers.Renderer.VML = OpenLayers.Class.create();
OpenLayers.Renderer.VML.prototype =
OpenLayers.Class.inherit(OpenLayers.Renderer.Elements, {
/** @type String */
xmlns: "urn:schemas-microsoft-com:vml",
/**
* @constructor
*
* @param {String} containerID
*/
initialize: function(containerID) {
if (!this.supported()) {
return;
}
document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
var style = document.createStyleSheet();
style.addRule('v\\:*', "behavior: url(#default#VML); " +
"position: relative; display: inline-block;");
OpenLayers.Renderer.Elements.prototype.initialize.apply(this,
arguments);
},
/**
*
*/
destroy: function() {
OpenLayers.Renderer.Elements.prototype.destroy.apply(this, arguments);
},
/**
* @returns Whether or not the browser supports the VML renderer
* @type Boolean
*/
supported: function() {
var supported = document.namespaces;
return supported;
},
/**
* @param {OpenLayers.Bounds} extent
*/
setExtent: function(extent) {
OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,
arguments);
var resolution = this.getResolution();
var org = extent.left/resolution + " " +
extent.top/resolution;
this.root.setAttribute("coordorigin", org);
var size = extent.getWidth()/resolution + " " +
-extent.getHeight()/resolution;
this.root.setAttribute("coordsize", size);
},
/**
* Set the size of the drawing surface
*
* @param size {OpenLayers.Size} the size of the drawing surface
*/
setSize: function(size) {
OpenLayers.Renderer.prototype.setSize.apply(this, arguments);
this.rendererRoot.style.width = this.size.w;
this.rendererRoot.style.height = this.size.h;
this.root.style.width = "100%";
this.root.style.height = "100%";
},
/**
* @param geometry {OpenLayers.Geometry}
*
* @returns The corresponding node type for the specified geometry
* @type String
*/
getNodeType: function(geometry) {
var nodeType = null;
switch (geometry.CLASS_NAME) {
case "OpenLayers.Geometry.Point":
nodeType = "v:oval";
break;
case "OpenLayers.Geometry.Rectangle":
nodeType = "v:rect";
break;
case "OpenLayers.Geometry.LineString":
case "OpenLayers.Geometry.LinearRing":
case "OpenLayers.Geometry.Polygon":
case "OpenLayers.Geometry.Curve":
case "OpenLayers.Geometry.Surface":
nodeType = "v:shape";
break;
default:
break;
}
return nodeType;
},
/**
* @param {DOMElement} node
*/
reprojectNode: function(node) {
//we have to reprojectNode the entire node since the coordinates
// system has changed
this.drawGeometryNode(node);
},
/**
* Use to set all the style attributes to a VML node.
*
* @param {DOMElement} node
* @param {Object} style
* @param {Object} options
* @option isFilled {boolean}
* @option isStroked {boolean}
*/
setStyle: function(node, style, options) {
style = style || node.olStyle;
options = options || node.olOptions;
if (node.geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
this.drawCircle(node, node.geometry, style.pointRadius);
}
//fill
var fillColor = (options.isFilled) ? style.fillColor : "none";
node.setAttribute("fillcolor", fillColor);
var fills = node.getElementsByTagName("fill");
var fill = (fills.length == 0) ? null : fills[0];
if (!options.isFilled) {
if (fill) {
node.removeChild(fill);
}
} else {
if (!fill) {
fill = this.createNode('v:fill', node.id + "_fill");
node.appendChild(fill);
}
fill.setAttribute("opacity", style.fillOpacity);
}
//stroke
var strokeColor = (options.isStroked) ? style.strokeColor : "none";
node.setAttribute("strokecolor", strokeColor);
node.setAttribute("strokeweight", style.strokeWidth);
var strokes = node.getElementsByTagName("stroke");
var stroke = (strokes.length == 0) ? null : strokes[0];
if (!options.isStroked) {
if (stroke) {
node.removeChild(stroke);
}
} else {
if (!stroke) {
stroke = this.createNode('v:stroke', node.id + "_stroke");
node.appendChild(stroke);
}
stroke.setAttribute("opacity", style.strokeOpacity);
}
if (style.cursor) {
node.style.cursor = style.cursor;
}
},
/** Get the geometry's bounds, convert it to our vml coordinate system,
* then set the node's position, size, and local coordinate system.
*
* @param {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
setNodeDimension: function(node, geometry) {
var bbox = geometry.getBounds();
var resolution = this.getResolution();
var scaledBox =
new OpenLayers.Bounds((bbox.left/resolution).toFixed(),
(bbox.bottom/resolution).toFixed(),
(bbox.right/resolution).toFixed(),
(bbox.top/resolution).toFixed());
// Set the internal coordinate system to draw the path
node.style.left = scaledBox.left;
node.style.top = scaledBox.top;
node.style.width = scaledBox.getWidth();
node.style.height = scaledBox.getHeight();
node.coordorigin = scaledBox.left + " " + scaledBox.top;
node.coordsize = scaledBox.getWidth()+ " " + scaledBox.getHeight();
},
/**
* @private
*
* @param {String} type Kind of node to draw
* @param {String} id Id for node
*
* @returns A new node of the given type and id
* @type DOMElement
*/
createNode: function(type, id) {
var node = document.createElement(type);
if (id) {
node.setAttribute('id', id);
}
return node;
},
/**
* @private
*
* @param {String} type Kind of node to draw
* @param {String} id Id for node
*
* @returns Whether or not the specified node is of the specified type
* @type Boolean
*/
nodeTypeCompare: function(node, type) {
//split type
var subType = type;
var splitIndex = subType.indexOf(":");
if (splitIndex != -1) {
subType = subType.substr(splitIndex+1);
}
//split nodeName
var nodeName = node.nodeName;
splitIndex = nodeName.indexOf(":");
if (splitIndex != -1) {
nodeName = nodeName.substr(splitIndex+1);
}
return (subType == nodeName);
},
/**
* @returns The specific render engine's root element
* @type DOMElement
*/
createRenderRoot: function() {
var id = this.container.id + "_vmlRoot";
var rendererRoot = this.nodeFactory(id, "div");
return rendererRoot;
},
/**
* @returns The main root element to which we'll add vectors
* @type DOMElement
*/
createRoot: function() {
var id = this.container.id + "_root";
var root = this.nodeFactory(id, "v:group");
return root;
},
/**************************************
* *
* GEOMETRY DRAWING FUNCTIONS *
* *
**************************************/
/**
* @param {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawPoint: function(node, geometry) {
this.drawCircle(node, node.geometry, 1);
},
/** Size and Center a circle given geometry (x,y center) and radius
*
* @param {DOMElement} node
* @param {OpenLayers.Geometry} geometry
* @param {float} radius
*/
drawCircle: function(node, geometry, radius) {
var resolution = this.getResolution();
node.style.left = (geometry.x /resolution).toFixed() - radius;
node.style.top = (geometry.y /resolution).toFixed() - radius;
var diameter = radius * 2;
node.style.width = diameter;
node.style.height = diameter;
},
/**
* @param {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawLineString: function(node, geometry) {
this.drawLine(node, geometry, false);
},
/**
* @param {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawLinearRing: function(node, geometry) {
this.drawLine(node, geometry, true);
},
/**
* @param {DOMElement} node
* @param {OpenLayers.Geometry} geometry
* @param {Boolean} closeLine Close the line? (make it a ring?)
*/
drawLine: function(node, geometry, closeLine) {
this.setNodeDimension(node, geometry);
var resolution = this.getResolution();
var path = "m";
for (var i = 0; i < geometry.components.length; i++) {
var x = (geometry.components[i].x/resolution);
var y = (geometry.components[i].y/resolution);
path += " " + x.toFixed() + "," + y.toFixed() + " l ";
}
if (closeLine) {
path += " x";
}
path += " e";
node.path = path;
},
/**
* @parm {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawPolygon: function(node, geometry) {
this.setNodeDimension(node, geometry);
var resolution = this.getResolution();
var path = "";
for (var j = 0; j < geometry.components.length; j++) {
var linearRing = geometry.components[j];
path += "m";
for (var i = 0; i < linearRing.components.length; i++) {
var x = linearRing.components[i].x / resolution;
var y = linearRing.components[i].y / resolution;
path += " " + x.toFixed() + "," + y.toFixed();
if (i==0) {
path += " l";
}
}
path += " x ";
}
path += "e";
node.path = path;
},
/**
* @parm {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawRectangle: function(node, geometry) {
var resolution = this.getResolution();
node.style.left = geometry.x/resolution;
node.style.top = geometry.y/resolution;
node.style.width = geometry.width/resolution;
node.style.height = geometry.height/resolution;
},
/**
* @parm {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawCurve: function(node, geometry) {
this.setNodeDimension(node, geometry);
var resolution = this.getResolution();
var path = "";
for (var i = 0; i < geometry.components.length; i++) {
var x = geometry.components[i].x / resolution;
var y = geometry.components[i].y / resolution;
if ((i%3)==0 && (i/3)==0) {
path += "m"
} else if ((i%3)==1) {
path += " c"
}
path += " " + x + "," + y;
}
path += " x e";
node.path = path;
},
/**
* @parm {DOMElement} node
* @param {OpenLayers.Geometry} geometry
*/
drawSurface: function(node, geometry) {
this.setNodeDimension(node, geometry);
var resolution = this.getResolution();
var path = "";
for (var i = 0; i < geometry.components.length; i++) {
var x = geometry.components[i].x / resolution;
var y = geometry.components[i].y / resolution;
if ((i%3)==0 && (i/3)==0) {
path += "m";
} else if ((i%3)==1) {
path += " c";
}
path += " " + x + "," + y;
}
path += " x e";
node.path = path;
},
CLASS_NAME: "OpenLayers.Renderer.VML"
});