General purpose canvas renderer

Currently only renders points as circles.  Eventually will have methods for other geometry types and other symbolizer types.  Also provides static methods to render point symbolizers (returning a canvas that can be drawn on another).
This commit is contained in:
Tim Schaub
2013-01-18 17:22:07 -07:00
parent b92fdaf911
commit 140e9ba355
2 changed files with 100 additions and 30 deletions

View File

@@ -1,17 +1,17 @@
goog.provide('ol.renderer.canvas');
goog.provide('ol.renderer.canvas.CanvasRenderer');
goog.provide('ol.renderer.canvas.Renderer');
goog.require('goog.asserts');
goog.require('goog.vec.Mat4');
goog.require('ol.Coordinate');
goog.require('ol.Pixel');
goog.require('ol.canvas');
goog.require('ol.geom.Geometry');
goog.require('ol.geom.Point');
goog.require('ol.renderer.Layer');
goog.require('ol.style.LiteralFill');
goog.require('ol.style.LiteralPoint');
goog.require('ol.style.LiteralShape');
goog.require('ol.style.LiteralStroke');
goog.require('ol.style.LiteralSymbolizer');
goog.require('ol.style.ShapeType');
/**
@@ -23,48 +23,118 @@ ol.renderer.canvas.isSupported = ol.canvas.isSupported;
/**
* @constructor
* @param {!HTMLCanvasElement} canvas Target canvas.
* @param {!goog.vec.Mat4.Number} transform Transform.
* @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
* transform applies to a separate canvas.
*/
ol.renderer.canvas.CanvasRenderer = function() {
ol.renderer.canvas.Renderer = function(canvas, transform, opt_offset) {
var context = /** @type {CanvasRenderingContext2D} */
(canvas.getContext('2d')),
dx = goog.isDef(opt_offset) ? opt_offset.x : 0,
dy = goog.isDef(opt_offset) ? opt_offset.y : 0;
context.setTransform(
goog.vec.Mat4.getElement(transform, 0, 0),
goog.vec.Mat4.getElement(transform, 1, 0),
goog.vec.Mat4.getElement(transform, 0, 1),
goog.vec.Mat4.getElement(transform, 1, 1),
goog.vec.Mat4.getElement(transform, 0, 3) + dx,
goog.vec.Mat4.getElement(transform, 1, 3) + dy);
/**
* @type {CanvasRenderingContext2D}
* @private
*/
this.context_ = null;
/**
* @type {ol.Pixel}
* @private
*/
this.offset_ = null;
this.context_ = context;
};
/**
* Confirm that we're ready to render.
* @param {Array.<ol.geom.Point>} points Point array.
* @param {ol.style.LiteralPoint} symbolizer Point symbolizer.
*/
ol.renderer.canvas.Renderer.prototype.renderPoints =
function(points, symbolizer) {
var context = this.context_,
canvas, i, ii, coords;
if (symbolizer instanceof ol.style.LiteralShape) {
canvas = ol.renderer.canvas.Renderer.renderShape(symbolizer);
} else {
throw new Error('Unsupported symbolizer: ' + symbolizer);
}
var mid = canvas.width / 2;
context.save();
context.translate(-mid, -mid);
context.globalAlpha = 1;
for (i = 0, ii = points.length; i < ii; ++i) {
coords = points[i].coordinates;
context.drawImage(canvas, coords[0], coords[1]);
}
context.restore();
};
/**
* @param {ol.style.LiteralShape} circle Shape symbolizer.
* @return {!HTMLCanvasElement} Canvas element.
* @private
*/
ol.renderer.canvas.CanvasRenderer.prototype.assertReady_ = function() {
goog.asserts.assert(!goog.isNull(this.context_),
'Call setTarget before rendering');
goog.asserts.assert(!goog.isNull(this.offset_),
'Call setOffset before rendering');
ol.renderer.canvas.Renderer.renderCircle_ = function(circle) {
var size = circle.size + (2 * circle.strokeWidth) + 1,
mid = size / 2,
canvas = /** @type {HTMLCanvasElement} */
(goog.dom.createElement(goog.dom.TagName.CANVAS)),
context = /** @type {CanvasRenderingContext2D} */
(canvas.getContext('2d')),
fillStyle = circle.fillStyle,
strokeStyle = circle.strokeStyle,
twoPi = Math.PI * 2;
canvas.height = size;
canvas.width = size;
context.globalAlpha = circle.opacity;
if (fillStyle) {
context.fillStyle = circle.fillStyle;
}
if (strokeStyle) {
context.lineWidth = circle.strokeWidth;
context.strokeStyle = circle.strokeStyle;
}
context.beginPath();
context.arc(mid, mid, circle.size / 2, 0, twoPi, true);
if (fillStyle) {
context.fill();
}
if (strokeStyle) {
context.stroke();
}
return canvas;
};
/**
* @param {ol.Pixel} offset Pixel offset of top left corner of canvas.
* @param {ol.style.LiteralShape} shape Shape symbolizer.
* @return {!HTMLCanvasElement} Canvas element.
*/
ol.renderer.canvas.CanvasRenderer.prototype.setOffset = function(offset) {
this.offset_ = offset;
};
/**
* @param {Element} canvas Target canvas element.
*/
ol.renderer.canvas.CanvasRenderer.prototype.setTarget = function(canvas) {
this.context_ = canvas.getContext('2d');
ol.renderer.canvas.Renderer.renderShape = function(shape) {
var canvas;
if (shape.type === ol.style.ShapeType.CIRCLE) {
canvas = ol.renderer.canvas.Renderer.renderCircle_(shape);
} else {
throw new Error('Unsupported shape type: ' + shape);
}
return canvas;
};

View File

@@ -6,6 +6,6 @@ goog.require('ol.style.LiteralSymbolizer');
/**
* @interface
* @implements {ol.style.LiteralSymbolizer}
* @extends {ol.style.LiteralSymbolizer}
*/
ol.style.LiteralPoint = function() {};