forked from codebox/js-planet-phase
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplanet_phase.js
executable file
·143 lines (122 loc) · 4.96 KB
/
planet_phase.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
Defines the function 'drawPlanetPhase' which will render a 'kind of' realistic lunar or planetary disc with
shadow.
The simplest way to call the function is like this:
drawPlanetPhase(document.getElementById('container'), 0.15, true)
the first argument is the HTML element that you want to contain the disc
the second argument must be a value between 0 and 1, indicating how large the shadow should be:
0 = new moon
0.25 = crescent
0.50 = quarter
0.75 = gibbous
1.00 = full moon
the third argument is a boolean value indicating whether the disc should be waxing or waning (ie which
side of the disc the shadow should be on):
true = waxing - shadow on the left
false = waning - shadow on the right
the function accepts an optional fourth argument, containing configuration values which change the
size, colour and appearance of the disc - see the comments on the 'defaultConfig' object for details.
Copyright 2014 Rob Dawson
http://codebox.org.uk/pages/planet-phase
*/
var drawPlanetPhase = (function(){
"use strict";
/*jslint browser: true, forin: true, white: true */
function calcInner(outerDiameter, semiPhase){
var innerRadius,
absPhase = Math.abs(semiPhase),
n = ((1-absPhase) * outerDiameter/2) || 0.01;
innerRadius = n/2 + outerDiameter * outerDiameter/ (8 * n);
return {
d : innerRadius * 2,
o : semiPhase > 0 ? (outerDiameter/2 - n) : (-2 * innerRadius + outerDiameter/2 + n)
};
}
function setCss(el, props){
var p;
for (p in props){
el.style[p] = props[p];
}
}
function drawDiscs(outer, inner, blurSize){
var blurredDiameter, blurredOffset;
setCss(outer.box, {
'position': 'absolute',
'height': outer.diameter + 'px',
'width': outer.diameter + 'px',
'border': '1px solid black',
'backgroundColor': outer.colour,
'borderRadius': (outer.diameter/2) + 'px',
'overflow': 'hidden'
});
blurredDiameter = inner.diameter - blurSize;
blurredOffset = inner.offset + blurSize/2;
setCss(inner.box, {
'position': 'absolute',
'backgroundColor': inner.colour,
'borderRadius': (blurredDiameter/2) + 'px',
'height': blurredDiameter + 'px',
'width': blurredDiameter + 'px',
'left': blurredOffset + 'px',
'top': ((outer.diameter-blurredDiameter)/2) + 'px',
'boxShadow': '0px 0px ' + blurSize + 'px ' + blurSize + 'px ' + inner.colour,
'opacity' : inner.opacity
});
}
function makeDiv(container){
var div = document.createElement('div');
container.appendChild(div);
return div;
}
function setPhase(outerBox, phase, isWaxing, config){
var innerBox = makeDiv(outerBox),
outerColour,
innerColour,
innerVals;
if (phase < 0.5){
outerColour = config.lightColour;
innerColour = config.shadowColour;
if (isWaxing){
phase *= -1;
}
} else {
outerColour = config.shadowColour;
innerColour = config.lightColour;
phase = 1 - phase;
if (!isWaxing){
phase *= -1;
}
}
innerVals = calcInner(config.diameter, phase * 2);
drawDiscs({
box : outerBox,
diameter : config.diameter,
colour: outerColour
}, {
box : innerBox,
diameter : innerVals.d,
colour: innerColour,
offset: innerVals.o,
opacity : 1 - config.earthshine
}, config.blur);
}
var defaultConfig = {
shadowColour: 'black', // CSS background-colour value for the shaded part of the disc
lightColour: 'white', // CSS background-colour value for the illuminated part of the disc
diameter: 100, // diameter of the moon/planets disc in pixels
earthshine : 0.1, // between 0 and 1, the amount of light falling on the shaded part of the disc 0=none, 1=full illumination
blur: 3 // amount of blur on the terminator in pixels, 0=no blur
};
function populateMissingConfigValues(config){
var p;
for(p in defaultConfig) {
config[p] = (config[p] === undefined) ? defaultConfig[p] : config[p];
}
return config;
}
return function(containerEl, phase, isWaxing, config){
config = populateMissingConfigValues(Object.create(config || {}));
var el = makeDiv(containerEl);
setPhase(el, phase, isWaxing, config);
};
}());