Files
openlayers/src/ol/renderer/canvas/canvasimagelayerrenderer.js
2015-03-30 22:53:03 +02:00

211 lines
5.8 KiB
JavaScript

goog.provide('ol.renderer.canvas.ImageLayer');
goog.require('goog.asserts');
goog.require('goog.functions');
goog.require('goog.vec.Mat4');
goog.require('ol.ImageBase');
goog.require('ol.ViewHint');
goog.require('ol.dom');
goog.require('ol.extent');
goog.require('ol.layer.Image');
goog.require('ol.proj');
goog.require('ol.renderer.canvas.Layer');
goog.require('ol.source.ImageVector');
goog.require('ol.vec.Mat4');
/**
* @constructor
* @extends {ol.renderer.canvas.Layer}
* @param {ol.layer.Image} imageLayer Single image layer.
*/
ol.renderer.canvas.ImageLayer = function(imageLayer) {
goog.base(this, imageLayer);
/**
* @private
* @type {?ol.ImageBase}
*/
this.image_ = null;
/**
* @private
* @type {!goog.vec.Mat4.Number}
*/
this.imageTransform_ = goog.vec.Mat4.createNumber();
/**
* @private
* @type {?goog.vec.Mat4.Number}
*/
this.imageTransformInv_ = null;
/**
* @private
* @type {CanvasRenderingContext2D}
*/
this.hitCanvasContext_ = null;
};
goog.inherits(ol.renderer.canvas.ImageLayer, ol.renderer.canvas.Layer);
/**
* @inheritDoc
*/
ol.renderer.canvas.ImageLayer.prototype.forEachFeatureAtCoordinate =
function(coordinate, frameState, callback, thisArg) {
var layer = this.getLayer();
var source = layer.getSource();
var resolution = frameState.viewState.resolution;
var rotation = frameState.viewState.rotation;
var skippedFeatureUids = frameState.skippedFeatureUids;
return source.forEachFeatureAtCoordinate(
coordinate, resolution, rotation, skippedFeatureUids,
/**
* @param {ol.Feature} feature Feature.
* @return {?} Callback result.
*/
function(feature) {
return callback.call(thisArg, feature, layer);
});
};
/**
* @inheritDoc
*/
ol.renderer.canvas.ImageLayer.prototype.forEachLayerAtPixel =
function(pixel, frameState, callback, thisArg) {
if (goog.isNull(this.getImage())) {
return undefined;
}
if (this.getLayer().getSource() instanceof ol.source.ImageVector) {
// for ImageVector sources use the original hit-detection logic,
// so that for example also transparent polygons are detected
var coordinate = pixel.slice();
ol.vec.Mat4.multVec2(
frameState.pixelToCoordinateMatrix, coordinate, coordinate);
var hasFeature = this.forEachFeatureAtCoordinate(
coordinate, frameState, goog.functions.TRUE, this);
if (hasFeature) {
return callback.call(thisArg, this.getLayer());
} else {
return undefined;
}
} else {
// for all other image sources directly check the image
if (goog.isNull(this.imageTransformInv_)) {
this.imageTransformInv_ = goog.vec.Mat4.createNumber();
goog.vec.Mat4.invert(this.imageTransform_, this.imageTransformInv_);
}
var pixelOnCanvas =
this.getPixelOnCanvas(pixel, this.imageTransformInv_);
if (goog.isNull(this.hitCanvasContext_)) {
this.hitCanvasContext_ = ol.dom.createCanvasContext2D(1, 1);
}
this.hitCanvasContext_.clearRect(0, 0, 1, 1);
this.hitCanvasContext_.drawImage(
this.getImage(), pixelOnCanvas[0], pixelOnCanvas[1], 1, 1, 0, 0, 1, 1);
var imageData = this.hitCanvasContext_.getImageData(0, 0, 1, 1).data;
if (imageData[3] > 0) {
return callback.call(thisArg, this.getLayer());
} else {
return undefined;
}
}
};
/**
* @inheritDoc
*/
ol.renderer.canvas.ImageLayer.prototype.getImage = function() {
return goog.isNull(this.image_) ?
null : this.image_.getImage();
};
/**
* @inheritDoc
*/
ol.renderer.canvas.ImageLayer.prototype.getImageTransform = function() {
return this.imageTransform_;
};
/**
* @inheritDoc
*/
ol.renderer.canvas.ImageLayer.prototype.prepareFrame =
function(frameState, layerState) {
var pixelRatio = frameState.pixelRatio;
var viewState = frameState.viewState;
var viewCenter = viewState.center;
var viewResolution = viewState.resolution;
var viewRotation = viewState.rotation;
var image;
var imageLayer = this.getLayer();
goog.asserts.assertInstanceof(imageLayer, ol.layer.Image,
'layer is an instance of ol.layer.Image');
var imageSource = imageLayer.getSource();
var hints = frameState.viewHints;
var renderedExtent = frameState.extent;
if (goog.isDef(layerState.extent)) {
renderedExtent = ol.extent.getIntersection(
renderedExtent, layerState.extent);
}
if (!hints[ol.ViewHint.ANIMATING] && !hints[ol.ViewHint.INTERACTING] &&
!ol.extent.isEmpty(renderedExtent)) {
var projection = viewState.projection;
var sourceProjection = imageSource.getProjection();
if (!goog.isNull(sourceProjection)) {
goog.asserts.assert(ol.proj.equivalent(projection, sourceProjection),
'projection and sourceProjection are equivalent');
projection = sourceProjection;
}
image = imageSource.getImage(
renderedExtent, viewResolution, pixelRatio, projection);
if (!goog.isNull(image)) {
var loaded = this.loadImage(image);
if (loaded) {
this.image_ = image;
}
}
}
if (!goog.isNull(this.image_)) {
image = this.image_;
var imageExtent = image.getExtent();
var imageResolution = image.getResolution();
var imagePixelRatio = image.getPixelRatio();
var scale = pixelRatio * imageResolution /
(viewResolution * imagePixelRatio);
ol.vec.Mat4.makeTransform2D(this.imageTransform_,
pixelRatio * frameState.size[0] / 2,
pixelRatio * frameState.size[1] / 2,
scale, scale,
viewRotation,
imagePixelRatio * (imageExtent[0] - viewCenter[0]) / imageResolution,
imagePixelRatio * (viewCenter[1] - imageExtent[3]) / imageResolution);
this.imageTransformInv_ = null;
this.updateAttributions(frameState.attributions, image.getAttributions());
this.updateLogos(frameState, imageSource);
}
return true;
};