2025年2月26日水曜日

JavaScriptで自作widget作りました。

(時計とカレンダー、天気とかをまとめてサブモニターに表示できたら便利だよなぁ) 

と思って、JavaScriptで自作widgetを作りました。

Javaでプログラムを書いて、Winのアプリ化するとかのスキルは持っていないのでブラウザ表示で妥協。

 以下リンク↓

https://noricwidget.futene.net

 

ソースコードはこんな感じ。

どうせこんなサイトを作ったところで誰も使わないし、もっと優秀なアプリやサイトはたくさんあるので無意味だとは思います。 (自己満足)

一応、残しておきますね。

___________________________

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>時計とカレンダーのダッシュボード</title>
    <style>
        .container {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 20px;
            padding: 20px;
            max-width: 1200px;
            margin: 0 auto;
        }
        
        .analog-clock {
            width: 200px;
            height: 200px;
            border: 2px solid #333;
            border-radius: 50%;
            position: relative;
            margin: 0 auto;
            background: #f5f5f5;
        }

        .hand {
            position: absolute;
            bottom: 50%;
            left: 50%;
            transform-origin: bottom;
            background: #333;
        }

        .hour-hand { width: 4px; height: 60px; }
        .minute-hand { width: 3px; height: 80px; }
        .second-hand { width: 2px; height: 90px; background: #ff4444; }

        .digital-clock, .weather, .news {
            padding: 20px;
            border: 1px solid #ccc;
            border-radius: 5px;
            background: #fff;
            font-family: Arial, sans-serif;
        }

        .digital-clock { font-size: 24px; text-align: center; line-height: 1.5; }
        .weather { font-size: 24px; }
        .news { font-size: 20px; line-height: 1.5; }

        .calendar {
            margin-top: 10px;
            font-size: 14px;
            text-align: center;
        }

        .calendar table {
            width: 100%;
            border-collapse: collapse;
        }

        .calendar th, .calendar td {
            padding: 5px;
            border: 1px solid #ddd;
        }

        .calendar th {
            background: #f0f0f0;
        }

        .today {
            background: #ffeb3b;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="analog-clock">
            <div class="hand hour-hand"></div>
            <div class="hand minute-hand"></div>
            <div class="hand second-hand"></div>
        </div>
        <div class="digital-clock" id="digitalClock">
            <div id="dateTime"></div>
            <div class="calendar" id="calendar"></div>
        </div>
        <div class="weather" id="weatherInfo">天気情報を取得中...</div>
        <div class="news" id="newsFeed">ニュースを取得中...</div>
    </div>

    <script>
        // アナログとデジタル時計、カレンダーの更新
        function updateClocks() {
            const now = new Date();
            
            // デジタル時計と日付
            const dateString = now.toLocaleDateString('ja-JP', {
                year: 'numeric',
                month: 'long',
                day: 'numeric',
                weekday: 'long'
            });
            const timeString = now.toLocaleTimeString('ja-JP', { hour12: false });
            document.getElementById('dateTime').innerHTML = `${dateString}<br>${timeString}`;

            // アナログ時計
            const seconds = now.getSeconds();
            const minutes = now.getMinutes();
            const hours = now.getHours();
            
            const secondDeg = seconds * 6;
            const minuteDeg = minutes * 6 + seconds / 10;
            const hourDeg = (hours % 12) * 30 + minutes / 2;

            document.querySelector('.second-hand').style.transform = `rotate(${secondDeg}deg)`;
            document.querySelector('.minute-hand').style.transform = `rotate(${minuteDeg}deg)`;
            document.querySelector('.hour-hand').style.transform = `rotate(${hourDeg}deg)`;

            // カレンダー(月初に更新)
            if (seconds === 0 && minutes === 0 && hours === 0) {
                updateCalendar();
            }
        }

        // カレンダーの生成
        function updateCalendar() {
            const now = new Date();
            const year = now.getFullYear();
            const month = now.getMonth(); // 0-11(0が1月)
            const today = now.getDate();

            const firstDay = new Date(year, month, 1);
            const lastDay = new Date(year, month + 1, 0);
            const firstDayOfWeek = firstDay.getDay(); // 0(日曜)-6(土曜)
            const daysInMonth = lastDay.getDate();

            let calendarHTML = `<table><tr><th>日</th><th>月</th><th>火</th><th>水</th><th>木</th><th>金</th><th>土</th></tr><tr>`;
            
            // 最初の空白日
            for (let i = 0; i < firstDayOfWeek; i++) {
                calendarHTML += '<td></td>';
            }

            // 日付の追加
            for (let day = 1; day <= daysInMonth; day++) {
                const currentDayOfWeek = (firstDayOfWeek + day - 1) % 7;
                if (currentDayOfWeek === 0 && day !== 1) {
                    calendarHTML += '</tr><tr>';
                }
                const className = (day === today) ? ' class="today"' : '';
                calendarHTML += `<td${className}>${day}</td>`;
            }

            // 残りの空白日
            const remainingCells = (7 - ((firstDayOfWeek + daysInMonth) % 7)) % 7;
            for (let i = 0; i < remainingCells; i++) {
                calendarHTML += '<td></td>';
            }

            calendarHTML += '</tr></table>';
            document.getElementById('calendar').innerHTML = calendarHTML;
        }

        // 天気情報の取得
        async function updateWeather() {
            try {
                const apiKey = 'あなたのOpenWeatherMapAPIキー';
                const city = 'Tokyo';
                const response = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric&lang=ja`);
                const data = await response.json();
                document.getElementById('weatherInfo').textContent = `${data.name}: ${data.weather[0].description}, ${data.main.temp}°C`;
            } catch (error) {
                document.getElementById('weatherInfo').textContent = '天気情報の取得に失敗しました';
                console.error('Weather API error:', error);
            }
        }

        // ニュースの取得
        async function updateNews() {
            try {
                const apiKey = 'あなたのNewsAPIキー';
                const response = await fetch(`https://newsapi.org/v2/top-headlines?country=jp&apiKey=${apiKey}`);
                const data = await response.json();
                const newsItem = data.articles[0];
                document.getElementById('newsFeed').textContent = `${newsItem.title} - ${newsItem.source.name}`;
            } catch (error) {
                document.getElementById('newsFeed').textContent = 'ニュースの取得に失敗しました';
                console.error('News API error:', error);
            }
        }

        // 初期表示と定期更新
        updateClocks();
        updateCalendar(); // 初回カレンダー表示
        updateWeather();
        updateNews();
        setInterval(updateClocks, 1000);    // 1秒ごとに時計更新
        setInterval(updateWeather, 60000); // 1分ごとに天気更新
        setInterval(updateNews, 300000);   // 5分ごとにニュース更新
    </script>
</body>
</html> 


___________________________________

 OpenWeatherMapAPIは割とすぐ反映されますけど、NewsAPIの反映が地味に長いし無料で使えるライセンスのバージョンだと意外と制約が多い…

 

テスト運用名のなので、そのうち作り変えます、そのうちね。

 

(終了)

 

 

 

0 件のコメント:

コメントを投稿

雑記。近況報告や今後の目標など

【網膜裂孔】 結膜炎になって数カ月後、眼科で検査を受けた際に網膜裂孔が発覚した。今は完全に完治しているが、検査の重要性を改めて実感した。痛みや明確な症状も特になかった。私の場合、目は命そのものだと感じるほど大切なので、以前よりも目の健康について真剣に考えるようになった。30歳...