こんにちは!今回は、大切な予定までの時間を蝋燭で表現するWebアプリ「イノチノロウソク」を作ってみたので、紹介させていただきます。
なぜ作ったの?
カウントダウンって、ただ数字が減っていくだけじゃ面白くないなぁと思っていました。
特に以下のような課題を感じていました:
- スマホアプリはインストールが面倒
- 機能が多すぎてごちゃごちゃしてる
- 時間の経過が実感しづらい
そこで、「蝋燭が溶けていく」というちょっとユニークな演出を思いつき、普通のカウントダウンとは一味違うアプリを作ることにしました!
イノチノロウソクの特徴
1. ちょっと変わった演出!
- 実際の蝋燭みたいに、どんどん溶けていきます
- 炎がゆらゆら揺れるちょっとした演出付き
- ダークモードベースのシンプルなデザイン
2. めっちゃ簡単に使えます
- 日付と時間を選ぶだけでOK
- 目標や目的も設定できる(「資格試験日まで」とか!)
- 残り時間が一目で分かる
3. 意外と便利な機能も!
- ブラウザを閉じても設定が消えません
- スマホでもPCでも同じように使えます
- インストール不要でブラウザですぐ使える
こんな使い方がおすすめ!
- 試験までの残り時間
「あと3日…やばい、勉強しなきゃ!」 - 楽しみな予定までのカウントダウン
「長期休暇まであと30日!」
「推しのライブまであと2週間!」 - 締め切り管理
「レポート提出期限まで、あと2時間…がんばろ!」
技術的な裏側も少し紹介!
このアプリは React + TailwindCSS で作っています。
凝ったポイントをいくつか紹介させてください!
1. 蝋燭のアニメーション
// 蝋燭が溶けるアニメーションの実装
const Candle = ({ percentage }) => (
<div className="relative w-24 h-64 mx-auto my-8">
{/* 炎のアニメーション */}
<div className="absolute -top-8 left-1/2 -translate-x-1/2 w-8 h-12">
<div className="relative w-full h-full">
<div className="absolute inset-0 animate-flame">
<div className="w-8 h-12 bg-gradient-to-t from-amber-500 via-orange-400 to-yellow-300 rounded-full blur-sm" />
</div>
</div>
</div>
{/* 芯 */}
<div className="absolute -top-1 left-1/2 -translate-x-1/2 w-1 h-4 bg-slate-600" />
{/* 蝋燭本体 */}
<div className="relative w-full h-full bg-gradient-to-b from-gray-100 to-white rounded-t-sm overflow-hidden">
{/* 溶けた部分 */}
<div
className="absolute top-0 w-full bg-gradient-to-b from-gray-200 to-gray-300 transition-all duration-1000"
style={{ height: `${percentage}%` }}
/>
{/* 溶け落ちる効果 */}
{percentage > 0 && percentage < 100 && (
<div className="absolute top-0 left-1/2 -translate-x-1/2">
<div className="w-1 h-4 bg-gray-200 animate-drip opacity-50" />
</div>
)}
</div>
</div>
);
2. 時間管理の仕組み
// カウントダウンの核となる部分
const calculateTimeLeft = () => {
if (!targetDateTime) return;
const now = new Date().getTime();
const difference = targetDateTime.getTime() - now;
if (difference <= 0) {
setTimeLeft({
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
totalSeconds: 0,
percentage: 100,
});
setIsTimeUp(true);
return;
}
const totalSeconds = Math.floor(difference / 1000);
const percentage =
((initialTotalSeconds - totalSeconds) / initialTotalSeconds) * 100;
setTimeLeft({
days: Math.floor(difference / (1000 * 60 * 60 * 24)),
hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
minutes: Math.floor((difference / (1000 * 60)) % 60),
seconds: Math.floor((difference / 1000) % 60),
totalSeconds,
percentage,
});
};
3. ローカルストレージへのデータ保存
// データを保存する関数
const saveToLocalStorage = (data) => {
try {
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
} catch (error) {
console.error("Error saving to localStorage:", error);
}
};
// データを取得する関数
const loadFromLocalStorage = () => {
try {
const saved = localStorage.getItem(STORAGE_KEY);
return saved ? JSON.parse(saved) : null;
} catch (error) {
console.error("Error loading from localStorage:", error);
return null;
}
};
使ってみてね!
実際のアプリはこちらから使えます:
イノチノロウソクを使ってみる
最後に
このアプリを通じて、普段のカウントダウンをちょっと楽しく過ごしていただければ嬉しいです。