目次
サンプル・プログラムの実行例
サンプル・プログラム
| moonage.php | サンプル・プログラム本体。 |
| fullmoon.webp | 満月画像。 |
| pahooCalendar.php | 暦・潮位計算クラス pahooCalendar。 暦・潮位計算クラスの使い方は「PHPで二十四節気・七十二候一覧を作成」「PHPで月齢を計算」「PHPで日出没・月出没・月齢・潮を計算」「PHPで潮位を計算する」などを参照。include_path が通ったディレクトリに配置すること。 |
| pahooInputData.php | データ入力に関わる関数群。 使い方は「PHPでGET/POSTでフォームから値を受け取る」「数値入力とバリデーション」「文字入力とバリデーション」などを参照。include_path が通ったディレクトリに配置すること。 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 1.4.0 | 2026/01/24 | PHP8.5対応:curl_closeを使わない |
| 1.3.0 | 2023/01/16 | 現在の月齢をデフォルト値にする |
| 1.2 | 2021/12/18 | PHP8対応,リファラ・チェック改良 |
| 1.1 | 2015/12/19 | 改良 |
| 1.0 | 2015/12/13 | 初版 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 2.0.1 | 2025/08/11 | getParam() bug-fix |
| 2.0.0 | 2025/08/11 | pahooLoadEnv() 追加 |
| 1.9.0 | 2025/07/26 | getParam() 引数に$trim追加 |
| 1.8.1 | 2025/03/15 | validRegexPattern() debug |
| 1.8.0 | 2024/11/12 | validRegexPattern() 追加 |
| バージョン | 更新日 | 内容 |
|---|---|---|
| 4.6.1 | 2025/11/23 | next_fullmoon: bug-fix |
| 4.6.0 | 2025/10/08 | getMidAutumnMoon() 追加 |
| 4.5.1 | 2025/05/31 | deg2ddmm(), deg2hhmm() 不具合修正 |
| 4.5.0 | 2024/03/17 | ヒジュラ暦メソッドを追加 |
| 4.4.1 | 2024/03/17 | getCabinetOfficeHolidayTable() -- bug-fix |
準備:初期値など
moonage.php
56: // 各種定数(START) ===========================================================
57:
58: // 満月の画像
59: // PNG形式限定
60: // 正方形で,領域いっぱいに真円の満月が描かれていること.
61: // 背景は透明であること.
62: define('FULLMOON', 'fullmoon.png');
63:
64: // 影の透明度(0~127):0 は完全に不透明な状態。 127 は完全に透明な状態
65: define('ALPHA', 30);
66:
67: // 明部分を白色で塗るかどうか
68: define('MOON_BRIGHT', FALSE);
69:
70: // 画像データ保存機能を使うかどうか TRUE:使う,FALSE:使わない
71: define('ISSAVE', FALSE);
72:
73: // 画像を保存するフォルダ
74: define('SAVE_PATH', './');
75:
76: // 表示幅(ピクセル)
77: define('WIDTH', 600);
78:
79: // 表示言語(jp:日本語, en:英語, en3:英語略記)
80: define('LANGUAGE', 'jp');
81:
82: // 世界時からの時差(日本標準時)
83: define('UTCDIFF', +9.0);
84:
85: // 各種定数(END) ===============================================================
満月の写真があれば、それを定数 FULLMOON に指定する。
ただし、写真はPNG形式限定。大きさの制限はないが、正方形で、領域いっぱいに真円の満月が描かれていること。また、背景は透明であることが望ましい。
今回は、影の部分だけ半透明の黒で塗りつぶすだけだが、もし太陽光の当たっている明部分を白で塗りたければ、定数 MOON_BRIGHT を TRUE にする。
影や明部分の透明度を制御するアルファチャネルの値は定数 ALPHA に指定する。0 は完全に不透明な状態、127 は完全に透明な状態となる。
月齢ごとの満ち欠け画像を保存するフォルダを、定数 SAVE_PATH に指定する。
データ入力に関わる関数群は別ファイル "pahooInputData.php" に分離しており、include_path が通ったディレクトリに配置すること。
また、暦計算クラス・ファイル "pahooCalendar.php" もinclude_pathが通ったディレクトリに配置すること。
準備:pahooInputData 関数群
また、各種クラウドサービスに登録したときに取得するアカウント情報、アプリケーションパスワードなどを登録した .pahooEnv ファイルから読み込む関数 pahooLoadEnv を備えている。こちらについては、「各種クラウド連携サービス(WebAPI)の登録方法」をご覧いただきたい。
準備:pahooCalendar クラス
pahooCalendar.php
11: class pahooCalendar {
12: var $CONVERGE = 0.00005; // 逐次近似計算収束判定値
13: var $ASTRO_REFRACT = 0.585556; // 大気差
14: var $TDIFF = +9.0; // 世界時との時差
15: var $error, $errmsg; // エラーフラグ,エラーメッセージ
16: var $year, $month, $day; // 西暦年月日
17: var $tblmoon; // グレゴリオ暦=旧暦テーブル
18: var $language; // 表示言語(jp:日本語, en:英語, en3:英語略記)
19: var $resolve2033; // 旧暦2033年問題解決案 0:解決しない,1:案1,2:案2,3:対応案3 → https://www.pahoo.org/e-soul/webtech/php02/php02-45-01.shtm#php_resolveLunarCalendar2033
20: var $pcc; // pahooCacheインスタンス
21: var $CabinetOfficeHolidayTables; // 内閣府が公開している祝日表
22: const CABINETOFFICE_HOLIDAY_FILE = 'https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv'; // 内閣府が公開している祝日表URL
23:
24: /**
25: * コンストラクタ
26: * @param string $language 表示言語;省略時 jp
27: * @param float $tdiff 世界時との時差(省略時 +9.0;日本標準時)
28: * @param object $pcc pahooCacheインスタンス;省略時 NULL
29: * インターネット経由で内閣府の国民の祝日を参照するときに指定
30: * @return bool オブジェクト/FALSE:$tdiffが不正
31: */
32: function __construct($language='jp', $tdiff=+9.0, $pcc=NULL) {
33: $this->error = FALSE;
34: $this->errmsg = '';
35: $this->year = date('Y');
36: $this->month = date('n');
37: $this->day = date('j');
38: $this->resolve2033 = 0;
39: $this->pcc = $pcc;
40: $this->CabinetOfficeHolidayTables = array();
41:
42: $this->setLanguage($language);
43: if ($this->setTimeDifference($tdiff) == FALSE) {
44: $this->error = TRUE;
45: $this->errmsg = 'illegal tdiff';
46: }
47: }
解説:指定した月齢の月の満ち欠けを描く
moonage.php
160: /**
161: * 指定した月齢の月の満ち欠けを描く.
162: * @param double $age 月齢
163: * @return object GDリソース
164: */
165: function drawMissingMoon($age) {
166: if ($age < 0 || $age > 30) $age = 0;
167:
168: // 満月画像がなければ円を描画
169: if (! file_exists(FULLMOON)) {
170: $dd = 500; // 直径
171: $rr = $dd / 2; // 半径
172: $image = imagecreatetruecolor($dd, $dd);
173: // 背景透明化
174: $bgcolor = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);// 背景色セット
175: imagefill($image, 0, 0, $bgcolor);
176: imagecolortransparent($image, $bgcolor);
177: // 円を描画
178: $color = imagecolorallocate($image, 0xFF, 0xFF, 0x7F);
179: imagefilledarc($image, $rr, $rr, $dd, $dd, 0, 360, $color, IMG_ARC_PIE);
180:
181: // 満月画像の読み込み
182: } else {
183: if (($arr = getimagesize(FULLMOON)) == FALSE) return FALSE;
184: $dd = $arr[0]; // 直径
185: $rr = $dd / 2; // 半径
186: // 画像読み込み
187: $image = imagecreatefrompng(FULLMOON);
188: }
189:
190: // 完全なアルファチャネル情報を保存するフラグをonにする
191: imagesavealpha($image, TRUE);
192: // カラー設定
193: $black = imagecolorallocatealpha($image, 0x00, 0x00, 0x00, ALPHA);
194: $white = imagecolorallocatealpha($image, 0xFF, 0xFF, 0xFF, ALPHA);
195:
196: // 影を描く
197: $x0 = $rr;
198: $y0 = $rr;
199: $th = $age / 14.765 * pi();
200: for ($y = -$rr; $y <= 0; $y++) {
201: $ac = acos($y / $rr);
202: $x2 = $rr * sin($ac); // 円周
203: $x1 = $rr * cos($th) * sin($ac); // 月の形
204: if (($age > 0.5) && ($age < 29.5)) {
205: if ($age < 15.0) {
206: $x3i = round($x0 + $x1);
207: $x4i = round($x0 + $x2);
208: $x5i = round($x0 - $x2);
209: $y3i = round($y0 + $y);
210: $y4i = round($y0 - $y);
211: } else {
212: $x3i = round($x0 - $x1);
213: $x4i = round($x0 - $x2);
214: $x5i = round($x0 + $x2);
215: $y3i = round($y0 + $y);
216: $y4i = round($y0 - $y);
217: }
218: imageline($image, $x3i, $y3i, $x5i, $y3i, $black);
219: if (MOON_BRIGHT) imageline($image, $x3i, $y3i, $x4i, $y3i, $white);
220: if ($y != 0) {
221: imageline($image, $x3i, $y4i, $x5i, $y4i, $black);
222: if (MOON_BRIGHT) {
223: imageline($image, $x3i, $y4i, $x4i, $y4i, $white);
224: }
225: }
226: } else {
227: $x3i = round($x0 - $x2);
228: $x4i = round($x0 + $x2);
229: $y3i = round($y0 + $y);
230: $y4i = round($y0 - $y);
231: imageline($image, $x3i, $y3i, $x4i, $y3i, $black);
232: if ($y != 0) {
233: imageline($image, $x3i, $y4i, $x4i, $y4i, $black);
234: }
235: }
236: }
237: return $image;
238: }
冒頭で、 file_exists を使い、満月画像 FULLMOON を探す。なければ円を描画する。
後半では、満月画像を読み込んで、影の部分を描画関数 imageline を使って1ラインずつ塗りつぶしていく。
遠方からやってくる太陽光線は直線になっているものと仮定する。ここで、太陽-地球-月のなす角をを $ \theta $ とする。
このときの月を拡大したのが図2である。
月の中心をOとすると、地球から観たときに明部分となっているのは、ACの部分である。
地球の中心をEとすると、$ \angle{AEC} = \theta = \angle{AOC} $ となる。
ここで、$ R = OA = OC $ であるので、$ AC = R \ cos \ \theta $ と計算できる。
$ R $ は、両極(緯度90°)で0、赤道(緯度0°)で月の半径と等しくなる。
月は真円であるので、月の緯度をγとするとRは $ R = sin \ \gamma $ で計算できる。
以上のことから、月の明部分の長さは $ sin \ \gamma \ cos \ \theta $ で計算できる。これを月の半径から減じたものが影の部分の長さになる。
$ \theta $ は月齢と同じ意味である。$ \theta = 180 ^\circ $(月齢15)を境界条件とし、月の南北で影の長さが同じであることから計算量を減らしたのがユーザー関数 draw_moonage の肝の部分となる。
参考サイト
- PHPで日出没・月出没・月齢を計算:ぱふぅ家のホームページ
- 月(moon)の形がr*sin(θ)*cos(α)で求められる理由:MLTLabのブログ
- 位相とは:スーパーサイエンスガール
- [html5]canvasタグで月の満ち欠けを書いてみる:tomotomo Snippet
- 位相角と輝面率(輝面比)の計算法:セッピーナの趣味の天文計算

(2026年1月24日)PHP8.5対応:imagedestroyを使わない