238 lines
6.4 KiB
JavaScript
238 lines
6.4 KiB
JavaScript
goog.provide('ol.source.ImageVector');
|
|
|
|
goog.require('goog.asserts');
|
|
goog.require('goog.events');
|
|
goog.require('goog.events.EventType');
|
|
goog.require('goog.vec.Mat4');
|
|
goog.require('ol.dom');
|
|
goog.require('ol.extent');
|
|
goog.require('ol.feature');
|
|
goog.require('ol.render.canvas.ReplayGroup');
|
|
goog.require('ol.renderer.vector');
|
|
goog.require('ol.source.ImageCanvas');
|
|
goog.require('ol.source.Vector');
|
|
goog.require('ol.vec.Mat4');
|
|
|
|
|
|
|
|
/**
|
|
* @classdesc
|
|
* An image source whose images are canvas elements into which vector features
|
|
* read from a vector source (`ol.source.Vector`) are drawn. An
|
|
* `ol.source.ImageVector` object is to be used as the `source` of an image
|
|
* layer (`ol.layer.Image`). Image layers are rotated, scaled, and translated,
|
|
* as opposed to being re-rendered, during animations and interactions. So, like
|
|
* any other image layer, an image layer configured with an
|
|
* `ol.source.ImageVector` will exhibit this behaviour. This is in contrast to a
|
|
* vector layer, where vector features are re-drawn during animations and
|
|
* interactions.
|
|
*
|
|
* @constructor
|
|
* @extends {ol.source.ImageCanvas}
|
|
* @param {olx.source.ImageVectorOptions} options Options.
|
|
* @todo api
|
|
*/
|
|
ol.source.ImageVector = function(options) {
|
|
|
|
/**
|
|
* @private
|
|
* @type {ol.source.Vector}
|
|
*/
|
|
this.source_ = options.source;
|
|
|
|
/**
|
|
* @private
|
|
* @type {!ol.feature.StyleFunction}
|
|
*/
|
|
this.styleFunction_ = goog.isDef(options.style) ?
|
|
ol.feature.createStyleFunction(options.style) :
|
|
ol.feature.defaultStyleFunction;
|
|
|
|
/**
|
|
* @private
|
|
* @type {!goog.vec.Mat4.Number}
|
|
*/
|
|
this.transform_ = goog.vec.Mat4.createNumber();
|
|
|
|
/**
|
|
* @private
|
|
* @type {CanvasRenderingContext2D}
|
|
*/
|
|
this.canvasContext_ = ol.dom.createCanvasContext2D();
|
|
|
|
/**
|
|
* @private
|
|
* @type {ol.Size}
|
|
*/
|
|
this.canvasSize_ = [0, 0];
|
|
|
|
/**
|
|
* @private
|
|
* @type {ol.render.canvas.ReplayGroup}
|
|
*/
|
|
this.replayGroup_ = null;
|
|
|
|
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 replayGroup = new ol.render.canvas.ReplayGroup(
|
|
ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio), extent,
|
|
resolution);
|
|
|
|
var loading = false;
|
|
this.source_.forEachFeatureInExtentAtResolution(extent, resolution,
|
|
/**
|
|
* @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.canvasContext_.canvas.width = size[0];
|
|
this.canvasContext_.canvas.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, pixelRatio, transform, 0,
|
|
{});
|
|
|
|
this.replayGroup_ = replayGroup;
|
|
|
|
return this.canvasContext_.canvas;
|
|
};
|
|
|
|
|
|
/**
|
|
* @inheritDoc
|
|
*/
|
|
ol.source.ImageVector.prototype.forEachFeatureAtPixel = function(
|
|
extent, resolution, rotation, coordinate, skippedFeatureUids, callback) {
|
|
if (goog.isNull(this.replayGroup_)) {
|
|
return undefined;
|
|
} else {
|
|
return this.replayGroup_.forEachGeometryAtPixel(
|
|
extent, resolution, 0, coordinate, skippedFeatureUids,
|
|
/**
|
|
* @param {ol.geom.Geometry} geometry Geometry.
|
|
* @param {Object} data Data.
|
|
* @return {?} Callback result.
|
|
*/
|
|
function(geometry, data) {
|
|
var feature = /** @type {ol.Feature} */ (data);
|
|
return callback(feature);
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @return {ol.source.Vector} Source.
|
|
* @todo api
|
|
*/
|
|
ol.source.ImageVector.prototype.getSource = function() {
|
|
return this.source_;
|
|
};
|
|
|
|
|
|
/**
|
|
* @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.handleImageChange_ =
|
|
function(event) {
|
|
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 styles = this.styleFunction_(feature, resolution);
|
|
if (!goog.isDefAndNotNull(styles)) {
|
|
return false;
|
|
}
|
|
var i, ii, loading = false;
|
|
for (i = 0, ii = styles.length; i < ii; ++i) {
|
|
loading = ol.renderer.vector.renderFeature(
|
|
replayGroup, feature, styles[i],
|
|
ol.renderer.vector.getSquaredTolerance(resolution, pixelRatio),
|
|
feature, this.handleImageChange_, this) || loading;
|
|
}
|
|
return loading;
|
|
};
|