Only create custom style for text we actually render

This commit is contained in:
Andreas Hocevar
2017-08-04 22:54:14 +02:00
parent 617151c8ff
commit 35f22fb52c
2 changed files with 54 additions and 63 deletions

View File

@@ -28,20 +28,18 @@ var style = new ol.style.Style({
renderer: function(coords, context) { renderer: function(coords, context) {
var feature = context.feature; var feature = context.feature;
var text = feature.get('name'); var text = feature.get('name');
if (text) { // Only create label when geometry has a long and straight segment
// Only create label when geometry has a long and straight segment var path = labelSegment(coords, Math.PI / 8, measureText(text));
var path = labelSegment(coords, Math.PI / 8, measureText(text)); if (path) {
if (path) { extent = ol.extent.createEmpty();
extent = ol.extent.createEmpty(); letters = [];
letters = []; textPath(text, path, measureText, collectDrawData);
textPath(text, path, measureText, collectDrawData); ol.extent.buffer(extent, 5 * pixelRatio, extent);
ol.extent.buffer(extent, 5 * pixelRatio, extent); var bounds = {
var bounds = { bottomLeft: ol.extent.getBottomLeft(extent),
bottomLeft: ol.extent.getBottomLeft(extent), topRight: ol.extent.getTopRight(extent)
topRight: ol.extent.getTopRight(extent) };
}; labelEngine.ingestLabel(bounds, feature.getId(), 1, letters, text, false);
labelEngine.ingestLabel(bounds, feature.getId(), 1, letters, text, false);
}
} }
} }
}); });
@@ -70,7 +68,7 @@ fetch('https://overpass-api.de/api/interpreter', {
var vectorLayer = new ol.layer.Vector({ var vectorLayer = new ol.layer.Vector({
source: source, source: source,
style: function(feature) { style: function(feature) {
if (feature.getGeometry().getType() == 'LineString') { if (feature.getGeometry().getType() == 'LineString' && feature.get('text')) {
return style; return style;
} }
} }

View File

@@ -4,7 +4,6 @@ goog.require('ol.Map');
goog.require('ol.View'); goog.require('ol.View');
goog.require('ol.extent'); goog.require('ol.extent');
goog.require('ol.format.GeoJSON'); goog.require('ol.format.GeoJSON');
goog.require('ol.geom.Point');
goog.require('ol.layer.Vector'); goog.require('ol.layer.Vector');
goog.require('ol.source.Vector'); goog.require('ol.source.Vector');
goog.require('ol.style.Fill'); goog.require('ol.style.Fill');
@@ -58,26 +57,43 @@ function sortByWidth(a, b) {
return ol.extent.getWidth(b.getExtent()) - ol.extent.getWidth(a.getExtent()); return ol.extent.getWidth(b.getExtent()) - ol.extent.getWidth(a.getExtent());
} }
var resolution; // This is set by the map's precompose listener var labelStyle = new ol.style.Style({
var styles = [ renderer: function(coords, state) {
new ol.style.Style({ var text = state.feature.get('name');
fill: new ol.style.Fill({ createLabel(textCache[text], text, coords);
color: 'rgba(255, 255, 255, 0.6)' }
}), });
stroke: new ol.style.Stroke({ var countryStyle = new ol.style.Style({
color: '#319FD3', fill: new ol.style.Fill({
width: 1 color: 'rgba(255, 255, 255, 0.6)'
})
}), }),
new ol.style.Style({ stroke: new ol.style.Stroke({
renderer: function(coords, state) { color: '#319FD3',
var pixelRatio = state.pixelRatio; width: 1
var text = state.feature.get('name'); })
var canvas = textCache[text]; });
if (!canvas) { var styleWithLabel = [countryStyle, labelStyle];
var styleWithoutLabel = [countryStyle];
var pixelRatio; // This is set by the map's precompose listener
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'data/geojson/countries.geojson',
format: new ol.format.GeoJSON()
}),
style: function(feature, resolution) {
var text = feature.get('name');
var width = textMeasureContext.measureText(text).width;
var geometry = feature.getGeometry();
if (geometry.getType() == 'MultiPolygon') {
geometry = geometry.getPolygons().sort(sortByWidth)[0];
}
var extentWidth = ol.extent.getWidth(geometry.getExtent());
if (extentWidth / resolution > width) {
// Only consider label when it fits its geometry's extent
if (!(text in textCache)) {
// Draw the label to its own canvas and cache it. // Draw the label to its own canvas and cache it.
var width = textMeasureContext.measureText(text).width; var canvas = textCache[text] = document.createElement('CANVAS');
canvas = textCache[text] = document.createElement('CANVAS');
canvas.width = width * pixelRatio; canvas.width = width * pixelRatio;
canvas.height = height * pixelRatio; canvas.height = height * pixelRatio;
var context = canvas.getContext('2d'); var context = canvas.getContext('2d');
@@ -86,38 +102,15 @@ var styles = [
context.strokeText(text, 0, 0); context.strokeText(text, 0, 0);
context.fillText(text, 0, 0); context.fillText(text, 0, 0);
} }
// The 3rd value of the coordinate is the measure of the extent width labelStyle.setGeometry(geometry.getInteriorPoint());
var extentWidth = state.geometry.getCoordinates()[2] / resolution * pixelRatio; return styleWithLabel;
if (extentWidth > canvas.width) { } else {
// Only consider labels not wider than their country's bounding box return styleWithoutLabel;
createLabel(canvas, text, coord);
}
},
// Geometry function to determine label positions
geometry: function(feature) {
var geometry = feature.getGeometry();
if (geometry.getType() == 'MultiPolygon') {
var geometries = geometry.getPolygons();
geometry = geometries.sort(sortByWidth)[0];
}
var coordinates = geometry.getInteriorPoint().getCoordinates();
var extentWidth = ol.extent.getWidth(geometry.getExtent());
// We are using the extentWidth as measure value of the geometry
coordinates.push(extentWidth);
return new ol.geom.Point(coordinates, 'XYM');
} }
}) }
];
var vectorLayer = new ol.layer.Vector({
source: new ol.source.Vector({
url: 'data/geojson/countries.geojson',
format: new ol.format.GeoJSON()
}),
style: styles
}); });
vectorLayer.on('precompose', function(e) { vectorLayer.on('precompose', function(e) {
resolution = e.frameState.viewState.resolution; pixelRatio = e.frameState.pixelRatio;
labelEngine.destroy(); labelEngine.destroy();
}); });
vectorLayer.on('postcompose', function(e) { vectorLayer.on('postcompose', function(e) {