2
* @author Patrick Schmiedel patrick.schmiedel@gmx.net
6
* @classDescription General overlay class. Enables to display
7
* any HTML element at a position on the image.
8
* Coordinate system is normalized to the interval [0,1]
9
* (0,0) being the top right and (1,1) the bottom left
10
* corner of the complete image.
11
* @see OverlayLayerProvider
12
* @see OverlayCollection
14
var Overlay = Class.create();
16
Overlay.prototype = Object.extend(new SunViewerWidget(), {
18
scaleWhenZooming: false,
25
* @param {String} html The HTML code that makes up the overlay.
26
* @param {SunImage} sunImage The sunImage the overlay belongs to. Set date to null to indicate it belongs to all images.
27
* @param {Hash} options Available options: position, offset, scaleWhenZooming, scaleFactor, dimensions
29
initialize: function(html, sunImage, options) {
31
this.sunImage = sunImage;
32
this.position = { x: 0.5, y: 0.5 };
33
this.offset = { x: 0, y: 0 };
35
this.dimensions = { width: 0, height: 0 };
37
Object.extend(this, this.defaultOptions);
38
Object.extend(this, options);
40
this.dimensions = { width: this.dimensions.width * this.scaleFactor, height: this.dimensions.height * this.scaleFactor };
41
if (this.scaleWhenZooming)
42
this.offset = { x: this.offset.x * this.scaleFactor, y: this.offset.y * this.scaleFactor };
46
* @method scaleTo Scales the overlay.
47
* @param {Number} scaleFactor The factor by which to scale.
49
scaleTo : function(scaleFactor) {
50
if (!this.dimensions) return;
52
if (this.domNode && this.domNode.style) {
53
this.domNode.style.width = Math.round(this.dimensions.width * scaleFactor) + 'px';
54
this.domNode.style.height = Math.round(this.dimensions.height * scaleFactor) + 'px';
57
if (this.domNode && this.domNode.width && this.domNode.height) {
58
this.domNode.width = Math.round(this.dimensions.width * scaleFactor);
59
this.domNode.height = Math.round(this.dimensions.height * scaleFactor);
64
* @method getQuadrant Gets the quadrant number in which the overlay is located.
76
* @param {Number} left The x coordinate of the top left corner.
77
* @param {Number} top The y coordinate of the top left corner.
78
* @param {Number} size The size of the sides.
79
* @return {Number} The number of the quadrant.
81
getQuadrant: function(left, top, size) {
82
return (this.position.x < left + size/2 ? 0 : 1) + (this.position.y < top + size/2 ? 0 : 2);
86
* @method appendTo Appends the overlay HTML element(s) to a layer at the given position.
87
* @param {HTML Element} layer The HTML element on which to append.
88
* @param {Object} x The x coordinate in the HTML element in pixels.
89
* @param {Object} y The y coordinate in the HTML element in pixels.
91
appendTo: function(layer, x, y) {
92
// The overlay HTML element
93
var htmlElement = document.createElement('div');
94
htmlElement.className = this.className;
95
htmlElement.innerHTML = this.html;
97
// The black background
98
bgElement = document.createElement('div');
99
bgElement.className = 'blackBg';
100
htmlElement.appendChild(bgElement);
102
// NOTE: This is rather crude, but I haven't found a better way
103
// to center the label on the position yet...
104
htmlElement.setStyle({
105
position: 'absolute',
107
left: Math.round(x + this.offset.x) + 'px',
108
top: Math.round(y + this.offset.y) + 'px'
111
// Append the overlay HTML element
112
this.domNode = layer.appendChild(htmlElement);
114
// If this overlay has info HTML
116
// Show it when clicked on
117
var handler = this.showInfo.bindAsEventListener(this, layer);
118
Event.observe(htmlElement, 'mousedown', handler);
119
$(htmlElement).setStyle({ cursor: 'pointer' });
124
* @method showInfo Shows HTML information associated with an overlay.
125
* @param {DOM MouseEvent} e The DOM MouseEvent.
126
* @param {HTML element} tileLayer The parent node of the overlay HTML element.
128
showInfo: function(e, tileLayer) {
131
x: Math.round(parseFloat(this.domNode.style.left)) - this.offset.x,
132
y: Math.round(parseFloat(this.domNode.style.top)) - this.offset.y
134
this.notifyListeners('ShowInfo', { html: this.infoHtml, layer: this.domNode.parentNode, position: this.position } );
139
* @classDescription Helper class for the quadTree.
140
* Specifies a branch. Defaults to a tree leaf (endsHere=true).
142
var branchEnd = Class.create();
144
branchEnd.prototype = Object.extend([], {
145
initialize: function() { this.endsHere=true; }
150
* @classDescription Overlay Collection class.
153
var OverlayCollection = Class.create();
155
OverlayCollection.prototype = Object.extend(
156
Object.extend($A([]), new SunViewerWidget()), {
161
initialize: function() {
163
this.quadTree.endsHere = true;
167
* @method createOverlay Creates a new Overlay and adds it to the collection.
168
* @param {String} html The HTML code that makes up the overlay.
169
* @param {SunImage} sunImage The sunImage the overlay belongs to. Set date to null to indicate it belongs to all images.
170
* @param {Hash} options Available options: position, offset, scaleWhenZooming, scaleFactor, dimensions
173
createOverlay: function(html, sunImage, options) {
174
var overlay = new Overlay(html, sunImage, options);
175
this.addOverlay(overlay);
178
this.notifyListeners('NewOverlay', overlay);
182
* @method getOverlays Returns the overlays for a tile at the given x and y index and zoom level.
183
* Utilizes a Quad Tree for storing them in sub-quadrants, so that they can be
185
* @param {Number} xIndex The x index of the tile.
186
* @param {Number} yIndex The y index of the tile.
187
* @param {Number} level The zoom level.
188
* @return {Overlay[]} An Array of overlays on this tile.
190
getOverlays: function(xIndex, yIndex, level) {
191
if (level < 0 // Do not display overlays for zoom levels < 0
193
|| (xIndex > 0 && xIndex >= Math.max(0, 1 << level))
195
|| (yIndex > 0 && yIndex >= Math.max(0, 1 << level)))
198
var branch = this.quadTree;
200
for(var l = 0; l < level; l++) {
201
if (branch.endsHere) {
202
if (branch.length == 0) return [];
203
// Put all the overlays for this quadrant into their corresponding sub-quadrants
204
// divide this quadrant into 4 sub-quadrants
205
var subQuads = [new branchEnd(),new branchEnd(),new branchEnd(),new branchEnd()];
206
// the position and size of the quadrant
207
var size = 1 / (1 << l);
208
var x = (xIndex >> (level - l)) / (1 << l);
209
var y = (yIndex >> (level - l)) / (1 << l);
210
// each overlay is put into the corresponding sub-quadrant
211
branch.each(function(overlay) {
212
var q = overlay.getQuadrant(x,y,size);
213
subQuads[q].push(overlay);
216
branch[0] = subQuads[0];
217
branch[1] = subQuads[1];
218
branch[2] = subQuads[2];
219
branch[3] = subQuads[3];
220
// now we have sub-quadrants
221
branch.endsHere = false;
224
// Determine next quadrant
225
var quadrant = ((xIndex >> (level - l - 1)) & 1) | ((yIndex >> (level - l - 1) << 1) & 2);
227
// Step down the Quad-Tree
228
branch = branch[quadrant];
231
// Return all the overlays in this quadrant (or its sub-quadrants)
232
return branch.flatten();
236
* @method addOverlay Adds a new overlay to the collection.
237
* Also adds it in the correct place in the Quad Tree.
238
* @param {Overlay} overlay The overlay to add.
240
addOverlay: function(overlay) {
242
var branch = this.quadTree;
243
// Until we reach the end
244
for(l = 0; !branch.endsHere; l++) {
245
// Determine next quadrant
246
var quadrant = (overlay.x * (1 << (l + 1)) & 1) | ((overlay.y * (1 << (l + 1)) << 1) & 2);
247
// Step down the Quad-Tree
248
branch = branch[quadrant];
250
// Add the overlay to this branch
251
branch.push(overlay);
255
* @method addOverlays Adds a number of overlays to the collection.
256
* @param {Overlay[]} overlays The overlays to add.
257
* @see OverlayCollection.addOverlays()
259
addOverlays: function(overlays) {
260
overlays.each(this.addOverlay.bind(this));
264
* @method clear Removes all overlays from the collection.
267
this.quadTree = new branchEnd();
b'\\ No newline at end of file'