Allow styles to configure a custom renderer

Two new examples show how custom renderers can be used to render text along
paths, and to declutter labels using 3rd party libraries.
This commit is contained in:
Andreas Hocevar
2017-07-15 00:06:35 +02:00
parent 2258c00fca
commit c6b942f185
21 changed files with 762 additions and 72 deletions

View File

@@ -4,6 +4,8 @@ goog.require('ol');
goog.require('ol.array');
goog.require('ol.extent');
goog.require('ol.extent.Relationship');
goog.require('ol.geom.GeometryType');
goog.require('ol.geom.flat.inflate');
goog.require('ol.geom.flat.transform');
goog.require('ol.has');
goog.require('ol.obj');
@@ -174,6 +176,75 @@ ol.render.canvas.Replay.prototype.appendFlatCoordinates = function(flatCoordinat
};
/**
* @param {Array.<number>} flatCoordinates Flat coordinates.
* @param {number} offset Offset.
* @param {Array.<number>} ends Ends.
* @param {number} stride Stride.
* @param {Array.<number>} replayEnds Replay ends.
* @return {number} Offset.
*/
ol.render.canvas.Replay.prototype.drawCustomCoordinates_ = function(flatCoordinates, offset, ends, stride, replayEnds) {
for (var i = 0, ii = ends.length; i < ii; ++i) {
var end = ends[i];
var replayEnd = this.appendFlatCoordinates(flatCoordinates, offset, end, stride, false, false);
replayEnds.push(replayEnd);
offset = end;
}
return offset;
};
/**
* @inheritDoc.
*/
ol.render.canvas.Replay.prototype.drawCustom = function(geometry, feature, renderer) {
this.beginGeometry(geometry, feature);
var type = geometry.getType();
var stride = geometry.getStride();
var replayBegin = this.coordinates.length;
var flatCoordinates, replayEnd, replayEnds, replayEndss;
var offset;
if (type == ol.geom.GeometryType.MULTI_POLYGON) {
geometry = /** @type {ol.geom.MultiPolygon} */ (geometry);
flatCoordinates = geometry.getOrientedFlatCoordinates();
replayEndss = [];
var endss = geometry.getEndss();
offset = 0;
for (var i = 0, ii = endss.length; i < ii; ++i) {
var myEnds = [];
offset = this.drawCustomCoordinates_(flatCoordinates, offset, endss[i], stride, myEnds);
replayEndss.push(myEnds);
}
this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
replayBegin, replayEndss, geometry, renderer, ol.geom.flat.inflate.coordinatesss]);
} else if (type == ol.geom.GeometryType.POLYGON || type == ol.geom.GeometryType.MULTI_LINE_STRING) {
replayEnds = [];
flatCoordinates = (type == ol.geom.GeometryType.POLYGON) ?
/** @type {ol.geom.Polygon} */ (geometry).getOrientedFlatCoordinates() :
geometry.getFlatCoordinates();
offset = this.drawCustomCoordinates_(flatCoordinates, 0,
/** @type {ol.geom.Polygon|ol.geom.MultiLineString} */ (geometry).getEnds(),
stride, replayEnds);
this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
replayBegin, replayEnds, geometry, renderer, ol.geom.flat.inflate.coordinatess]);
} else if (type == ol.geom.GeometryType.LINE_STRING || type == ol.geom.GeometryType.MULTI_POINT) {
flatCoordinates = geometry.getFlatCoordinates();
replayEnd = this.appendFlatCoordinates(
flatCoordinates, 0, flatCoordinates.length, stride, false, false);
this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
replayBegin, replayEnd, geometry, renderer, ol.geom.flat.inflate.coordinates]);
} else if (type == ol.geom.GeometryType.POINT) {
flatCoordinates = geometry.getFlatCoordinates();
this.coordinates.push(flatCoordinates[0], flatCoordinates[1]);
replayEnd = this.coordinates.length;
this.instructions.push([ol.render.canvas.Instruction.CUSTOM,
replayBegin, replayEnd, geometry, renderer]);
}
this.endGeometry(geometry, feature);
};
/**
* @protected
* @param {ol.geom.Geometry|ol.render.Feature} geometry Geometry.
@@ -249,6 +320,17 @@ ol.render.canvas.Replay.prototype.replay_ = function(
var prevX, prevY, roundX, roundY;
var pendingFill = 0;
var pendingStroke = 0;
/**
* @type {olx.render.State}
*/
var replayState = {
context: context,
pixelRatio: pixelRatio,
resolution: this.resolution,
rotation: viewRotation
};
// When the batch size gets too big, performance decreases. 200 is a good
// balance between batch size and number of fill/stroke instructions.
var batchSize =
@@ -303,6 +385,21 @@ ol.render.canvas.Replay.prototype.replay_ = function(
context.closePath();
++i;
break;
case ol.render.canvas.Instruction.CUSTOM:
d = /** @type {number} */ (instruction[1]);
dd = instruction[2];
var geometry = /** @type {ol.geom.SimpleGeometry} */ (instruction[3]);
var renderer = instruction[4];
var coords;
if (instruction.length == 6) {
var fn = instruction[5];
coords = fn(pixelCoordinates, d, dd, 2, geometry.getRenderCoordinates());
} else {
coords = pixelCoordinates.slice(d, dd);
}
renderer(coords, geometry, feature, replayState);
++i;
break;
case ol.render.canvas.Instruction.DRAW_IMAGE:
d = /** @type {number} */ (instruction[1]);
dd = /** @type {number} */ (instruction[2]);