Files
openlayers/tests/Renderer/Canvas.html
Arjen Kopinga a836224a14 added hit detection for symbol edges to canvas renderer with unit tests
Added unit tests for hit detection on invisible canvas layer

simplified unit test for hit detection on invisible canvas
2012-03-06 14:12:53 +01:00

502 lines
15 KiB
HTML

<html>
<head>
<script src="../OLLoader.js"></script>
<script type="text/javascript">
var supported = OpenLayers.Renderer.Canvas.prototype.supported();
var map, layer;
function setUp() {
map = new OpenLayers.Map("map");
layer = new OpenLayers.Layer.Vector(null, {
isBaseLayer: true,
renderers: ["Canvas"]
});
map.addLayer(layer);
map.setCenter(new OpenLayers.LonLat(0, 0));
}
function tearDown() {
map.destroy();
map = null;
layer = null;
}
function test_Renderer_Canvas_constructor(t) {
if (!supported) { t.plan(0); return; }
t.plan(2);
var el = document.body;
el.id = "foo";
var r = new OpenLayers.Renderer.Canvas(el.id);
t.ok(r instanceof OpenLayers.Renderer.Canvas, "new OpenLayers.Renderer.Canvas returns Renderer.Canvas object" );
t.ok(r.container == el, "renderer container is correctly set");
r.destroy();
}
function test_Renderer_Canvas_setextent(t) {
if (!supported) { t.plan(0); return; }
t.plan(2);
setUp();
var r = layer.renderer;
var extent = new OpenLayers.Bounds(1,2,3,4);
r.resolution = 1;
r.setExtent(extent, true);
t.ok(r.extent.equals(extent), "extent is correctly set");
t.eq(r.resolution, null, "resolution nullified");
tearDown();
}
function test_Renderer_Canvas_setsize(t) {
if (!supported) { t.plan(0); return; }
t.plan(2);
var el = document.body;
el.id = "foo";
var r = new OpenLayers.Renderer.Canvas(el.id);
var size = new OpenLayers.Size(1,2);
r.resolution = 1;
r.setSize(size);
t.ok(r.size.equals(size), "size is correctly set");
t.eq(r.resolution, null, "resolution nullified");
r.destroy();
}
function test_Renderer_Canvas_getresolution(t) {
if (!supported) { t.plan(0); return; }
t.plan(2);
var el = document.body;
el.id = "foo";
var r = new OpenLayers.Renderer.Canvas(el.id);
var map = new OpenLayers.Map("map");
r.map = map;
var resolution = r.getResolution();
t.eq(resolution, map.getResolution(), "resolution matches the map resolution");
t.eq(r.resolution, resolution, "resolution is correctly set");
map.destroy();
}
function test_featureIdToHex(t) {
if (!supported) {
t.plan(0);
return;
}
t.plan(2);
var el = document.body;
el.id = "foo";
var renderer = new OpenLayers.Renderer.Canvas(el.id);
var cases = [{
id: "foo_0", hex: "#000001"
}, {
id: "foo_10", hex: "#00000b"
}, {
id: "foo_100", hex: "#000065"
}, {
id: "foo_1000000", hex: "#0f4241"
}, {
id: "foo_16777214", hex: "#ffffff"
}, {
id: "foo_16777215", hex: "#000001"
}];
t.plan(cases.length);
var c;
for (var i=0; i<cases.length; ++i) {
c = cases[i];
t.eq(renderer.featureIdToHex(c.id), c.hex, c.id);
}
renderer.destroy();
}
function test_Renderer_Canvas_destroy(t) {
if (!supported) { t.plan(0); return; }
t.plan(5);
var el = document.body;
el.id = "foo";
var r = new OpenLayers.Renderer.Canvas(el.id);
r.container = document.createElement("div");
r.extent = new OpenLayers.Bounds(1,2,3,4);
r.size = new OpenLayers.Size(1,2);
r.resolution = 1;
r.map = {};
r.destroy();
t.eq(r.container, null, "container nullified");
t.eq(r.extent, null, "extent nullified");
t.eq(r.size, null, "size nullified");
t.eq(r.resolution, null, "resolution nullified");
t.eq(r.map, null, "map nullified");
}
function test_drawFeature(t) {
if (!supported) {
t.plan(0);
return;
}
t.plan(10);
setUp();
var renderer = layer.renderer;
var count = 0;
var redraw = layer.renderer.redraw;
renderer.redraw = function() {
++count;
redraw.apply(this, arguments);
}
var exp;
// a) draw a point feature
count = 0;
exp = renderer.drawFeature(
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0, 0)), {}
);
t.eq(exp, true, "a) drawFeature returns true");
t.eq(count, 1, "a) redraw called once after drawing a point feature");
renderer.clear();
// b) draw one feature with no geometry
count = 0;
exp = renderer.drawFeature(
new OpenLayers.Feature.Vector(), {}
);
t.eq(exp, undefined, "b) drawFeature returns undefined");
t.eq(count, 0, "b) redraw is not called when drawing a feature with no geometry");
renderer.clear();
// c) draw a point feature with display "none"
count = 0;
exp = renderer.drawFeature(
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1, 0)),
{display: "none"}
);
t.eq(exp, false, "c) drawFeature returns false");
t.eq(count, 1, "c) redraw is called when drawing a feature with display 'none'");
renderer.clear();
// d) draw a point feature outside renderer extent
count = 0;
exp = renderer.drawFeature(
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(-1000, 0)), {}
);
t.eq(exp, false, "d) drawFeature returns false");
t.eq(count, 1, "d) redraw is called when drawing a feature outside renderer extent");
renderer.clear();
// e) draw a polygon feature without bounds
count = 0;
exp = renderer.drawFeature(
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon()), {}
);
t.eq(exp, false, "d) drawFeature returns false");
t.eq(count, 1, "d) redraw is called when drawing a feature without bounds");
renderer.clear();
tearDown();
}
function test_pendingRedraw(t) {
if (!supported) {
t.plan(0);
return;
}
t.plan(4);
var layer = new OpenLayers.Layer.Vector(null, {
isBaseLayer: true,
renderers: ["Canvas"]
});
var map = new OpenLayers.Map({
div: "map",
controls: [],
layers: [layer],
center: new OpenLayers.LonLat(0, 0),
zoom: 0
});
var count = 0;
var redraw = layer.renderer.redraw;
layer.renderer.redraw = function() {
++count;
redraw.apply(this, arguments);
}
// add one point feature and confirm redraw is called once
count = 0;
layer.addFeatures([
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0, 0))
]);
t.eq(count, 1, "redraw called once after adding one point feature");
// add one feature with no geometry and confirm redraw is not called
count = 0;
layer.addFeatures([
new OpenLayers.Feature.Vector()
]);
t.eq(count, 0, "redraw is not called when adding a feature with no geometry");
// add one point feature, one feature with no geom, and one point feature and confirm redraw is called once
count = 0;
layer.addFeatures([
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1, 0)),
new OpenLayers.Feature.Vector(),
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0, 1))
]);
t.eq(count, 1, "redraw called once after adding three features where middle one has no geometry");
// add two point features and one feature with no geom, and confirm redraw is called once
count = 0;
layer.addFeatures([
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(1, 0)),
new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(0, 1)),
new OpenLayers.Feature.Vector()
]);
t.eq(count, 1, "redraw called once after adding three features where last one has no geometry");
map.destroy();
}
function test_hitDetection(t) {
if (!supported) {
t.plan(0);
return;
}
var layer = new OpenLayers.Layer.Vector(null, {
isBaseLayer: true,
resolutions: [1],
styleMap: new OpenLayers.StyleMap({
pointRadius: 5,
strokeWidth: 3,
fillColor: "red",
fillOpacity: 0.5,
strokeColor: "blue",
strokeOpacity: 0.75
}),
renderers: ["Canvas"]
});
var map = new OpenLayers.Map({
div: "map",
controls: [],
layers: [layer],
center: new OpenLayers.LonLat(0, 0),
zoom: 0
});
layer.addFeatures([
new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(-100, 0)
),
new OpenLayers.Feature.Vector(
OpenLayers.Geometry.fromWKT("LINESTRING(-50 0, 50 0)")
),
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: 5,
strokeWidth: 3,
fillColor: "red",
fillOpacity: 0.5,
strokeColor: "blue",
strokeOpacity: 0.75
}
)
]);
var cases = [{
msg: "center of point", x: -100, y: 0, id: layer.features[0].id
}, {
msg: "edge of point", x: -103, y: 3, id: layer.features[0].id
}, {
msg: "outside point", x: -110, y: 3, id: null
}, {
msg: "center of line", x: 0, y: 0, id: layer.features[1].id
}, {
msg: "edge of line", x: 0, y: 1, id: layer.features[1].id
}, {
msg: "outside line", x: 0, y: 5, id: null
}, {
msg: "inside polygon", x: 110, y: 0, id: layer.features[2].id
}, {
msg: "edge of polygon", x: 99, y: 0, id: layer.features[2].id
}, {
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: 86, y: 6, id: layer.features[3].id
}, {
msg: "outside symbol", x: 90, y: 0, id: null
}];
function px(x, y) {
return map.getPixelFromLonLat(
new OpenLayers.LonLat(x, y)
);
}
var num = cases.length;
t.plan(2 * num);
var c, feature;
for (var i=0; i<num; ++i) {
c = cases[i];
feature = layer.renderer.getFeatureIdFromEvent({xy: px(c.x, c.y)});
t.eq(feature && feature.id, c.id, c.msg);
// Extra test: hit detection on an invisible canvas should return undefined
layer.setVisibility(false);
feature = layer.renderer.getFeatureIdFromEvent({xy: px(c.x, c.y)});
t.eq(feature, undefined, c.msg + ' (invisible)');
layer.setVisibility(true);
}
map.destroy();
}
// see http://trac.osgeo.org/openlayers/ticket/3264
function test_externalGraphic_destroyFeatures(t) {
if (!supported) {
t.plan(0);
return;
}
t.plan(1);
// set up
var layer = new OpenLayers.Layer.Vector(null, {
isBaseLayer: true,
renderers: ["Canvas"]
});
var map = new OpenLayers.Map({
div: "map",
controls: [],
layers: [layer],
center: new OpenLayers.LonLat(0, 0),
zoom: 0
});
layer.addFeatures([
new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(0, 0),
null,
{
externalGraphic: '../../img/marker.png',
graphicHeight: 20,
graphicWidth: 20
}
)
]);
var called = false;
layer.renderer.canvas.drawImage = function(img, x, y, w, h) {
called = true;
};
// test
// schedule a canvas.drawImage
layer.renderer.redraw();
// destroy the feature before drawImage gets called
layer.destroyFeatures();
t.delay_call(0.1, function() {
t.ok(!called,
'canvas.drawImage not called if feature is destroyed');
// tear down
map.destroy();
});
}
// see http://trac.osgeo.org/openlayers/ticket/3264
function test_externalGraphic_moveTo(t) {
if (!supported) {
t.plan(0);
return;
}
t.plan(2);
// set up
var layer = new OpenLayers.Layer.Vector(null, {
isBaseLayer: true,
renderers: ["Canvas"]
});
var map = new OpenLayers.Map({
div: "map",
controls: [],
layers: [layer],
center: new OpenLayers.LonLat(0, 0),
zoom: 0
});
var feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(0, 0),
null,
{
externalGraphic: '../../img/marker.png',
graphicHeight: 20,
graphicWidth: 20,
graphicXOffset: 0,
graphicYOffset: 0
}
);
layer.addFeatures([feature]);
// test
// delay_call to let the first drawImage (the one
// resulting from addFeatures) run
t.delay_call(0.1, function() {
var log = [];
layer.renderer.canvas.drawImage = function(img, x, y, w, h) {
log.push({x: x, y: y});
};
layer.renderer.redraw();
map.setCenter(new OpenLayers.LonLat(45, 0), 0);
t.delay_call(0.1, function() {
t.eq(log.length, 2,
"canvas.drawImage called twice");
t.ok(log[0].x == log[1].x && log[0].y == log[1].y,
"image drawn at the same location");
// tear down
map.destroy();
});
});
}
</script>
</head>
<body>
<div id="map" style="width:500px;height:550px"></div>
</body>
</html>