Merge pull request #296 from ajkopinga/canvas-edge-hit2

added hit detection for symbol edges to canvas renderer with unit tests
This commit is contained in:
ahocevar
2012-03-12 06:12:57 -07:00
2 changed files with 45 additions and 5 deletions

View File

@@ -322,6 +322,11 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
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];
@@ -393,9 +398,7 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
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];
@@ -404,6 +407,21 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
}
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;
@@ -465,7 +483,7 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
* featureId - {String} The feature id.
* symbolizer - {<OpenLayers.Symbolizer>} The symbolizer.
*/
setHitContextStyle: function(type, featureId, symbolizer) {
setHitContextStyle: function(type, featureId, symbolizer, strokeScaling) {
var hex = this.featureIdToHex(featureId);
if (type == "fill") {
this.hitContext.globalAlpha = 1.0;
@@ -473,8 +491,13 @@ OpenLayers.Renderer.Canvas = OpenLayers.Class(OpenLayers.Renderer, {
} else if (type == "stroke") {
this.hitContext.globalAlpha = 1.0;
this.hitContext.strokeStyle = hex;
// bump up stroke width to deal with antialiasing
this.hitContext.lineWidth = symbolizer.strokeWidth + 2;
// 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;

View File

@@ -304,6 +304,17 @@
),
new OpenLayers.Feature.Vector(
OpenLayers.Geometry.fromWKT("POLYGON((100 -25, 150 -25, 150 25, 100 25, 100 -25), (120 -5, 130 -5, 130 5, 120 5, 120 -5))")
),
new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(80, 0), {}, {
graphicName: "square",
pointRadius: 8,
strokeWidth: 4,
fillColor: "red",
fillOpacity: 0.5,
strokeColor: "blue",
strokeOpacity: 0.75
}
)
]);
@@ -327,6 +338,12 @@
msg: "inside polygon hole", x: 125, y: 0, id: null
}, {
msg: "outside polygon", x: 155, y: 0, id: null
}, {
msg: "inside symbol", x: 80, y: 0, id: layer.features[3].id
}, {
msg: "outside symbol interior, inside symbol edge", x: 90, y: 8, id: layer.features[3].id
}, {
msg: "outside symbol", x: 94, y: 0, id: null
}];
function px(x, y) {