Merge pull request #12646 from ashchurova/fix-8136-hit-detection-custom-renderer
Support for hit detection in styles with custom rendering
This commit is contained in:
12
examples/custom-hit-detection-renderer.html
Normal file
12
examples/custom-hit-detection-renderer.html
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
layout: example.html
|
||||
title: Custom Hit Detection Render
|
||||
shortdesc: Example of a custom hit detection renderer.
|
||||
docs: >
|
||||
This example demonstrates the use of 'ol/style/Style' hitDetectionRender option function in
|
||||
detecting if pointer is over a particular feature.
|
||||
Move pointer over the label for Columbus Circle feature and see that only label is used in
|
||||
hit detection.
|
||||
tags: "circle, feature, vector, render, custom, hitDetectionRenderer"
|
||||
---
|
||||
<div id="map" class="map"></div>
|
||||
103
examples/custom-hit-detection-renderer.js
Normal file
103
examples/custom-hit-detection-renderer.js
Normal file
@@ -0,0 +1,103 @@
|
||||
import Feature from '../src/ol/Feature.js';
|
||||
import Map from '../src/ol/Map.js';
|
||||
import View from '../src/ol/View.js';
|
||||
import {Circle} from '../src/ol/geom.js';
|
||||
import {OSM, Vector as VectorSource} from '../src/ol/source.js';
|
||||
import {Style} from '../src/ol/style.js';
|
||||
import {Tile as TileLayer, Vector as VectorLayer} from '../src/ol/layer.js';
|
||||
import {fromLonLat} from '../src/ol/proj.js';
|
||||
|
||||
const columbusCircleCoords = fromLonLat([-73.98189, 40.76805]);
|
||||
const labelTextStroke = 'rgba(120, 120, 120, 1)';
|
||||
const labelText = 'Columbus Circle';
|
||||
|
||||
let pointerOverFeature = null;
|
||||
|
||||
const renderLabelText = (ctx, x, y, stroke) => {
|
||||
ctx.fillStyle = 'rgba(255,0,0,1)';
|
||||
ctx.strokeStyle = stroke;
|
||||
ctx.lineWidth = 1;
|
||||
ctx.textAlign = 'center';
|
||||
ctx.textBaseline = 'middle';
|
||||
ctx.font = `bold 30px verdana`;
|
||||
ctx.filter = 'drop-shadow(7px 7px 2px #e81)';
|
||||
ctx.fillText(labelText, x, y);
|
||||
ctx.strokeText(labelText, x, y);
|
||||
};
|
||||
|
||||
const circleFeature = new Feature({
|
||||
geometry: new Circle(columbusCircleCoords, 50),
|
||||
});
|
||||
|
||||
circleFeature.set('label-color', labelTextStroke);
|
||||
|
||||
circleFeature.setStyle(
|
||||
new Style({
|
||||
renderer(coordinates, state) {
|
||||
const [[x, y], [x1, y1]] = coordinates;
|
||||
const ctx = state.context;
|
||||
const dx = x1 - x;
|
||||
const dy = y1 - y;
|
||||
const radius = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
const innerRadius = 0;
|
||||
const outerRadius = radius * 1.4;
|
||||
|
||||
const gradient = ctx.createRadialGradient(
|
||||
x,
|
||||
y,
|
||||
innerRadius,
|
||||
x,
|
||||
y,
|
||||
outerRadius
|
||||
);
|
||||
gradient.addColorStop(0, 'rgba(255,0,0,0)');
|
||||
gradient.addColorStop(0.6, 'rgba(255,0,0,0.2)');
|
||||
gradient.addColorStop(1, 'rgba(255,0,0,0.8)');
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, radius, 0, 2 * Math.PI, true);
|
||||
ctx.fillStyle = gradient;
|
||||
ctx.fill();
|
||||
ctx.strokeStyle = 'rgba(255,0,0,1)';
|
||||
ctx.stroke();
|
||||
|
||||
renderLabelText(ctx, x, y, circleFeature.get('label-color'));
|
||||
},
|
||||
hitDetectionRenderer(coordinates, state) {
|
||||
const [x, y] = coordinates[0];
|
||||
const ctx = state.context;
|
||||
renderLabelText(ctx, x, y, circleFeature.get('label-color'));
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
const map = new Map({
|
||||
layers: [
|
||||
new TileLayer({
|
||||
source: new OSM(),
|
||||
visible: true,
|
||||
}),
|
||||
new VectorLayer({
|
||||
source: new VectorSource({
|
||||
features: [circleFeature],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
target: 'map',
|
||||
view: new View({
|
||||
center: columbusCircleCoords,
|
||||
zoom: 19,
|
||||
}),
|
||||
});
|
||||
|
||||
map.on('pointermove', (evt) => {
|
||||
const featureOver = map.forEachFeatureAtPixel(evt.pixel, (feature) => {
|
||||
feature.set('label-color', 'rgba(255,255,255,1)');
|
||||
return feature;
|
||||
});
|
||||
|
||||
if (pointerOverFeature && pointerOverFeature != featureOver) {
|
||||
pointerOverFeature.set('label-color', labelTextStroke);
|
||||
}
|
||||
pointerOverFeature = featureOver;
|
||||
});
|
||||
@@ -15,8 +15,9 @@ class VectorContext {
|
||||
* @param {import("../geom/SimpleGeometry.js").default} geometry Geometry.
|
||||
* @param {import("../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {Function} renderer Renderer.
|
||||
* @param {Function} hitDetectionRenderer Renderer.
|
||||
*/
|
||||
drawCustom(geometry, feature, renderer) {}
|
||||
drawCustom(geometry, feature, renderer, hitDetectionRenderer) {}
|
||||
|
||||
/**
|
||||
* Render a geometry.
|
||||
|
||||
@@ -247,97 +247,104 @@ class CanvasBuilder extends VectorContext {
|
||||
* @param {import("../../geom/SimpleGeometry.js").default} geometry Geometry.
|
||||
* @param {import("../../Feature.js").FeatureLike} feature Feature.
|
||||
* @param {Function} renderer Renderer.
|
||||
* @param {Function} hitDetectionRenderer Renderer.
|
||||
*/
|
||||
drawCustom(geometry, feature, renderer) {
|
||||
drawCustom(geometry, feature, renderer, hitDetectionRenderer) {
|
||||
this.beginGeometry(geometry, feature);
|
||||
|
||||
const type = geometry.getType();
|
||||
const stride = geometry.getStride();
|
||||
const builderBegin = this.coordinates.length;
|
||||
|
||||
let flatCoordinates, builderEnd, builderEnds, builderEndss;
|
||||
let offset;
|
||||
if (type == GeometryType.MULTI_POLYGON) {
|
||||
flatCoordinates =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates();
|
||||
builderEndss = [];
|
||||
const endss =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getEndss();
|
||||
offset = 0;
|
||||
for (let i = 0, ii = endss.length; i < ii; ++i) {
|
||||
const myEnds = [];
|
||||
|
||||
switch (type) {
|
||||
case GeometryType.MULTI_POLYGON:
|
||||
flatCoordinates =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates();
|
||||
builderEndss = [];
|
||||
const endss =
|
||||
/** @type {import("../../geom/MultiPolygon.js").default} */ (
|
||||
geometry
|
||||
).getEndss();
|
||||
offset = 0;
|
||||
for (let i = 0, ii = endss.length; i < ii; ++i) {
|
||||
const myEnds = [];
|
||||
offset = this.drawCustomCoordinates_(
|
||||
flatCoordinates,
|
||||
offset,
|
||||
endss[i],
|
||||
stride,
|
||||
myEnds
|
||||
);
|
||||
builderEndss.push(myEnds);
|
||||
}
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEndss,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateMultiCoordinatesArray,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEndss,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateMultiCoordinatesArray,
|
||||
]);
|
||||
break;
|
||||
case GeometryType.POLYGON:
|
||||
case GeometryType.MULTI_LINE_STRING:
|
||||
builderEnds = [];
|
||||
flatCoordinates =
|
||||
type == GeometryType.POLYGON
|
||||
? /** @type {import("../../geom/Polygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates()
|
||||
: geometry.getFlatCoordinates();
|
||||
offset = this.drawCustomCoordinates_(
|
||||
flatCoordinates,
|
||||
offset,
|
||||
endss[i],
|
||||
0,
|
||||
/** @type {import("../../geom/Polygon.js").default|import("../../geom/MultiLineString.js").default} */ (
|
||||
geometry
|
||||
).getEnds(),
|
||||
stride,
|
||||
myEnds
|
||||
builderEnds
|
||||
);
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnds,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinatesArray,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnds,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateCoordinatesArray,
|
||||
]);
|
||||
break;
|
||||
case GeometryType.LINE_STRING:
|
||||
case GeometryType.CIRCLE:
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatLineCoordinates(
|
||||
flatCoordinates,
|
||||
0,
|
||||
flatCoordinates.length,
|
||||
stride,
|
||||
false,
|
||||
false
|
||||
);
|
||||
builderEndss.push(myEnds);
|
||||
}
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEndss,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateMultiCoordinatesArray,
|
||||
]);
|
||||
} else if (
|
||||
type == GeometryType.POLYGON ||
|
||||
type == GeometryType.MULTI_LINE_STRING
|
||||
) {
|
||||
builderEnds = [];
|
||||
flatCoordinates =
|
||||
type == GeometryType.POLYGON
|
||||
? /** @type {import("../../geom/Polygon.js").default} */ (
|
||||
geometry
|
||||
).getOrientedFlatCoordinates()
|
||||
: geometry.getFlatCoordinates();
|
||||
offset = this.drawCustomCoordinates_(
|
||||
flatCoordinates,
|
||||
0,
|
||||
/** @type {import("../../geom/Polygon.js").default|import("../../geom/MultiLineString.js").default} */ (
|
||||
geometry
|
||||
).getEnds(),
|
||||
stride,
|
||||
builderEnds
|
||||
);
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnds,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinatesArray,
|
||||
]);
|
||||
} else if (
|
||||
type == GeometryType.LINE_STRING ||
|
||||
type == GeometryType.CIRCLE
|
||||
) {
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatLineCoordinates(
|
||||
flatCoordinates,
|
||||
0,
|
||||
flatCoordinates.length,
|
||||
stride,
|
||||
false,
|
||||
false
|
||||
);
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
} else if (type == GeometryType.MULTI_POINT) {
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);
|
||||
if (builderEnd > builderBegin) {
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
@@ -346,18 +353,59 @@ class CanvasBuilder extends VectorContext {
|
||||
renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
}
|
||||
} else if (type == GeometryType.POINT) {
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
|
||||
builderEnd = this.coordinates.length;
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
break;
|
||||
case GeometryType.MULTI_POINT:
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
builderEnd = this.appendFlatPointCoordinates(flatCoordinates, stride);
|
||||
|
||||
if (builderEnd > builderBegin) {
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
inflateCoordinates,
|
||||
]);
|
||||
}
|
||||
break;
|
||||
case GeometryType.POINT:
|
||||
flatCoordinates = geometry.getFlatCoordinates();
|
||||
this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
|
||||
builderEnd = this.coordinates.length;
|
||||
|
||||
this.instructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
renderer,
|
||||
]);
|
||||
this.hitDetectionInstructions.push([
|
||||
CanvasInstruction.CUSTOM,
|
||||
builderBegin,
|
||||
builderEnd,
|
||||
geometry,
|
||||
hitDetectionRenderer || renderer,
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
this.endGeometry(feature);
|
||||
}
|
||||
|
||||
@@ -208,7 +208,8 @@ function renderGeometry(replayGroup, geometry, style, feature) {
|
||||
replay.drawCustom(
|
||||
/** @type {import("../geom/SimpleGeometry.js").default} */ (geometry),
|
||||
feature,
|
||||
style.getRenderer()
|
||||
style.getRenderer(),
|
||||
style.getHitDetectionRenderer()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ import {assert} from '../asserts.js';
|
||||
* @property {import("./Image.js").default} [image] Image style.
|
||||
* @property {RenderFunction} [renderer] Custom renderer. When configured, `fill`, `stroke` and `image` will be
|
||||
* ignored, and the provided function will be called with each render frame for each geometry.
|
||||
* @property {RenderFunction} [hitDetectionRenderer] Custom renderer for hit detection. If provided will be used
|
||||
* in hit detection rendering.
|
||||
* @property {import("./Stroke.js").default} [stroke] Stroke style.
|
||||
* @property {import("./Text.js").default} [text] Text style.
|
||||
* @property {number} [zIndex] Z index.
|
||||
@@ -186,6 +188,15 @@ class Style {
|
||||
*/
|
||||
this.renderer_ = options.renderer !== undefined ? options.renderer : null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {RenderFunction|null}
|
||||
*/
|
||||
this.hitDetectionRenderer_ =
|
||||
options.hitDetectionRenderer !== undefined
|
||||
? options.hitDetectionRenderer
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import("./Stroke.js").default}
|
||||
@@ -248,6 +259,26 @@ class Style {
|
||||
this.renderer_ = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a custom renderer function for this style used
|
||||
* in hit detection.
|
||||
* @param {RenderFunction|null} renderer Custom renderer function.
|
||||
* @api
|
||||
*/
|
||||
setHitDetectionRenderer(renderer) {
|
||||
this.hitDetectionRenderer_ = renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom renderer function that was configured with
|
||||
* {@link #setHitDetectionRenderer} or the `hitDetectionRenderer` constructor option.
|
||||
* @return {RenderFunction|null} Custom renderer function.
|
||||
* @api
|
||||
*/
|
||||
getHitDetectionRenderer() {
|
||||
return this.hitDetectionRenderer_;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the geometry to be rendered.
|
||||
* @return {string|import("../geom/Geometry.js").default|GeometryFunction}
|
||||
|
||||
@@ -236,87 +236,193 @@ describe('ol.render.canvas.BuilderGroup', function () {
|
||||
expect(lineDashOffset).to.be(4);
|
||||
});
|
||||
|
||||
it('calls the renderer function configured for the style', function () {
|
||||
const calls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
describe('use renderer and hitDetectionRenderer defined in style', function () {
|
||||
let point, multipoint, linestring, multilinestring;
|
||||
let polygon, multipolygon, geometrycollection;
|
||||
|
||||
/**
|
||||
* @param {BuilderGroup} builder The builder to get instructions from.
|
||||
* @param {number} [pixelRatio] The pixel ratio.
|
||||
* @param {boolean} [overlaps] Whether there is overlaps.
|
||||
* @param {Array<number>} [coordinate] Used for hit detection.
|
||||
*/
|
||||
function executeHitDetectionForCoordinate(
|
||||
builder,
|
||||
pixelRatio,
|
||||
overlaps,
|
||||
coordinate
|
||||
) {
|
||||
const executor = new ExecutorGroup(
|
||||
[-180, -90, 180, 90],
|
||||
1,
|
||||
pixelRatio || 1,
|
||||
!!overlaps,
|
||||
builder.finish()
|
||||
);
|
||||
|
||||
executor.execute(context, 1, transform, 0, false);
|
||||
executor.forEachFeatureAtCoordinate(coordinate, 1, 0, 1, () => {});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
point = new Feature(new Point([45, 90]));
|
||||
multipoint = new Feature(
|
||||
new MultiPoint([
|
||||
[45, 90],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
linestring = new Feature(
|
||||
new LineString([
|
||||
[45, 90],
|
||||
[45, 45],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
multilinestring = new Feature(
|
||||
new MultiLineString([
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
polygon = feature1;
|
||||
multipolygon = new Feature(
|
||||
new MultiPolygon([
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
geometrycollection = new Feature(
|
||||
new GeometryCollection([
|
||||
point.getGeometry(),
|
||||
linestring.getGeometry(),
|
||||
polygon.getGeometry(),
|
||||
])
|
||||
);
|
||||
});
|
||||
it('calls the renderer function in hit detection', function () {
|
||||
const calls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
executeHitDetectionForCoordinate(builder, 1, true, [45, 90]);
|
||||
|
||||
// since renderer will be used for rendering and hit detection
|
||||
// expect calls.length to be ass twice was in rendering
|
||||
expect(calls.length).to.be(18);
|
||||
});
|
||||
|
||||
it('calls the hit detection renderer in hit detection', function () {
|
||||
const calls = [];
|
||||
const hitDetectionCalls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
hitDetectionRenderer: function (coords, state) {
|
||||
hitDetectionCalls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
executeHitDetectionForCoordinate(builder, 1, true, [45, 90]);
|
||||
expect(calls.length).to.be(9);
|
||||
expect(hitDetectionCalls.length).to.be(9);
|
||||
});
|
||||
|
||||
it('calls the renderer function configured for the style', function () {
|
||||
const calls = [];
|
||||
const style = new Style({
|
||||
renderer: function (coords, state) {
|
||||
calls.push({
|
||||
coords: coords,
|
||||
geometry: state.geometry,
|
||||
feature: state.feature,
|
||||
context: state.context,
|
||||
pixelRatio: state.pixelRatio,
|
||||
rotation: state.rotation,
|
||||
resolution: state.resolution,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
execute(builder, 1, true);
|
||||
expect(calls.length).to.be(9);
|
||||
expect(calls[0].geometry).to.be(point.getGeometry());
|
||||
expect(calls[0].feature).to.be(point);
|
||||
expect(calls[0].context).to.be(context);
|
||||
expect(calls[0].pixelRatio).to.be(1);
|
||||
expect(calls[0].rotation).to.be(0);
|
||||
expect(calls[0].resolution).to.be(1);
|
||||
expect(calls[0].coords).to.eql([4.5, 9]);
|
||||
expect(calls[1].feature).to.be(multipoint);
|
||||
expect(calls[1].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[2].feature).to.be(linestring);
|
||||
expect(calls[2].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[3].feature).to.be(multilinestring);
|
||||
expect(calls[3].coords[0][0]).to.eql([4.5, 9]);
|
||||
expect(calls[4].feature).to.be(polygon);
|
||||
expect(calls[4].coords[0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[5].feature).to.be(multipolygon);
|
||||
expect(calls[5].coords[0][0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[6].feature).to.be(geometrycollection);
|
||||
expect(calls[6].geometry.getCoordinates()).to.eql([45, 90]);
|
||||
expect(calls[7].geometry.getCoordinates()[0]).to.eql([45, 90]);
|
||||
expect(calls[8].geometry.getCoordinates()[0][0]).to.eql([-90, -45]);
|
||||
});
|
||||
const point = new Feature(new Point([45, 90]));
|
||||
const multipoint = new Feature(
|
||||
new MultiPoint([
|
||||
[45, 90],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
const linestring = new Feature(
|
||||
new LineString([
|
||||
[45, 90],
|
||||
[45, 45],
|
||||
[90, 45],
|
||||
])
|
||||
);
|
||||
const multilinestring = new Feature(
|
||||
new MultiLineString([
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
linestring.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
const polygon = feature1;
|
||||
const multipolygon = new Feature(
|
||||
new MultiPolygon([
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
polygon.getGeometry().getCoordinates(),
|
||||
])
|
||||
);
|
||||
const geometrycollection = new Feature(
|
||||
new GeometryCollection([
|
||||
point.getGeometry(),
|
||||
linestring.getGeometry(),
|
||||
polygon.getGeometry(),
|
||||
])
|
||||
);
|
||||
builder = new BuilderGroup(1, [-180, -90, 180, 90], 1, 1, true);
|
||||
renderFeature(builder, point, style, 1);
|
||||
renderFeature(builder, multipoint, style, 1);
|
||||
renderFeature(builder, linestring, style, 1);
|
||||
renderFeature(builder, multilinestring, style, 1);
|
||||
renderFeature(builder, polygon, style, 1);
|
||||
renderFeature(builder, multipolygon, style, 1);
|
||||
renderFeature(builder, geometrycollection, style, 1);
|
||||
scaleTransform(transform, 0.1, 0.1);
|
||||
execute(builder, 1, true);
|
||||
expect(calls.length).to.be(9);
|
||||
expect(calls[0].geometry).to.be(point.getGeometry());
|
||||
expect(calls[0].feature).to.be(point);
|
||||
expect(calls[0].context).to.be(context);
|
||||
expect(calls[0].pixelRatio).to.be(1);
|
||||
expect(calls[0].rotation).to.be(0);
|
||||
expect(calls[0].resolution).to.be(1);
|
||||
expect(calls[0].coords).to.eql([4.5, 9]);
|
||||
expect(calls[1].feature).to.be(multipoint);
|
||||
expect(calls[1].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[2].feature).to.be(linestring);
|
||||
expect(calls[2].coords[0]).to.eql([4.5, 9]);
|
||||
expect(calls[3].feature).to.be(multilinestring);
|
||||
expect(calls[3].coords[0][0]).to.eql([4.5, 9]);
|
||||
expect(calls[4].feature).to.be(polygon);
|
||||
expect(calls[4].coords[0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[5].feature).to.be(multipolygon);
|
||||
expect(calls[5].coords[0][0][0]).to.eql([-9, -4.5]);
|
||||
expect(calls[6].feature).to.be(geometrycollection);
|
||||
expect(calls[6].geometry.getCoordinates()).to.eql([45, 90]);
|
||||
expect(calls[7].geometry.getCoordinates()[0]).to.eql([45, 90]);
|
||||
expect(calls[8].geometry.getCoordinates()[0][0]).to.eql([-90, -45]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user