├── planet_phase.html ├── LICENSE ├── README.md └── planet_phase.js /planet_phase.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 9 | 10 | 11 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Rob Dawson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # js-planet-phase 2 | 3 | This JavaScript library can be used to draw somewhat realistic lunar or planetary discs, complete with phase shadows: 4 | 5 |  6 | 7 | The library requires that browsers support the CSS `border-radius` and `box-shadow` properties, which means it [should work everywhere except IE8 (and earlier)](http://caniuse.com/#feat=css-boxshadow). 8 | 9 | To use the library, just include the [planet_phase.js](https://github.com/codebox/js-planet-phase/blob/master/planet_phase.js) file somewhere in your page, and call the `drawPlanetPhase` function once for each disc that you want to draw. 10 | 11 | The simplest way to call the function is like this: 12 | 13 |drawPlanetPhase(document.getElementById('container'), 0.15, true);
14 |
15 |
16 | * The first argument is the HTML element that you want to contain the disc.
17 | * The second argument must be a value between 0 and 1, indicating how large the shadow should be:
18 | * 0 = new moon
19 | * 0.25 = crescent
20 | * 0.50 = quarter
21 | * 0.75 = gibbous
22 | * 1.00 = full moon
23 | * The third argument is a boolean value indicating whether the disc should be waxing or waning (i.e. which side of the disc the shadow should be on):
24 | * true = waxing - shadow on the left
25 | * false = waning - shadow on the right
26 | * The function also accepts an optional fourth argument, containing configuration values which change the size, colour and appearance of the disc:
27 | * `shadowColour` - CSS background-colour value for the shaded part of the disc
28 | * `lightColour` - CSS background-colour value for the illuminated part of the disc
29 | * `diameter` - diameter of the disc in pixels
30 | * `earthshine` - a number between 0 and 1, specifying the amount of light falling on the shaded part of the disc (0 = none, 1 = full illumination)
31 | * `blur` - amount of blur on the terminator in pixels (0 = no blur)
32 |
--------------------------------------------------------------------------------
/planet_phase.js:
--------------------------------------------------------------------------------
1 | /*
2 | Defines the function 'drawPlanetPhase' which will render a 'kind of' realistic lunar or planetary disc with
3 | shadow.
4 |
5 | The simplest way to call the function is like this:
6 |
7 | drawPlanetPhase(document.getElementById('container'), 0.15, true)
8 |
9 | the first argument is the HTML element that you want to contain the disc
10 |
11 | the second argument must be a value between 0 and 1, indicating how large the shadow should be:
12 | 0 = new moon
13 | 0.25 = crescent
14 | 0.50 = quarter
15 | 0.75 = gibbous
16 | 1.00 = full moon
17 |
18 | the third argument is a boolean value indicating whether the disc should be waxing or waning (ie which
19 | side of the disc the shadow should be on):
20 | true = waxing - shadow on the left
21 | false = waning - shadow on the right
22 |
23 | the function accepts an optional fourth argument, containing configuration values which change the
24 | size, colour and appearance of the disc - see the comments on the 'defaultConfig' object for details.
25 |
26 | Copyright 2014 Rob Dawson
27 | http://codebox.org.uk/pages/planet-phase
28 | */
29 |
30 | var drawPlanetPhase = (function(){
31 | "use strict";
32 | /*jslint browser: true, forin: true, white: true */
33 |
34 | function calcInner(outerDiameter, semiPhase){
35 | var innerRadius,
36 | absPhase = Math.abs(semiPhase),
37 | n = ((1-absPhase) * outerDiameter/2) || 0.01;
38 |
39 | innerRadius = n/2 + outerDiameter * outerDiameter/ (8 * n);
40 |
41 | return {
42 | d : innerRadius * 2,
43 | o : semiPhase > 0 ? (outerDiameter/2 - n) : (-2 * innerRadius + outerDiameter/2 + n)
44 | };
45 | }
46 |
47 | function setCss(el, props){
48 | var p;
49 | for (p in props){
50 | el.style[p] = props[p];
51 | }
52 | }
53 | function drawDiscs(outer, inner, blurSize){
54 | var blurredDiameter, blurredOffset;
55 | setCss(outer.box, {
56 | 'position': 'absolute',
57 | 'height': outer.diameter + 'px',
58 | 'width': outer.diameter + 'px',
59 | 'border': '1px solid black',
60 | 'backgroundColor': outer.colour,
61 | 'borderRadius': (outer.diameter/2) + 'px',
62 | 'overflow': 'hidden'
63 | });
64 |
65 | blurredDiameter = inner.diameter - blurSize;
66 | blurredOffset = inner.offset + blurSize/2;
67 |
68 | setCss(inner.box, {
69 | 'position': 'absolute',
70 | 'backgroundColor': inner.colour,
71 | 'borderRadius': (blurredDiameter/2) + 'px',
72 | 'height': blurredDiameter + 'px',
73 | 'width': blurredDiameter + 'px',
74 | 'left': blurredOffset + 'px',
75 | 'top': ((outer.diameter-blurredDiameter)/2) + 'px',
76 | 'boxShadow': '0px 0px ' + blurSize + 'px ' + blurSize + 'px ' + inner.colour,
77 | 'opacity' : inner.opacity
78 | });
79 | }
80 | function makeDiv(container){
81 | var div = document.createElement('div');
82 | container.appendChild(div);
83 | return div;
84 | }
85 | function setPhase(outerBox, phase, isWaxing, config){
86 | var innerBox = makeDiv(outerBox),
87 | outerColour,
88 | innerColour,
89 | innerVals;
90 |
91 | if (phase < 0.5){
92 | outerColour = config.lightColour;
93 | innerColour = config.shadowColour;
94 | if (isWaxing){
95 | phase *= -1;
96 | }
97 | } else {
98 | outerColour = config.shadowColour;
99 | innerColour = config.lightColour;
100 | phase = 1 - phase;
101 | if (!isWaxing){
102 | phase *= -1;
103 | }
104 | }
105 |
106 | innerVals = calcInner(config.diameter, phase * 2);
107 |
108 | drawDiscs({
109 | box : outerBox,
110 | diameter : config.diameter,
111 | colour: outerColour
112 | }, {
113 | box : innerBox,
114 | diameter : innerVals.d,
115 | colour: innerColour,
116 | offset: innerVals.o,
117 | opacity : 1 - config.earthshine
118 | }, config.blur);
119 | }
120 |
121 | var defaultConfig = {
122 | shadowColour: 'black', // CSS background-colour value for the shaded part of the disc
123 | lightColour: 'white', // CSS background-colour value for the illuminated part of the disc
124 | diameter: 100, // diameter of the moon/planets disc in pixels
125 | earthshine : 0.1, // between 0 and 1, the amount of light falling on the shaded part of the disc 0=none, 1=full illumination
126 | blur: 3 // amount of blur on the terminator in pixels, 0=no blur
127 | };
128 |
129 | function populateMissingConfigValues(config){
130 | var p;
131 | for(p in defaultConfig) {
132 | config[p] = (config[p] === undefined) ? defaultConfig[p] : config[p];
133 | }
134 | return config;
135 | }
136 |
137 | return function(containerEl, phase, isWaxing, config){
138 | config = populateMissingConfigValues(Object.create(config || {}));
139 | var el = makeDiv(containerEl);
140 | setPhase(el, phase, isWaxing, config);
141 | };
142 |
143 | }());
144 |
--------------------------------------------------------------------------------