diff options
Diffstat (limited to 'misc/openlayers/lib/OpenLayers/Renderer/Canvas.js')
-rw-r--r-- | misc/openlayers/lib/OpenLayers/Renderer/Canvas.js | 906 |
1 files changed, 0 insertions, 906 deletions
diff --git a/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js b/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js deleted file mode 100644 index 61a327c..0000000 --- a/misc/openlayers/lib/OpenLayers/Renderer/Canvas.js +++ /dev/null @@ -1,906 +0,0 @@ -/* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for - * full list of contributors). Published under the 2-clause BSD license. - * See license.txt in the OpenLayers distribution or repository for the - * full text of the license. */ - -/** - * @requires OpenLayers/Renderer.js - */ - -/** - * Class: OpenLayers.Renderer.Canvas - * A renderer based on the 2D 'canvas' drawing element. - * - * Inherits: - * - <OpenLayers.Renderer> - */ -OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, { - - /** - * APIProperty: hitDetection - * {Boolean} Allow for hit detection of features. Default is true. - */ - hitDetection: true, - - /** - * Property: hitOverflow - * {Number} The method for converting feature identifiers to color values - * supports 16777215 sequential values. Two features cannot be - * predictably detected if their identifiers differ by more than this - * value. The hitOverflow allows for bigger numbers (but the - * difference in values is still limited). - */ - hitOverflow: 0, - - /** - * Property: canvas - * {Canvas} The canvas context object. - */ - canvas: null, - - /** - * Property: features - * {Object} Internal object of feature/style pairs for use in redrawing the layer. - */ - features: null, - - /** - * Property: pendingRedraw - * {Boolean} The renderer needs a redraw call to render features added while - * the renderer was locked. - */ - pendingRedraw: false, - - /** - * Property: cachedSymbolBounds - * {Object} Internal cache of calculated symbol extents. - */ - cachedSymbolBounds: {}, - - /** - * Constructor: OpenLayers.Renderer.Canvas - * - * Parameters: - * containerID - {<String>} - * options - {Object} Optional properties to be set on the renderer. - */ - initialize: function(containerID, options) { - OpenLayers.Renderer.prototype.initialize.apply(this, arguments); - this.root = document.createElement("canvas"); - this.container.appendChild(this.root); - this.canvas = this.root.getContext("2d"); - this.features = {}; - if (this.hitDetection) { - this.hitCanvas = document.createElement("canvas"); - this.hitContext = this.hitCanvas.getContext("2d"); - } - }, - - /** - * Method: setExtent - * Set the visible part of the layer. - * - * 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() { - OpenLayers.Renderer.prototype.setExtent.apply(this, arguments); - // always redraw features - return false; - }, - - /** - * Method: eraseGeometry - * Erase a geometry from the renderer. Because the Canvas renderer has - * 'memory' of the features that it has drawn, we have to remove the - * feature so it doesn't redraw. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * featureId - {String} - */ - eraseGeometry: function(geometry, featureId) { - this.eraseFeatures(this.features[featureId][0]); - }, - - /** - * APIMethod: supported - * - * Returns: - * {Boolean} Whether or not the browser supports the renderer class - */ - supported: function() { - return OpenLayers.CANVAS_SUPPORTED; - }, - - /** - * Method: setSize - * Sets the size of the drawing surface. - * - * Once the size is updated, redraw the canvas. - * - * Parameters: - * size - {<OpenLayers.Size>} - */ - setSize: function(size) { - this.size = size.clone(); - var root = this.root; - root.style.width = size.w + "px"; - root.style.height = size.h + "px"; - root.width = size.w; - root.height = size.h; - this.resolution = null; - if (this.hitDetection) { - var hitCanvas = this.hitCanvas; - hitCanvas.style.width = size.w + "px"; - hitCanvas.style.height = size.h + "px"; - hitCanvas.width = size.w; - hitCanvas.height = size.h; - } - }, - - /** - * Method: drawFeature - * Draw the feature. Stores the feature in the features list, - * then redraws the layer. - * - * Parameters: - * feature - {<OpenLayers.Feature.Vector>} - * style - {<Object>} - * - * Returns: - * {Boolean} The feature has been drawn completely. If the feature has no - * geometry, undefined will be returned. If the feature is not rendered - * for other reasons, false will be returned. - */ - drawFeature: function(feature, style) { - var rendered; - if (feature.geometry) { - style = this.applyDefaultSymbolizer(style || feature.style); - // don't render if display none or feature outside extent - var bounds = feature.geometry.getBounds(); - - var worldBounds; - if (this.map.baseLayer && this.map.baseLayer.wrapDateLine) { - worldBounds = this.map.getMaxExtent(); - } - - var intersects = bounds && bounds.intersectsBounds(this.extent, {worldBounds: worldBounds}); - - rendered = (style.display !== "none") && !!bounds && intersects; - if (rendered) { - // keep track of what we have rendered for redraw - this.features[feature.id] = [feature, style]; - } - else { - // remove from features tracked for redraw - delete(this.features[feature.id]); - } - this.pendingRedraw = true; - } - if (this.pendingRedraw && !this.locked) { - this.redraw(); - this.pendingRedraw = false; - } - return rendered; - }, - - /** - * Method: drawGeometry - * Used when looping (in redraw) over the features; draws - * the canvas. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - */ - drawGeometry: function(geometry, style, featureId) { - var className = geometry.CLASS_NAME; - if ((className == "OpenLayers.Geometry.Collection") || - (className == "OpenLayers.Geometry.MultiPoint") || - (className == "OpenLayers.Geometry.MultiLineString") || - (className == "OpenLayers.Geometry.MultiPolygon")) { - for (var i = 0; i < geometry.components.length; i++) { - this.drawGeometry(geometry.components[i], style, featureId); - } - return; - } - switch (geometry.CLASS_NAME) { - case "OpenLayers.Geometry.Point": - this.drawPoint(geometry, style, featureId); - break; - case "OpenLayers.Geometry.LineString": - this.drawLineString(geometry, style, featureId); - break; - case "OpenLayers.Geometry.LinearRing": - this.drawLinearRing(geometry, style, featureId); - break; - case "OpenLayers.Geometry.Polygon": - this.drawPolygon(geometry, style, featureId); - break; - default: - break; - } - }, - - /** - * Method: drawExternalGraphic - * Called to draw External graphics. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - * featureId - {String} - */ - drawExternalGraphic: function(geometry, style, featureId) { - var img = new Image(); - - var title = style.title || style.graphicTitle; - if (title) { - img.title = title; - } - - 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 onLoad = function() { - if(!this.features[featureId]) { - return; - } - var pt = this.getLocalXY(geometry); - var p0 = pt[0]; - var p1 = pt[1]; - if(!isNaN(p0) && !isNaN(p1)) { - var x = (p0 + xOffset) | 0; - var y = (p1 + yOffset) | 0; - var canvas = this.canvas; - canvas.globalAlpha = opacity; - var factor = OpenLayers.Renderer.Canvas.drawImageScaleFactor || - (OpenLayers.Renderer.Canvas.drawImageScaleFactor = - /android 2.1/.test(navigator.userAgent.toLowerCase()) ? - // 320 is the screen width of the G1 phone, for - // which drawImage works out of the box. - 320 / window.screen.width : 1 - ); - canvas.drawImage( - img, x*factor, y*factor, width*factor, height*factor - ); - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId); - this.hitContext.fillRect(x, y, width, height); - } - } - }; - - img.onload = OpenLayers.Function.bind(onLoad, this); - img.src = style.externalGraphic; - }, - - /** - * Method: drawNamedSymbol - * Called to draw Well Known Graphic Symbol Name. - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - * featureId - {String} - */ - drawNamedSymbol: function(geometry, style, featureId) { - var x, y, cx, cy, i, symbolBounds, scaling, angle; - var unscaledStrokeWidth; - var deg2rad = Math.PI / 180.0; - - var symbol = OpenLayers.Renderer.symbol[style.graphicName]; - - if (!symbol) { - throw new Error(style.graphicName + ' is not a valid symbol name'); - } - - if (!symbol.length || symbol.length < 2) return; - - var pt = this.getLocalXY(geometry); - var p0 = pt[0]; - var p1 = pt[1]; - - if (isNaN(p0) || isNaN(p1)) return; - - // Use rounded line caps - this.canvas.lineCap = "round"; - this.canvas.lineJoin = "round"; - - if (this.hitDetection) { - this.hitContext.lineCap = "round"; - this.hitContext.lineJoin = "round"; - } - - // Scale and rotate symbols, using precalculated bounds whenever possible. - if (style.graphicName in this.cachedSymbolBounds) { - symbolBounds = this.cachedSymbolBounds[style.graphicName]; - } else { - symbolBounds = new OpenLayers.Bounds(); - for(i = 0; i < symbol.length; i+=2) { - symbolBounds.extend(new OpenLayers.LonLat(symbol[i], symbol[i+1])); - } - this.cachedSymbolBounds[style.graphicName] = symbolBounds; - } - - // Push symbol scaling, translation and rotation onto the transformation stack in reverse order. - // Don't forget to apply all canvas transformations to the hitContext canvas as well(!) - this.canvas.save(); - if (this.hitDetection) { this.hitContext.save(); } - - // Step 3: place symbol at the desired location - this.canvas.translate(p0,p1); - if (this.hitDetection) { this.hitContext.translate(p0,p1); } - - // Step 2a. rotate the symbol if necessary - angle = deg2rad * style.rotation; // will be NaN when style.rotation is undefined. - if (!isNaN(angle)) { - this.canvas.rotate(angle); - if (this.hitDetection) { this.hitContext.rotate(angle); } - } - - // // Step 2: scale symbol such that pointRadius equals half the maximum symbol dimension. - scaling = 2.0 * style.pointRadius / Math.max(symbolBounds.getWidth(), symbolBounds.getHeight()); - this.canvas.scale(scaling,scaling); - if (this.hitDetection) { this.hitContext.scale(scaling,scaling); } - - // Step 1: center the symbol at the origin - cx = symbolBounds.getCenterLonLat().lon; - cy = symbolBounds.getCenterLonLat().lat; - this.canvas.translate(-cx,-cy); - if (this.hitDetection) { this.hitContext.translate(-cx,-cy); } - - // Don't forget to scale stroke widths, because they are affected by canvas scale transformations as well(!) - // Alternative: scale symbol coordinates manually, so stroke width scaling is not needed anymore. - unscaledStrokeWidth = style.strokeWidth; - style.strokeWidth = unscaledStrokeWidth / scaling; - - if (style.fill !== false) { - this.setCanvasStyle("fill", style); - this.canvas.beginPath(); - for (i=0; i<symbol.length; i=i+2) { - x = symbol[i]; - y = symbol[i+1]; - if (i == 0) this.canvas.moveTo(x,y); - this.canvas.lineTo(x,y); - } - this.canvas.closePath(); - this.canvas.fill(); - - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId, style); - this.hitContext.beginPath(); - for (i=0; i<symbol.length; i=i+2) { - x = symbol[i]; - y = symbol[i+1]; - if (i == 0) this.canvas.moveTo(x,y); - this.hitContext.lineTo(x,y); - } - this.hitContext.closePath(); - this.hitContext.fill(); - } - } - - if (style.stroke !== false) { - this.setCanvasStyle("stroke", style); - this.canvas.beginPath(); - for (i=0; i<symbol.length; i=i+2) { - x = symbol[i]; - y = symbol[i+1]; - if (i == 0) this.canvas.moveTo(x,y); - this.canvas.lineTo(x,y); - } - this.canvas.closePath(); - this.canvas.stroke(); - - - if (this.hitDetection) { - this.setHitContextStyle("stroke", featureId, style, scaling); - this.hitContext.beginPath(); - for (i=0; i<symbol.length; i=i+2) { - x = symbol[i]; - y = symbol[i+1]; - if (i == 0) this.hitContext.moveTo(x,y); - this.hitContext.lineTo(x,y); - } - this.hitContext.closePath(); - this.hitContext.stroke(); - } - - } - - style.strokeWidth = unscaledStrokeWidth; - this.canvas.restore(); - if (this.hitDetection) { this.hitContext.restore(); } - this.setCanvasStyle("reset"); - }, - - /** - * Method: setCanvasStyle - * Prepare the canvas for drawing by setting various global settings. - * - * Parameters: - * type - {String} one of 'stroke', 'fill', or 'reset' - * style - {Object} Symbolizer hash - */ - setCanvasStyle: function(type, style) { - if (type === "fill") { - this.canvas.globalAlpha = style['fillOpacity']; - this.canvas.fillStyle = style['fillColor']; - } else if (type === "stroke") { - this.canvas.globalAlpha = style['strokeOpacity']; - this.canvas.strokeStyle = style['strokeColor']; - this.canvas.lineWidth = style['strokeWidth']; - } else { - this.canvas.globalAlpha = 0; - this.canvas.lineWidth = 1; - } - }, - - /** - * Method: featureIdToHex - * Convert a feature ID string into an RGB hex string. - * - * Parameters: - * featureId - {String} Feature id - * - * Returns: - * {String} RGB hex string. - */ - featureIdToHex: function(featureId) { - var id = Number(featureId.split("_").pop()) + 1; // zero for no feature - if (id >= 16777216) { - this.hitOverflow = id - 16777215; - id = id % 16777216 + 1; - } - var hex = "000000" + id.toString(16); - var len = hex.length; - hex = "#" + hex.substring(len-6, len); - return hex; - }, - - /** - * Method: setHitContextStyle - * Prepare the hit canvas for drawing by setting various global settings. - * - * Parameters: - * type - {String} one of 'stroke', 'fill', or 'reset' - * featureId - {String} The feature id. - * symbolizer - {<OpenLayers.Symbolizer>} The symbolizer. - */ - setHitContextStyle: function(type, featureId, symbolizer, strokeScaling) { - var hex = this.featureIdToHex(featureId); - if (type == "fill") { - this.hitContext.globalAlpha = 1.0; - this.hitContext.fillStyle = hex; - } else if (type == "stroke") { - this.hitContext.globalAlpha = 1.0; - this.hitContext.strokeStyle = hex; - // bump up stroke width to deal with antialiasing. If strokeScaling is defined, we're rendering a symbol - // on a transformed canvas, so the antialias width bump has to scale as well. - if (typeof strokeScaling === "undefined") { - this.hitContext.lineWidth = symbolizer.strokeWidth + 2; - } else { - if (!isNaN(strokeScaling)) { this.hitContext.lineWidth = symbolizer.strokeWidth + 2.0 / strokeScaling; } - } - } else { - this.hitContext.globalAlpha = 0; - this.hitContext.lineWidth = 1; - } - }, - - /** - * Method: drawPoint - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - * featureId - {String} - */ - drawPoint: function(geometry, style, featureId) { - if(style.graphic !== false) { - if(style.externalGraphic) { - this.drawExternalGraphic(geometry, style, featureId); - } else if (style.graphicName && (style.graphicName != "circle")) { - this.drawNamedSymbol(geometry, style, featureId); - } else { - var pt = this.getLocalXY(geometry); - var p0 = pt[0]; - var p1 = pt[1]; - if(!isNaN(p0) && !isNaN(p1)) { - var twoPi = Math.PI*2; - var radius = style.pointRadius; - if(style.fill !== false) { - this.setCanvasStyle("fill", style); - this.canvas.beginPath(); - this.canvas.arc(p0, p1, radius, 0, twoPi, true); - this.canvas.fill(); - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId, style); - this.hitContext.beginPath(); - this.hitContext.arc(p0, p1, radius, 0, twoPi, true); - this.hitContext.fill(); - } - } - - if(style.stroke !== false) { - this.setCanvasStyle("stroke", style); - this.canvas.beginPath(); - this.canvas.arc(p0, p1, radius, 0, twoPi, true); - this.canvas.stroke(); - if (this.hitDetection) { - this.setHitContextStyle("stroke", featureId, style); - this.hitContext.beginPath(); - this.hitContext.arc(p0, p1, radius, 0, twoPi, true); - this.hitContext.stroke(); - } - this.setCanvasStyle("reset"); - } - } - } - } - }, - - /** - * Method: drawLineString - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - * featureId - {String} - */ - drawLineString: function(geometry, style, featureId) { - style = OpenLayers.Util.applyDefaults({fill: false}, style); - this.drawLinearRing(geometry, style, featureId); - }, - - /** - * Method: drawLinearRing - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - * featureId - {String} - */ - drawLinearRing: function(geometry, style, featureId) { - if (style.fill !== false) { - this.setCanvasStyle("fill", style); - this.renderPath(this.canvas, geometry, style, featureId, "fill"); - if (this.hitDetection) { - this.setHitContextStyle("fill", featureId, style); - this.renderPath(this.hitContext, geometry, style, featureId, "fill"); - } - } - if (style.stroke !== false) { - this.setCanvasStyle("stroke", style); - this.renderPath(this.canvas, geometry, style, featureId, "stroke"); - if (this.hitDetection) { - this.setHitContextStyle("stroke", featureId, style); - this.renderPath(this.hitContext, geometry, style, featureId, "stroke"); - } - } - this.setCanvasStyle("reset"); - }, - - /** - * Method: renderPath - * Render a path with stroke and optional fill. - */ - renderPath: function(context, geometry, style, featureId, type) { - var components = geometry.components; - var len = components.length; - context.beginPath(); - var start = this.getLocalXY(components[0]); - var x = start[0]; - var y = start[1]; - if (!isNaN(x) && !isNaN(y)) { - context.moveTo(start[0], start[1]); - for (var i=1; i<len; ++i) { - var pt = this.getLocalXY(components[i]); - context.lineTo(pt[0], pt[1]); - } - if (type === "fill") { - context.fill(); - } else { - context.stroke(); - } - } - }, - - /** - * Method: drawPolygon - * This method is only called by the renderer itself. - * - * Parameters: - * geometry - {<OpenLayers.Geometry>} - * style - {Object} - * featureId - {String} - */ - drawPolygon: function(geometry, style, featureId) { - var components = geometry.components; - var len = components.length; - this.drawLinearRing(components[0], style, featureId); - // erase inner rings - for (var i=1; i<len; ++i) { - /** - * Note that this is overly agressive. Here we punch holes through - * all previously rendered features on the same canvas. A better - * solution for polygons with interior rings would be to draw the - * polygon on a sketch canvas first. We could erase all holes - * there and then copy the drawing to the layer canvas. - * TODO: http://trac.osgeo.org/openlayers/ticket/3130 - */ - this.canvas.globalCompositeOperation = "destination-out"; - if (this.hitDetection) { - this.hitContext.globalCompositeOperation = "destination-out"; - } - this.drawLinearRing( - components[i], - OpenLayers.Util.applyDefaults({stroke: false, fillOpacity: 1.0}, style), - featureId - ); - this.canvas.globalCompositeOperation = "source-over"; - if (this.hitDetection) { - this.hitContext.globalCompositeOperation = "source-over"; - } - this.drawLinearRing( - components[i], - OpenLayers.Util.applyDefaults({fill: false}, style), - featureId - ); - } - }, - - /** - * Method: drawText - * This method is only called by the renderer itself. - * - * Parameters: - * location - {<OpenLayers.Point>} - * style - {Object} - */ - drawText: function(location, style) { - var pt = this.getLocalXY(location); - - this.setCanvasStyle("reset"); - this.canvas.fillStyle = style.fontColor; - this.canvas.globalAlpha = style.fontOpacity || 1.0; - var fontStyle = [style.fontStyle ? style.fontStyle : "normal", - "normal", // "font-variant" not supported - style.fontWeight ? style.fontWeight : "normal", - style.fontSize ? style.fontSize : "1em", - style.fontFamily ? style.fontFamily : "sans-serif"].join(" "); - var labelRows = style.label.split('\n'); - var numRows = labelRows.length; - if (this.canvas.fillText) { - // HTML5 - this.canvas.font = fontStyle; - this.canvas.textAlign = - OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]] || - "center"; - this.canvas.textBaseline = - OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[1]] || - "middle"; - var vfactor = - OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]]; - if (vfactor == null) { - vfactor = -.5; - } - var lineHeight = - this.canvas.measureText('Mg').height || - this.canvas.measureText('xx').width; - pt[1] += lineHeight*vfactor*(numRows-1); - for (var i = 0; i < numRows; i++) { - if (style.labelOutlineWidth) { - this.canvas.save(); - this.canvas.globalAlpha = style.labelOutlineOpacity || style.fontOpacity || 1.0; - this.canvas.strokeStyle = style.labelOutlineColor; - this.canvas.lineWidth = style.labelOutlineWidth; - this.canvas.strokeText(labelRows[i], pt[0], pt[1] + (lineHeight*i) + 1); - this.canvas.restore(); - } - this.canvas.fillText(labelRows[i], pt[0], pt[1] + (lineHeight*i)); - } - } else if (this.canvas.mozDrawText) { - // Mozilla pre-Gecko1.9.1 (<FF3.1) - this.canvas.mozTextStyle = fontStyle; - // No built-in text alignment, so we measure and adjust the position - var hfactor = - OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[0]]; - if (hfactor == null) { - hfactor = -.5; - } - var vfactor = - OpenLayers.Renderer.Canvas.LABEL_FACTOR[style.labelAlign[1]]; - if (vfactor == null) { - vfactor = -.5; - } - var lineHeight = this.canvas.mozMeasureText('xx'); - pt[1] += lineHeight*(1 + (vfactor*numRows)); - for (var i = 0; i < numRows; i++) { - var x = pt[0] + (hfactor*this.canvas.mozMeasureText(labelRows[i])); - var y = pt[1] + (i*lineHeight); - this.canvas.translate(x, y); - this.canvas.mozDrawText(labelRows[i]); - this.canvas.translate(-x, -y); - } - } - this.setCanvasStyle("reset"); - }, - - /** - * Method: getLocalXY - * transform geographic xy into pixel xy - * - * Parameters: - * point - {<OpenLayers.Geometry.Point>} - */ - getLocalXY: function(point) { - var resolution = this.getResolution(); - var extent = this.extent; - var x = ((point.x - this.featureDx) / resolution + (-extent.left / resolution)); - var y = ((extent.top / resolution) - point.y / resolution); - return [x, y]; - }, - - /** - * Method: clear - * Clear all vectors from the renderer. - */ - clear: function() { - var height = this.root.height; - var width = this.root.width; - this.canvas.clearRect(0, 0, width, height); - this.features = {}; - if (this.hitDetection) { - this.hitContext.clearRect(0, 0, width, height); - } - }, - - /** - * Method: getFeatureIdFromEvent - * Returns a feature id from an event on the renderer. - * - * Parameters: - * evt - {<OpenLayers.Event>} - * - * Returns: - * {<OpenLayers.Feature.Vector} A feature or undefined. This method returns a - * feature instead of a feature id to avoid an unnecessary lookup on the - * layer. - */ - getFeatureIdFromEvent: function(evt) { - var featureId, feature; - - if (this.hitDetection && this.root.style.display !== "none") { - // this dragging check should go in the feature handler - if (!this.map.dragging) { - var xy = evt.xy; - var x = xy.x | 0; - var y = xy.y | 0; - var data = this.hitContext.getImageData(x, y, 1, 1).data; - if (data[3] === 255) { // antialiased - var id = data[2] + (256 * (data[1] + (256 * data[0]))); - if (id) { - featureId = "OpenLayers_Feature_Vector_" + (id - 1 + this.hitOverflow); - try { - feature = this.features[featureId][0]; - } catch(err) { - // Because of antialiasing on the canvas, when the hit location is at a point where the edge of - // one symbol intersects the interior of another symbol, a wrong hit color (and therefore id) results. - // todo: set Antialiasing = 'off' on the hitContext as soon as browsers allow it. - } - } - } - } - } - return feature; - }, - - /** - * Method: eraseFeatures - * This is called by the layer to erase features; removes the feature from - * the list, then redraws the layer. - * - * Parameters: - * features - {Array(<OpenLayers.Feature.Vector>)} - */ - eraseFeatures: function(features) { - if(!(OpenLayers.Util.isArray(features))) { - features = [features]; - } - for(var i=0; i<features.length; ++i) { - delete this.features[features[i].id]; - } - this.redraw(); - }, - - /** - * Method: redraw - * The real 'meat' of the function: any time things have changed, - * redraw() can be called to loop over all the data and (you guessed - * it) redraw it. Unlike Elements-based Renderers, we can't interact - * with things once they're drawn, to remove them, for example, so - * instead we have to just clear everything and draw from scratch. - */ - redraw: function() { - if (!this.locked) { - var height = this.root.height; - var width = this.root.width; - this.canvas.clearRect(0, 0, width, height); - if (this.hitDetection) { - this.hitContext.clearRect(0, 0, width, height); - } - var labelMap = []; - var feature, geometry, style; - var worldBounds = (this.map.baseLayer && this.map.baseLayer.wrapDateLine) && this.map.getMaxExtent(); - for (var id in this.features) { - if (!this.features.hasOwnProperty(id)) { continue; } - feature = this.features[id][0]; - geometry = feature.geometry; - this.calculateFeatureDx(geometry.getBounds(), worldBounds); - style = this.features[id][1]; - this.drawGeometry(geometry, style, feature.id); - if(style.label) { - labelMap.push([feature, style]); - } - } - var item; - for (var i=0, len=labelMap.length; i<len; ++i) { - item = labelMap[i]; - this.drawText(item[0].geometry.getCentroid(), item[1]); - } - } - }, - - CLASS_NAME: "OpenLayers.Renderer.Canvas" -}); - -/** - * Constant: OpenLayers.Renderer.Canvas.LABEL_ALIGN - * {Object} - */ -OpenLayers.Renderer.Canvas.LABEL_ALIGN = { - "l": "left", - "r": "right", - "t": "top", - "b": "bottom" -}; - -/** - * Constant: OpenLayers.Renderer.Canvas.LABEL_FACTOR - * {Object} - */ -OpenLayers.Renderer.Canvas.LABEL_FACTOR = { - "l": 0, - "r": -1, - "t": 0, - "b": -1 -}; - -/** - * Constant: OpenLayers.Renderer.Canvas.drawImageScaleFactor - * {Number} Scale factor to apply to the canvas drawImage arguments. This - * is always 1 except for Android 2.1 devices, to work around - * http://code.google.com/p/android/issues/detail?id=5141. - */ -OpenLayers.Renderer.Canvas.drawImageScaleFactor = null; |