Add ol.source.ImageVector

This commit is contained in:
Éric Lemoine
2014-01-09 14:51:59 +01:00
parent e4b5f309eb
commit 8c1f7f9b29
3 changed files with 228 additions and 0 deletions

View File

@@ -638,6 +638,20 @@
* @property {ol.source.State|undefined} state Source state.
*/
/**
* @typedef {Object} olx.source.ImageVectorOptions
* @property {Array.<ol.Attribution>|undefined} attributions Attributions.
* @property {ol.Extent|undefined} extent Extent.
* @property {string|undefined} logo Logo.
* @property {ol.proj.ProjectionLike} projection Projection.
* @property {number|undefined} ratio Ratio. 1 means canvases are the size
* of the map viewport, 2 means twice the size of the map viewport, and so
* on.
* @property {Array.<number>|undefined} resolutions Resolutions. If specified,
* new canvases will be created for these resolutions only.
* @property {ol.source.Vector} source Vector source.
*/
/**
* @typedef {Object} olx.source.ImageWMSOptions
* @property {Array.<ol.Attribution>|undefined} attributions Attributions.

View File

@@ -0,0 +1 @@
@exportSymbol ol.source.ImageVector

View File

@@ -0,0 +1,213 @@
goog.provide('ol.source.ImageVector');
goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.vec.Mat4');
goog.require('ol.extent');
goog.require('ol.render.canvas.ReplayGroup');
goog.require('ol.renderer.vector');
goog.require('ol.source.ImageCanvas');
goog.require('ol.source.Vector');
goog.require('ol.style.ImageState');
goog.require('ol.vec.Mat4');
/**
* @constructor
* @extends {ol.source.ImageCanvas}
* @param {olx.source.ImageVectorOptions} options Options.
*/
ol.source.ImageVector = function(options) {
/**
* @private
* @type {ol.source.Vector}
*/
this.source_ = options.source;
/**
* @private
* @type {ol.feature.StyleFunction}
*/
this.styleFunction_ = options.styleFunction;
/**
* @private
* @type {!goog.vec.Mat4.Number}
*/
this.transform_ = goog.vec.Mat4.createNumber();
/**
* @private
* @type {HTMLCanvasElement}
*/
this.canvasElement_ = /** @type {HTMLCanvasElement} */
(goog.dom.createElement(goog.dom.TagName.CANVAS));
/**
* @private
* @type {CanvasRenderingContext2D}
*/
this.canvasContext_ = /** @type {CanvasRenderingContext2D} */
(this.canvasElement_.getContext('2d'));
/**
* @private
* @type {ol.Size}
*/
this.canvasSize_ = [0, 0];
goog.base(this, {
attributions: options.attributions,
canvasFunction: goog.bind(this.canvasFunctionInternal_, this),
extent: options.extent,
logo: options.logo,
projection: options.projection,
ratio: options.ratio,
resolutions: options.resolutions,
state: this.source_.getState()
});
goog.events.listen(this.source_, goog.events.EventType.CHANGE,
this.handleSourceChange_, undefined, this);
};
goog.inherits(ol.source.ImageVector, ol.source.ImageCanvas);
/**
* @param {ol.Extent} extent Extent.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.Size} size Size.
* @param {ol.proj.Projection} projection Projection;
* @return {HTMLCanvasElement} Canvas element.
* @private
*/
ol.source.ImageVector.prototype.canvasFunctionInternal_ =
function(extent, resolution, pixelRatio, size, projection) {
var tolerance = resolution / (2 * pixelRatio);
var replayGroup = new ol.render.canvas.ReplayGroup(
pixelRatio, tolerance);
var loading = false;
this.source_.forEachFeatureInExtent(extent,
/**
* @param {ol.Feature} feature Feature.
*/
function(feature) {
loading = loading ||
this.renderFeature_(feature, resolution, pixelRatio, replayGroup);
}, this);
replayGroup.finish();
if (loading) {
return null;
}
if (this.canvasSize_[0] != size[0] || this.canvasSize_[1] != size[1]) {
this.canvasElement_.width = size[0];
this.canvasElement_.height = size[1];
this.canvasSize_[0] = size[0];
this.canvasSize_[1] = size[1];
} else {
this.canvasContext_.clearRect(0, 0, size[0], size[1]);
}
var transform = this.getTransform_(ol.extent.getCenter(extent),
resolution, pixelRatio, size);
replayGroup.replay(this.canvasContext_, extent, transform,
goog.functions.TRUE);
return this.canvasElement_;
};
/**
* @param {ol.Coordinate} center Center.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.Size} size Size.
* @return {!goog.vec.Mat4.Number} Transform.
* @private
*/
ol.source.ImageVector.prototype.getTransform_ =
function(center, resolution, pixelRatio, size) {
return ol.vec.Mat4.makeTransform2D(this.transform_,
size[0] / 2, size[1] / 2,
pixelRatio / resolution, -pixelRatio / resolution,
0,
-center[0], -center[1]);
};
/**
* Handle changes in image style state.
* @param {goog.events.Event} event Image style change event.
* @private
*/
ol.source.ImageVector.prototype.handleImageStyleChange_ =
function(event) {
var imageStyle = /** @type {ol.style.Image} */ (event.target);
if (imageStyle.getImageState() == ol.style.ImageState.LOADED) {
this.dispatchChangeEvent();
}
};
/**
* @private
*/
ol.source.ImageVector.prototype.handleSourceChange_ = function() {
// setState will trigger a CHANGE event, so we always rely
// change events by calling setState.
this.setState(this.source_.getState());
};
/**
* @param {ol.Feature} feature Feature.
* @param {number} resolution Resolution.
* @param {number} pixelRatio Pixel ratio.
* @param {ol.render.canvas.ReplayGroup} replayGroup Replay group.
* @return {boolean} `true` if an image is loading.
* @private
*/
ol.source.ImageVector.prototype.renderFeature_ =
function(feature, resolution, pixelRatio, replayGroup) {
var loading = false;
var styles = this.styleFunction_(feature, resolution);
if (!goog.isDefAndNotNull(styles)) {
return false;
}
// simplify to a tolerance of half a device pixel
var squaredTolerance =
resolution * resolution / (4 * pixelRatio * pixelRatio);
var i, ii, style, imageStyle, imageState;
for (i = 0, ii = styles.length; i < ii; ++i) {
style = styles[i];
imageStyle = style.getImage();
if (!goog.isNull(imageStyle)) {
if (imageStyle.getImageState() == ol.style.ImageState.IDLE) {
goog.events.listenOnce(imageStyle, goog.events.EventType.CHANGE,
this.handleImageStyleChange_, false, this);
imageStyle.load();
} else if (imageStyle.getImageState() == ol.style.ImageState.LOADED) {
ol.renderer.vector.renderFeature(
replayGroup, feature, style, squaredTolerance, feature);
}
goog.asserts.assert(
imageStyle.getImageState() != ol.style.ImageState.IDLE);
loading = imageStyle.getImageState() == ol.style.ImageState.LOADING;
} else {
ol.renderer.vector.renderFeature(
replayGroup, feature, style, squaredTolerance, feature);
}
}
return loading;
};