not really known
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

269 lines
9.9 KiB

define(['activity/data-model', 'webL10n'], function(DataModel, l10n) {
'use strict';
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d'),
moon = document.querySelector('img#moon');
var _ = l10n.get;
var IMAGE_SIZE, HALF_SIZE;
if (!ctx.ellipse) {
/*
CanvasRenderingContext2D.ellipse() is esperimental at the time of writing
Provide pollyfill
*/
ctx.ellipse = function(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise) {
/* for this project, we do not need: rotation, startAngle, endAngle, anticlockwise */
x -= radiusX;
y -= radiusY;
radiusX *= 2;
radiusY *= 2;
var kappa = 0.5522848,
ox = (radiusX / 2) * kappa, // control point offset horizontal
oy = (radiusY / 2) * kappa, // control point offset vertical
xe = x + radiusX, // x-end
ye = y + radiusY, // y-end
xm = x + radiusX / 2, // x-middle
ym = y + radiusY / 2; // y-middle
if (startAngle === Math.PI / 2 && endAngle === 3 * Math.PI / 2) {
ctx.moveTo(xm, ye);
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); /* 2nd quarter */
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); /* 3rd quarter */
} else if (startAngle === 3 * Math.PI / 2 && endAngle === Math.PI / 2) {
ctx.moveTo(xm, y);
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); /* 4th quarter */
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); /* 1st quarter */
} else if (startAngle === 0 && endAngle === 2 * Math.PI) {
ctx.moveTo(xe, ym);
ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); /* 1st quarter */
ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); /* 2nd quarter */
ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); /* 3rd quarter */
ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); /* 4th quarter */
}
};
}
function drawMoon() {
/*
Draw mask corresponding to either shaded region or lit region
*/
var phase_shadow_adjust = null;
var arc_scale = null;
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.fillRect(0, 0, IMAGE_SIZE, IMAGE_SIZE);
if (DataModel.phase_of_moon < 0.25) {
phase_shadow_adjust = DataModel.phase_of_moon - Math.abs(Math.sin(DataModel.phase_of_moon * Math.PI * 4) / 18.0);
arc_scale = 1 - (4 * phase_shadow_adjust);
ctx.fillStyle = 'white';
ctx.fillRect(HALF_SIZE, 0, HALF_SIZE, IMAGE_SIZE);
ctx.fillStyle = 'black';
drawEllipse(HALF_SIZE - IMAGE_SIZE * arc_scale / 2, 0, IMAGE_SIZE * arc_scale, IMAGE_SIZE, 0, 3 * Math.PI / 2, Math.PI / 2);
ctx.fill();
} else if (DataModel.phase_of_moon < 0.50) {
phase_shadow_adjust = DataModel.phase_of_moon + Math.abs(Math.sin(DataModel.phase_of_moon * Math.PI * 4) / 18.0);
arc_scale = 4 * (phase_shadow_adjust - 0.25);
ctx.fillStyle = 'white';
ctx.fillRect(HALF_SIZE, 0, HALF_SIZE, IMAGE_SIZE);
ctx.fillStyle = 'white';
drawEllipse(HALF_SIZE - IMAGE_SIZE * arc_scale / 2, 0, IMAGE_SIZE * arc_scale, IMAGE_SIZE, 0, Math.PI / 2, 3 * Math.PI / 2);
ctx.fill();
} else if (DataModel.phase_of_moon < 0.75) {
phase_shadow_adjust = DataModel.phase_of_moon - Math.abs(Math.sin(DataModel.phase_of_moon * Math.PI * 4) / 18.0);
arc_scale = 1 - (4 * (phase_shadow_adjust - 0.5));
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, HALF_SIZE, IMAGE_SIZE);
ctx.fillStyle = 'white';
drawEllipse(HALF_SIZE - IMAGE_SIZE * arc_scale / 2, 0, IMAGE_SIZE * arc_scale, IMAGE_SIZE, 0, 3 * Math.PI / 2, Math.PI / 2);
ctx.fill();
} else {
phase_shadow_adjust = DataModel.phase_of_moon + Math.abs(Math.sin(DataModel.phase_of_moon * Math.PI * 4) / 18.0);
arc_scale = 4 * (phase_shadow_adjust - 0.75);
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, HALF_SIZE, IMAGE_SIZE);
ctx.fillStyle = 'black';
drawEllipse(HALF_SIZE - IMAGE_SIZE * arc_scale / 2, 0, IMAGE_SIZE * arc_scale, IMAGE_SIZE, 0, Math.PI / 2, 3 * Math.PI / 2);
ctx.fill();
}
ctx.save();
ctx.globalCompositeOperation = 'multiply';
ctx.drawImage(moon, 0, 0, IMAGE_SIZE, IMAGE_SIZE);
ctx.globalAlpha = 0.5;
ctx.globalCompositeOperation = 'source-over';
ctx.drawImage(moon, 0, 0, IMAGE_SIZE, IMAGE_SIZE);
ctx.restore();
drawEclipse();
}
function drawEclipse() {
if (
(
DataModel.next_lunar_eclipse_sec !== -1 ||
DataModel.last_lunar_eclipse_sec <= 7200
) && (
DataModel.next_lunar_eclipse_sec <= 7200 ||
DataModel.last_lunar_eclipse_sec !== -1
) && (
Math.min(DataModel.next_lunar_eclipse_sec, DataModel.last_lunar_eclipse_sec) <= 7200
)
) {
var eclipse_alpha;
if (DataModel.next_lunar_eclipse_sec == -1) {
eclipse_alpha = DataModel.last_lunar_eclipse_sec / 7200;
}
else if (DataModel.last_lunar_eclipse_sec == -1) {
eclipse_alpha = DataModel.next_lunar_eclipse_sec / 7200;
}
else {
eclipse_alpha = Math.min(DataModel.next_lunar_eclipse_sec, DataModel.last_lunar_eclipse_sec) / 7200;
}
ctx.save();
ctx.globalAlpha = 0.25 * (1 - eclipse_alpha);
ctx.globalCompositeOperation = 'multiply';
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, IMAGE_SIZE, IMAGE_SIZE);
ctx.restore();
}
}
function drawGrid(compass_text) {
/*
Draw longitudes at 0, +/-30 and +/-60 degrees
Draw latitudes at 0, +/-30 and +/-60 degrees
Draw compass
*/
var needleLength = 0.08 * IMAGE_SIZE;
ctx.font = '16px Sans';
ctx.lineWidth = 3;
/* Latitude Labels */
ctx.fillStyle = 'blue';
drawLabel(HALF_SIZE + 1, HALF_SIZE, 26, 22, '0\xB0');
drawLabel(HALF_SIZE + 1, HALF_SIZE * 0.50, 36, 22, '30\xB0');
drawLabel(HALF_SIZE + 1, HALF_SIZE * 1.5, 36, 22, '30\xB0');
drawLabel(HALF_SIZE + 1, HALF_SIZE * 0.15, 36, 22, '60\xB0');
drawLabel(HALF_SIZE + 1, HALF_SIZE * 1.85, 36, 22, '60\xB0');
/* Longitude Labels */
ctx.fillStyle = 'red';
drawLabel((HALF_SIZE * 0.48), HALF_SIZE, 36, 22, '30\xB0');
drawLabel((HALF_SIZE * 1.52), HALF_SIZE, 36, 22, '30\xB0');
drawLabel((HALF_SIZE * 0.15), HALF_SIZE, 36, 22, '60\xB0');
drawLabel((HALF_SIZE * 1.85), HALF_SIZE, 36, 22, '60\xB0');
/* Latitude Lines*/
ctx.strokeStyle = 'blue';
drawLine(0, HALF_SIZE, IMAGE_SIZE, HALF_SIZE);
drawLine(HALF_SIZE * 0.15, HALF_SIZE * 0.5, IMAGE_SIZE - HALF_SIZE * 0.15, HALF_SIZE * 0.5);
drawLine(HALF_SIZE * 0.15, HALF_SIZE * 1.5, IMAGE_SIZE - HALF_SIZE * 0.15, HALF_SIZE * 1.5);
drawLine(HALF_SIZE * 0.5, HALF_SIZE * 0.15, IMAGE_SIZE - HALF_SIZE * 0.5, HALF_SIZE * 0.15);
drawLine(HALF_SIZE * 0.5, HALF_SIZE * 1.85, IMAGE_SIZE - HALF_SIZE * 0.5, HALF_SIZE * 1.85);
/* Longitude Lines*/
ctx.strokeStyle = 'red';
drawLine(HALF_SIZE, 0, HALF_SIZE, IMAGE_SIZE);
drawEllipse(HALF_SIZE * 0.15, 0, IMAGE_SIZE - IMAGE_SIZE * 0.15, IMAGE_SIZE, 0, 0, 2 * Math.PI);
drawEllipse(HALF_SIZE * 0.48, 0, IMAGE_SIZE - IMAGE_SIZE * 0.48, IMAGE_SIZE, 0, 0, 2 * Math.PI);
/* Compass */
ctx.fillStyle = 'red';
ctx.fillRect(0 + 16, needleLength, needleLength, 4);
ctx.fillText(compass_text[3], 0, needleLength + 8);
ctx.fillText(compass_text[2], needleLength + 16 + 4, needleLength + 8);
ctx.fillText(_('Longitude'), 0, IMAGE_SIZE - 16);
ctx.fillStyle = 'blue';
ctx.fillRect(0.5 * needleLength + 16, 0.5 * needleLength, 4, needleLength);
ctx.fillText(compass_text[0], 0.5 * needleLength + 16 - 4, 0.5 * needleLength - 8);
ctx.fillText(compass_text[1], 0.5 * needleLength + 16 - 4, 1.5 * needleLength + 16 + 4);
ctx.fillText(_('Latitude'), 0, IMAGE_SIZE - 40);
}
function drawEllipse(x, y, width, height, rotation, startAngle, endAngle, anticlockwise) {
/*
Wrapper for drawing ellipse on canvas
converts bounding-box drawing instructions to center-axes instructions
*/
ctx.beginPath();
x += width / 2;
y += height / 2;
var radiusX = width / 2;
var radiusY = height / 2;
ctx.ellipse(x, y, radiusX, radiusY, rotation, startAngle, endAngle, anticlockwise);
ctx.stroke();
}
function drawLine(x1, y1, x2, y2) {
/*
Wrapper for drawing line on canvas
*/
ctx.beginPath();
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.stroke();
}
function drawLabel(x, y, width, height, text) {
/*
Wrapper for placing text on canvas
*/
var labelColor = ctx.fillStyle;
ctx.fillRect(x, y, width, height);
ctx.fillStyle = 'white';
ctx.fillText(text, x + 5, y + 18);
ctx.fillStyle = labelColor;
}
function setImageSize(size) {
/*
Update IMAGE_SIZE as window resizes
*/
IMAGE_SIZE = size;
HALF_SIZE = 0.5 * IMAGE_SIZE;
}
return {
moon: drawMoon,
eclipse: drawEclipse,
grid: drawGrid,
setImageSize: setImageSize
};
});