Rendering vector layers
This commit is contained in:
@@ -9,6 +9,7 @@ goog.require('ol.Size');
|
|||||||
goog.require('ol.layer.TileLayer');
|
goog.require('ol.layer.TileLayer');
|
||||||
goog.require('ol.renderer.Map');
|
goog.require('ol.renderer.Map');
|
||||||
goog.require('ol.renderer.canvas.TileLayer');
|
goog.require('ol.renderer.canvas.TileLayer');
|
||||||
|
goog.require('ol.renderer.canvas.VectorLayer');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -60,6 +61,8 @@ goog.inherits(ol.renderer.canvas.Map, ol.renderer.Map);
|
|||||||
ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) {
|
ol.renderer.canvas.Map.prototype.createLayerRenderer = function(layer) {
|
||||||
if (layer instanceof ol.layer.TileLayer) {
|
if (layer instanceof ol.layer.TileLayer) {
|
||||||
return new ol.renderer.canvas.TileLayer(this, layer);
|
return new ol.renderer.canvas.TileLayer(this, layer);
|
||||||
|
} else if (layer instanceof ol.layer.Vector) {
|
||||||
|
return new ol.renderer.canvas.VectorLayer(this, layer);
|
||||||
} else {
|
} else {
|
||||||
goog.asserts.assert(false);
|
goog.asserts.assert(false);
|
||||||
return null;
|
return null;
|
||||||
@@ -141,6 +144,8 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
|
|||||||
context.globalAlpha = 1;
|
context.globalAlpha = 1;
|
||||||
context.fillRect(0, 0, size.width, size.height);
|
context.fillRect(0, 0, size.width, size.height);
|
||||||
|
|
||||||
|
this.calculateMatrices2D(frameState);
|
||||||
|
|
||||||
goog.array.forEach(frameState.layersArray, function(layer) {
|
goog.array.forEach(frameState.layersArray, function(layer) {
|
||||||
|
|
||||||
var layerState = frameState.layerStates[goog.getUid(layer)];
|
var layerState = frameState.layerStates[goog.getUid(layer)];
|
||||||
@@ -172,6 +177,4 @@ ol.renderer.canvas.Map.prototype.renderFrame = function(frameState) {
|
|||||||
this.renderedVisible_ = true;
|
this.renderedVisible_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.calculateMatrices2D(frameState);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ goog.require('ol.style.LiteralLine');
|
|||||||
goog.require('ol.style.LiteralPoint');
|
goog.require('ol.style.LiteralPoint');
|
||||||
goog.require('ol.style.LiteralPolygon');
|
goog.require('ol.style.LiteralPolygon');
|
||||||
goog.require('ol.style.LiteralShape');
|
goog.require('ol.style.LiteralShape');
|
||||||
|
goog.require('ol.style.LiteralSymbolizer');
|
||||||
goog.require('ol.style.ShapeType');
|
goog.require('ol.style.ShapeType');
|
||||||
|
|
||||||
|
|
||||||
@@ -26,8 +27,8 @@ ol.renderer.canvas.isSupported = ol.canvas.isSupported;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {!HTMLCanvasElement} canvas Target canvas.
|
* @param {HTMLCanvasElement} canvas Target canvas.
|
||||||
* @param {!goog.vec.Mat4.Number} transform Transform.
|
* @param {goog.vec.Mat4.Number} transform Transform.
|
||||||
* @param {ol.Pixel=} opt_offset Pixel offset for top-left corner. This is
|
* @param {ol.Pixel=} opt_offset Pixel offset for top-left corner. This is
|
||||||
* provided as an optional argument as a convenience in cases where the
|
* provided as an optional argument as a convenience in cases where the
|
||||||
* transform applies to a separate canvas.
|
* transform applies to a separate canvas.
|
||||||
@@ -39,6 +40,11 @@ ol.renderer.canvas.Renderer = function(canvas, transform, opt_offset) {
|
|||||||
dx = goog.isDef(opt_offset) ? opt_offset.x : 0,
|
dx = goog.isDef(opt_offset) ? opt_offset.x : 0,
|
||||||
dy = goog.isDef(opt_offset) ? opt_offset.y : 0;
|
dy = goog.isDef(opt_offset) ? opt_offset.y : 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {goog.vec.Mat4.Number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.transform_ = transform;
|
||||||
context.setTransform(
|
context.setTransform(
|
||||||
goog.vec.Mat4.getElement(transform, 0, 0),
|
goog.vec.Mat4.getElement(transform, 0, 0),
|
||||||
goog.vec.Mat4.getElement(transform, 1, 0),
|
goog.vec.Mat4.getElement(transform, 1, 0),
|
||||||
@@ -47,6 +53,15 @@ ol.renderer.canvas.Renderer = function(canvas, transform, opt_offset) {
|
|||||||
goog.vec.Mat4.getElement(transform, 0, 3) + dx,
|
goog.vec.Mat4.getElement(transform, 0, 3) + dx,
|
||||||
goog.vec.Mat4.getElement(transform, 1, 3) + dy);
|
goog.vec.Mat4.getElement(transform, 1, 3) + dy);
|
||||||
|
|
||||||
|
var vec = [1, 0, 0];
|
||||||
|
goog.vec.Mat4.multVec3NoTranslate(transform, vec, vec);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {number}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
this.inverseScale_ = 1 / Math.sqrt(vec[0] * vec[0] + vec[1] * vec[1]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {CanvasRenderingContext2D}
|
* @type {CanvasRenderingContext2D}
|
||||||
* @private
|
* @private
|
||||||
@@ -57,22 +72,52 @@ ol.renderer.canvas.Renderer = function(canvas, transform, opt_offset) {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<ol.geom.LineString>} lines Line array.
|
* @param {ol.geom.GeometryType} type Geometry type.
|
||||||
* @param {ol.style.LiteralLine} symbolizer Line symbolizer.
|
* @param {Array.<ol.Feature>} features Array of features.
|
||||||
|
* @param {ol.style.LiteralSymbolizer} symbolizer Symbolizer.
|
||||||
*/
|
*/
|
||||||
ol.renderer.canvas.Renderer.prototype.renderLineStrings =
|
ol.renderer.canvas.Renderer.prototype.renderFeaturesByGeometryType =
|
||||||
function(lines, symbolizer) {
|
function(type, features, symbolizer) {
|
||||||
|
switch (type) {
|
||||||
|
case ol.geom.GeometryType.POINT:
|
||||||
|
goog.asserts.assert(symbolizer instanceof ol.style.LiteralPoint);
|
||||||
|
this.renderPointFeatures_(
|
||||||
|
features, /** @type {ol.style.LiteralPoint} */ (symbolizer));
|
||||||
|
break;
|
||||||
|
case ol.geom.GeometryType.LINESTRING:
|
||||||
|
goog.asserts.assert(symbolizer instanceof ol.style.LiteralLine);
|
||||||
|
this.renderLineStringFeatures_(
|
||||||
|
features, /** @type {ol.style.LiteralLine} */ (symbolizer));
|
||||||
|
break;
|
||||||
|
case ol.geom.GeometryType.POLYGON:
|
||||||
|
goog.asserts.assert(symbolizer instanceof ol.style.LiteralPolygon);
|
||||||
|
this.renderPolygonFeatures_(
|
||||||
|
features, /** @type {ol.style.LiteralPolygon} */ (symbolizer));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Error('Rendering not implemented for geometry type: ' + type);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array.<ol.Feature>} features Array of line features.
|
||||||
|
* @param {ol.style.LiteralLine} symbolizer Line symbolizer.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ol.renderer.canvas.Renderer.prototype.renderLineStringFeatures_ =
|
||||||
|
function(features, symbolizer) {
|
||||||
|
|
||||||
var context = this.context_,
|
var context = this.context_,
|
||||||
i, ii, line, coords, dim, j, jj, x, y;
|
i, ii, line, coords, dim, j, jj, x, y;
|
||||||
|
|
||||||
context.globalAlpha = symbolizer.opacity;
|
context.globalAlpha = symbolizer.opacity;
|
||||||
context.strokeStyle = symbolizer.strokeStyle;
|
context.strokeStyle = symbolizer.strokeStyle;
|
||||||
context.lineWidth = symbolizer.strokeWidth;
|
context.lineWidth = symbolizer.strokeWidth * this.inverseScale_;
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
|
|
||||||
for (i = 0, ii = lines.length; i < ii; ++i) {
|
for (i = 0, ii = features.length; i < ii; ++i) {
|
||||||
line = lines[i];
|
line = features[i].getGeometry();
|
||||||
dim = line.dimension;
|
dim = line.dimension;
|
||||||
coords = line.coordinates;
|
coords = line.coordinates;
|
||||||
for (j = 0, jj = coords.length; j < jj; j += dim) {
|
for (j = 0, jj = coords.length; j < jj; j += dim) {
|
||||||
@@ -91,14 +136,15 @@ ol.renderer.canvas.Renderer.prototype.renderLineStrings =
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<ol.geom.Point>} points Point array.
|
* @param {Array.<ol.Feature>} features Array of point features.
|
||||||
* @param {ol.style.LiteralPoint} symbolizer Point symbolizer.
|
* @param {ol.style.LiteralPoint} symbolizer Point symbolizer.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.renderer.canvas.Renderer.prototype.renderPoints =
|
ol.renderer.canvas.Renderer.prototype.renderPointFeatures_ =
|
||||||
function(points, symbolizer) {
|
function(features, symbolizer) {
|
||||||
|
|
||||||
var context = this.context_,
|
var context = this.context_,
|
||||||
canvas, i, ii, coords;
|
canvas, i, ii, coords, vec;
|
||||||
|
|
||||||
if (symbolizer instanceof ol.style.LiteralShape) {
|
if (symbolizer instanceof ol.style.LiteralShape) {
|
||||||
canvas = ol.renderer.canvas.Renderer.renderShape(symbolizer);
|
canvas = ol.renderer.canvas.Renderer.renderShape(symbolizer);
|
||||||
@@ -108,22 +154,25 @@ ol.renderer.canvas.Renderer.prototype.renderPoints =
|
|||||||
|
|
||||||
var mid = canvas.width / 2;
|
var mid = canvas.width / 2;
|
||||||
context.save();
|
context.save();
|
||||||
context.translate(-mid, -mid);
|
context.setTransform(1, 0, 0, 1, -mid, -mid);
|
||||||
context.globalAlpha = 1;
|
context.globalAlpha = 1;
|
||||||
for (i = 0, ii = points.length; i < ii; ++i) {
|
for (i = 0, ii = features.length; i < ii; ++i) {
|
||||||
coords = points[i].coordinates;
|
coords = features[i].getGeometry().coordinates;
|
||||||
context.drawImage(canvas, coords[0], coords[1]);
|
vec = goog.vec.Mat4.multVec3(
|
||||||
|
this.transform_, [coords[0], coords[1], 0], []);
|
||||||
|
context.drawImage(canvas, vec[0], vec[1]);
|
||||||
}
|
}
|
||||||
context.restore();
|
context.restore();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<ol.geom.Polygon>} polygons Array of polygons.
|
* @param {Array.<ol.Feature>} features Array of polygon features.
|
||||||
* @param {ol.style.LiteralPolygon} symbolizer Polygon symbolizer.
|
* @param {ol.style.LiteralPolygon} symbolizer Polygon symbolizer.
|
||||||
|
* @private
|
||||||
*/
|
*/
|
||||||
ol.renderer.canvas.Renderer.prototype.renderPolygons =
|
ol.renderer.canvas.Renderer.prototype.renderPolygonFeatures_ =
|
||||||
function(polygons, symbolizer) {
|
function(features, symbolizer) {
|
||||||
|
|
||||||
var context = this.context_,
|
var context = this.context_,
|
||||||
strokeStyle = symbolizer.strokeStyle,
|
strokeStyle = symbolizer.strokeStyle,
|
||||||
@@ -133,7 +182,7 @@ ol.renderer.canvas.Renderer.prototype.renderPolygons =
|
|||||||
context.globalAlpha = symbolizer.opacity;
|
context.globalAlpha = symbolizer.opacity;
|
||||||
if (strokeStyle) {
|
if (strokeStyle) {
|
||||||
context.strokeStyle = symbolizer.strokeStyle;
|
context.strokeStyle = symbolizer.strokeStyle;
|
||||||
context.lineWidth = symbolizer.strokeWidth;
|
context.lineWidth = symbolizer.strokeWidth * this.inverseScale_;
|
||||||
}
|
}
|
||||||
if (fillStyle) {
|
if (fillStyle) {
|
||||||
context.fillStyle = fillStyle;
|
context.fillStyle = fillStyle;
|
||||||
@@ -147,8 +196,8 @@ ol.renderer.canvas.Renderer.prototype.renderPolygons =
|
|||||||
* 4) holes - render polygon to sketch canvas first
|
* 4) holes - render polygon to sketch canvas first
|
||||||
*/
|
*/
|
||||||
context.beginPath();
|
context.beginPath();
|
||||||
for (i = 0, ii = polygons.length; i < ii; ++i) {
|
for (i = 0, ii = features.length; i < ii; ++i) {
|
||||||
poly = polygons[i];
|
poly = features[i].getGeometry();
|
||||||
dim = poly.dimension;
|
dim = poly.dimension;
|
||||||
rings = poly.rings;
|
rings = poly.rings;
|
||||||
numRings = rings.length;
|
numRings = rings.length;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
goog.provide('ol.renderer.canvas.VectorLayer');
|
goog.provide('ol.renderer.canvas.VectorLayer');
|
||||||
|
|
||||||
goog.require('goog.vec.Mat4');
|
goog.require('goog.vec.Mat4');
|
||||||
|
goog.require('ol.filter.Geometry');
|
||||||
|
goog.require('ol.geom.GeometryType');
|
||||||
goog.require('ol.layer.Vector');
|
goog.require('ol.layer.Vector');
|
||||||
|
|
||||||
|
|
||||||
@@ -38,6 +40,19 @@ ol.renderer.canvas.VectorLayer = function(mapRenderer, layer) {
|
|||||||
* @type {!goog.vec.Mat4.Number}
|
* @type {!goog.vec.Mat4.Number}
|
||||||
*/
|
*/
|
||||||
this.transform_ = goog.vec.Mat4.createNumber();
|
this.transform_ = goog.vec.Mat4.createNumber();
|
||||||
|
goog.vec.Mat4.makeIdentity(this.transform_);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Geometry filters in rendering order.
|
||||||
|
* @private
|
||||||
|
* @type {Array.<ol.filter.Geometry>}
|
||||||
|
* TODO: deal with multis
|
||||||
|
*/
|
||||||
|
this.geometryFilters_ = [
|
||||||
|
new ol.filter.Geometry(ol.geom.GeometryType.POLYGON),
|
||||||
|
new ol.filter.Geometry(ol.geom.GeometryType.LINESTRING),
|
||||||
|
new ol.filter.Geometry(ol.geom.GeometryType.POINT)
|
||||||
|
];
|
||||||
|
|
||||||
};
|
};
|
||||||
goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);
|
goog.inherits(ol.renderer.canvas.VectorLayer, ol.renderer.canvas.Layer);
|
||||||
@@ -72,4 +87,76 @@ ol.renderer.canvas.VectorLayer.prototype.getTransform = function() {
|
|||||||
*/
|
*/
|
||||||
ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
ol.renderer.canvas.VectorLayer.prototype.renderFrame =
|
||||||
function(frameState, layerState) {
|
function(frameState, layerState) {
|
||||||
|
|
||||||
|
var view2DState = frameState.view2DState;
|
||||||
|
|
||||||
|
var layer = this.getVectorLayer();
|
||||||
|
var source = layer.getVectorSource();
|
||||||
|
var extent = frameState.extent;
|
||||||
|
|
||||||
|
var canvasSize = frameState.size;
|
||||||
|
|
||||||
|
var canvas, context;
|
||||||
|
if (goog.isNull(this.canvas_)) {
|
||||||
|
canvas = /** @type {HTMLCanvasElement} */
|
||||||
|
(goog.dom.createElement(goog.dom.TagName.CANVAS));
|
||||||
|
canvas.width = canvasSize.width;
|
||||||
|
canvas.height = canvasSize.height;
|
||||||
|
context = /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d'));
|
||||||
|
this.canvas_ = canvas;
|
||||||
|
this.canvasSize_ = canvasSize;
|
||||||
|
this.context_ = context;
|
||||||
|
} else {
|
||||||
|
canvas = this.canvas_;
|
||||||
|
context = this.context_;
|
||||||
|
// force clear the canvas
|
||||||
|
canvas.width = canvasSize.width;
|
||||||
|
canvas.height = canvasSize.height;
|
||||||
|
this.canvasSize_ = canvasSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For now, we create a canvas renderer and have it render all features with
|
||||||
|
* every call to renderFrame.
|
||||||
|
* TODO: only render newly visible/dirty areas
|
||||||
|
*/
|
||||||
|
var canvasRenderer = new ol.renderer.canvas.Renderer(
|
||||||
|
canvas, frameState.coordinateToPixelMatrix);
|
||||||
|
|
||||||
|
// TODO: get these elsewhere
|
||||||
|
var symbolizers = {
|
||||||
|
point: new ol.style.LiteralShape({
|
||||||
|
type: ol.style.ShapeType.CIRCLE,
|
||||||
|
size: 10,
|
||||||
|
fillStyle: '#ffcc99',
|
||||||
|
strokeStyle: '#ff9933',
|
||||||
|
strokeWidth: 2,
|
||||||
|
opacity: 0.75
|
||||||
|
}),
|
||||||
|
linestring: new ol.style.LiteralLine({
|
||||||
|
strokeStyle: '#ff9933',
|
||||||
|
strokeWidth: 2,
|
||||||
|
opacity: 1
|
||||||
|
}),
|
||||||
|
polygon: new ol.style.LiteralPolygon({
|
||||||
|
fillStyle: '#ffcc99',
|
||||||
|
strokeStyle: '#ff9933',
|
||||||
|
strokeWidth: 2,
|
||||||
|
opacity: 0.5
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// render features by geometry type
|
||||||
|
var filters = this.geometryFilters_,
|
||||||
|
numFilters = filters.length,
|
||||||
|
i, filter, type, features, symbolizer;
|
||||||
|
|
||||||
|
for (i = 0; i < numFilters; ++i) {
|
||||||
|
filter = filters[i];
|
||||||
|
type = filter.getType();
|
||||||
|
features = source.getFeatures(filter);
|
||||||
|
symbolizer = symbolizers[type];
|
||||||
|
canvasRenderer.renderFeaturesByGeometryType(type, features, symbolizer);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ ol.source.VectorOptions;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @constructor
|
* @constructor
|
||||||
* @extends {ol.source.Source}
|
* @extends {ol.source.Source}
|
||||||
@@ -150,19 +149,16 @@ ol.source.Vector = function(options) {
|
|||||||
* @type {ol.source.FeatureCache}
|
* @type {ol.source.FeatureCache}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.featureCache_ = null;
|
this.featureCache_ = new ol.source.FeatureCache();
|
||||||
|
|
||||||
};
|
};
|
||||||
goog.inherits(ol.source.Vector, ol.source.Source);
|
goog.inherits(ol.source.Vector, ol.source.Source);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array.<ol.Feature>} features Array of features.
|
* @param {Array.<ol.Feature>} features Array of features.
|
||||||
*/
|
*/
|
||||||
ol.source.Vector.prototype.setFeatures = function(features) {
|
ol.source.Vector.prototype.addFeatures = function(features) {
|
||||||
this.featureCache_.clear();
|
|
||||||
|
|
||||||
for (var i = 0, ii = features.length; i < ii; ++i) {
|
for (var i = 0, ii = features.length; i < ii; ++i) {
|
||||||
this.featureCache_.add(features[i]);
|
this.featureCache_.add(features[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user