Apply transform to coordinates rather than the canvas

Credit goes to @jystic for figuring out this approach.
This commit is contained in:
ahocevar
2013-06-09 20:20:53 +02:00
parent 7cd5266d39
commit 489459f313
2 changed files with 27 additions and 37 deletions

View File

@@ -386,7 +386,7 @@ ol.renderer.canvas.VectorLayer.prototype.renderFrame =
sketchCanvas.height = sketchHeight; sketchCanvas.height = sketchHeight;
var sketchCanvasRenderer = new ol.renderer.canvas.VectorRenderer( var sketchCanvasRenderer = new ol.renderer.canvas.VectorRenderer(
sketchCanvas, sketchTransform, undefined, this.requestMapRenderFrame_); sketchCanvas, sketchTransform, this.requestMapRenderFrame_);
// clear/resize final canvas // clear/resize final canvas
var finalCanvas = this.canvas_; var finalCanvas = this.canvas_;

View File

@@ -8,7 +8,6 @@ goog.require('goog.events');
goog.require('goog.events.EventType'); goog.require('goog.events.EventType');
goog.require('goog.vec.Mat4'); goog.require('goog.vec.Mat4');
goog.require('ol.Feature'); goog.require('ol.Feature');
goog.require('ol.Pixel');
goog.require('ol.geom.Geometry'); goog.require('ol.geom.Geometry');
goog.require('ol.geom.GeometryType'); goog.require('ol.geom.GeometryType');
goog.require('ol.geom.LineString'); goog.require('ol.geom.LineString');
@@ -31,32 +30,19 @@ goog.require('ol.style.SymbolizerLiteral');
* @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
* provided as an optional argument as a convenience in cases where the
* transform applies to a separate canvas.
* @param {function()=} opt_iconLoadedCallback Callback for deferred rendering * @param {function()=} opt_iconLoadedCallback Callback for deferred rendering
* when images need to be loaded before rendering. * when images need to be loaded before rendering.
*/ */
ol.renderer.canvas.VectorRenderer = ol.renderer.canvas.VectorRenderer =
function(canvas, transform, opt_offset, opt_iconLoadedCallback) { function(canvas, transform, opt_iconLoadedCallback) {
var context = /** @type {CanvasRenderingContext2D} */ var context = /** @type {CanvasRenderingContext2D} */
(canvas.getContext('2d')), (canvas.getContext('2d'));
dx = goog.isDef(opt_offset) ? opt_offset[0] : 0,
dy = goog.isDef(opt_offset) ? opt_offset[1] : 0;
/** /**
* @type {goog.vec.Mat4.Number} * @type {goog.vec.Mat4.Number}
* @private * @private
*/ */
this.transform_ = transform; this.transform_ = transform;
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);
var vec = [1, 0, 0]; var vec = [1, 0, 0];
goog.vec.Mat4.multVec3NoTranslate(transform, vec, vec); goog.vec.Mat4.multVec3NoTranslate(transform, vec, vec);
@@ -158,20 +144,21 @@ ol.renderer.canvas.VectorRenderer.prototype.renderLineStringFeatures_ =
var context = this.context_, var context = this.context_,
i, ii, feature, id, currentSize, geometry, components, j, jj, line, dim, i, ii, feature, id, currentSize, geometry, components, j, jj, line, dim,
k, kk, x, y; k, kk, vec, strokeSize;
context.globalAlpha = symbolizer.opacity; context.globalAlpha = symbolizer.opacity;
context.strokeStyle = symbolizer.strokeColor; context.strokeStyle = symbolizer.strokeColor;
context.lineWidth = symbolizer.strokeWidth * this.inverseScale_; context.lineWidth = symbolizer.strokeWidth;
context.lineCap = 'round'; // TODO: accept this as a symbolizer property context.lineCap = 'round'; // TODO: accept this as a symbolizer property
context.lineJoin = 'round'; // TODO: accept this as a symbolizer property context.lineJoin = 'round'; // TODO: accept this as a symbolizer property
strokeSize = context.lineWidth * this.inverseScale_;
context.beginPath(); context.beginPath();
for (i = 0, ii = features.length; i < ii; ++i) { for (i = 0, ii = features.length; i < ii; ++i) {
feature = features[i]; feature = features[i];
id = goog.getUid(feature); id = goog.getUid(feature);
currentSize = goog.isDef(this.symbolSizes_[id]) ? currentSize = goog.isDef(this.symbolSizes_[id]) ?
this.symbolSizes_[id] : [0]; this.symbolSizes_[id] : [0];
currentSize[0] = Math.max(currentSize[0], context.lineWidth); currentSize[0] = Math.max(currentSize[0], strokeSize);
this.symbolSizes_[id] = currentSize; this.symbolSizes_[id] = currentSize;
this.maxSymbolSize_ = [Math.max(currentSize[0], this.maxSymbolSize_[0]), this.maxSymbolSize_ = [Math.max(currentSize[0], this.maxSymbolSize_[0]),
Math.max(currentSize[0], this.maxSymbolSize_[1])]; Math.max(currentSize[0], this.maxSymbolSize_[1])];
@@ -187,12 +174,12 @@ ol.renderer.canvas.VectorRenderer.prototype.renderLineStringFeatures_ =
line = components[j]; line = components[j];
dim = line.dimension; dim = line.dimension;
for (k = 0, kk = line.getCount(); k < kk; ++k) { for (k = 0, kk = line.getCount(); k < kk; ++k) {
x = line.get(k, 0); vec = [line.get(k, 0), line.get(k, 1), 0];
y = line.get(k, 1); goog.vec.Mat4.multVec3(this.transform_, vec, vec);
if (k === 0) { if (k === 0) {
context.moveTo(x, y); context.moveTo(vec[0], vec[1]);
} else { } else {
context.lineTo(x, y); context.lineTo(vec[0], vec[1]);
} }
} }
} }
@@ -232,6 +219,8 @@ ol.renderer.canvas.VectorRenderer.prototype.renderPointFeatures_ =
var midWidth = content.width / 2; var midWidth = content.width / 2;
var midHeight = content.height / 2; var midHeight = content.height / 2;
var contentWidth = content.width * this.inverseScale_;
var contentHeight = content.height * this.inverseScale_;
context.save(); context.save();
context.setTransform(1, 0, 0, 1, -midWidth, -midHeight); context.setTransform(1, 0, 0, 1, -midWidth, -midHeight);
context.globalAlpha = alpha; context.globalAlpha = alpha;
@@ -240,10 +229,8 @@ ol.renderer.canvas.VectorRenderer.prototype.renderPointFeatures_ =
id = goog.getUid(feature); id = goog.getUid(feature);
size = this.symbolSizes_[id]; size = this.symbolSizes_[id];
this.symbolSizes_[id] = goog.isDef(size) ? this.symbolSizes_[id] = goog.isDef(size) ?
[Math.max(size[0], content.width * this.inverseScale_), [Math.max(size[0], contentWidth), Math.max(size[1], contentHeight)] :
Math.max(size[1], content.height * this.inverseScale_)] : [contentWidth, contentHeight];
[content.width * this.inverseScale_,
content.height * this.inverseScale_];
this.maxSymbolSize_ = this.maxSymbolSize_ =
[Math.max(this.maxSymbolSize_[0], this.symbolSizes_[id][0]), [Math.max(this.maxSymbolSize_[0], this.symbolSizes_[id][0]),
Math.max(this.maxSymbolSize_[1], this.symbolSizes_[id][1])]; Math.max(this.maxSymbolSize_[1], this.symbolSizes_[id][1])];
@@ -257,8 +244,8 @@ ol.renderer.canvas.VectorRenderer.prototype.renderPointFeatures_ =
} }
for (j = 0, jj = components.length; j < jj; ++j) { for (j = 0, jj = components.length; j < jj; ++j) {
point = components[j]; point = components[j];
vec = goog.vec.Mat4.multVec3( vec = [point.get(0), point.get(1), 0];
this.transform_, [point.get(0), point.get(1), 0], []); goog.vec.Mat4.multVec3(this.transform_, vec, vec);
context.drawImage(content, vec[0], vec[1], content.width, content.height); context.drawImage(content, vec[0], vec[1], content.width, content.height);
} }
} }
@@ -277,14 +264,17 @@ ol.renderer.canvas.VectorRenderer.prototype.renderPolygonFeatures_ =
function(features, symbolizer) { function(features, symbolizer) {
var context = this.context_, var context = this.context_,
strokeColor = symbolizer.strokeColor, strokeColor = symbolizer.strokeColor,
strokeWidth = symbolizer.strokeWidth,
fillColor = symbolizer.fillColor, fillColor = symbolizer.fillColor,
i, ii, geometry, components, j, jj, poly, i, ii, geometry, components, j, jj, poly,
rings, numRings, ring, dim, k, kk, x, y; rings, numRings, ring, dim, k, kk, vec;
context.globalAlpha = symbolizer.opacity; context.globalAlpha = symbolizer.opacity;
if (strokeColor) { if (strokeColor) {
context.strokeStyle = symbolizer.strokeColor; context.strokeStyle = strokeColor;
context.lineWidth = symbolizer.strokeWidth * this.inverseScale_; if (strokeWidth) {
context.lineWidth = strokeWidth;
}
context.lineCap = 'round'; // TODO: accept this as a symbolizer property context.lineCap = 'round'; // TODO: accept this as a symbolizer property
context.lineJoin = 'round'; // TODO: accept this as a symbolizer property context.lineJoin = 'round'; // TODO: accept this as a symbolizer property
} }
@@ -318,12 +308,12 @@ ol.renderer.canvas.VectorRenderer.prototype.renderPolygonFeatures_ =
// TODO: scenario 4 // TODO: scenario 4
ring = rings[0]; ring = rings[0];
for (k = 0, kk = ring.getCount(); k < kk; ++k) { for (k = 0, kk = ring.getCount(); k < kk; ++k) {
x = ring.get(k, 0); vec = [ring.get(k, 0), ring.get(k, 1), 0];
y = ring.get(k, 1); goog.vec.Mat4.multVec3(this.transform_, vec, vec);
if (k === 0) { if (k === 0) {
context.moveTo(x, y); context.moveTo(vec[0], vec[1]);
} else { } else {
context.lineTo(x, y); context.lineTo(vec[0], vec[1]);
} }
} }
if (fillColor && strokeColor) { if (fillColor && strokeColor) {