カレンダーは、ユーザーがイベントを整理、スケジュール設定、追跡することを可能にするため、現代のWebアプリケーションにおいて欠かせない要素となっています。プロジェクト管理ツール、イベントスケジューリングアプリ、または個人向け生産性スイートを構築している場合、カスタムカレンダーコンポーネントはユーザーエクスペリエンスを大幅に向上させることができます。数多くの既製のカレンダーライブラリが存在していますが、独自のコンポーネントを作成することで、特定のデザインや機能要件に対応する柔軟性が得られます。
このチュートリアルでは、JavaScriptを使用してGoogleカレンダーのようなコンポーネントを構築する方法について探究します。このガイドの最後までには、インタラクティブな機能を備えた完全な機能を備えたカレンダーと、Webアプリケーション向けの再利用可能なコンポーネントを構築する方法についてより深く理解することができます。プロジェクトにユニークな要素を追加したい開発者であるか、カレンダー機能の内部動作を学びたい初心者であるかに関わらず、この段階ごとの解説は貴重なものになるでしょう。さあ、始めましょう!
概要
以下の機能を備えたカレンダーコンポーネントを作成します:
- 時間軸:午前0時から午後11時までの垂直タイムライン。
- イベントブロック:開始時間と終了時間に基づいて適切な位置と高さで動的にレンダリングされるイベント。
- 重複処理:時間が重なるイベントは隣接して表示されます。
このコンポーネントを段階的に作成する方法を以下に示します。
段階ごとのガイド
1. HTMLと基本的なスタイルの設定
カレンダーのために最小限のHTML構造を作成して始めます。レイアウトにはタイムラインとイベント用のコンテナが含まれています。
<div class="calendar">
<div class="calendar-time">
<ul id="timelist" class="calendar-timelist"></ul>
</div>
<div id="events" class="calendar-events"></div>
</div>
カレンダーのスタイリングのための基本的なCSSを追加します:
.calendar {
display: flex;
width: 500px;
margin: 20px auto;
position: relative;
}
.event {
background: #039be5;
border: 1px solid white;
border-radius: 5px;
position: absolute;
box-sizing: border-box;
color: white;
overflow: hidden;
padding: 3px;
}
.calendar-time {
border-right: 1px solid #ccc;
width: 100px;
}
.calendar-timelist {
list-style: none;
padding: 0;
margin: 0;
text-align: right;
padding-right: 20px;
}
.calendar-timelist li {
height: 60px;
box-sizing: border-box;
width: 100%;
}
.calendar-events {
flex-grow: 1;
position: relative;
}
2. カレンダーのJavaScriptクラスを作成
すべての機能をカプセル化するCalendar
クラスを定義します。
コンストラクタ
コンストラクタは、タイムラインとイベントをレンダリングしてカレンダーを初期化します:
class Calendar {
constructor(data) {
// Render the timeline on the Y-axis
this.renderTime();
// Render the event blocks
this.renderEvents(data);
}
renderTime() {
let timeHTML = Array.from({ length: 24 }, (_, i) => `<li>${this.to12HourFormat(i)}</li>`).join("");
document.getElementById("timelist").innerHTML = timeHTML;
}
renderEvents(data) {
let groupedEvents = this.groupEvents(data);
let eventData = this.calculateEventStyles(groupedEvents);
let eventHTML = eventData
.map(
(e) =>
`<div class="event" style="top: ${e.top}px; height: ${e.height}px; width: ${e.width}%; left: ${e.left}%; z-index: ${e.zIndex};">
<strong>${e.title}</strong><br>${e.time}
</div>`
)
.join("");
document.getElementById("events").innerHTML = eventHTML;
}
to12HourFormat(hour) {
if (hour === 0) return "12 AM";
if (hour < 12) return `${hour} AM`;
if (hour === 12) return "12 PM";
return `${hour - 12} PM`;
}
}
3. イベントの重複と位置の処理
重なるイベントを処理するためのロジックが必要です。これはグループ化して適切な位置を計算することによって達成されます。
開始時刻でイベントをグループ化
groupEvents(data) {
let groups = [];
data.forEach((event) => {
let hour = parseInt(event.start.split(":")[0], 10);
if (!groups[hour]) groups[hour] = [];
groups[hour].push(event);
});
return groups;
}
イベントのスタイルを計算
各グループに対して、時間と重複に基づいてイベントのtop
、height
、width
、left
を計算します。
calculateEventStyles(groups) {
let eventData = [];
groups.forEach((group) => {
let columns = [];
group.forEach((event) => {
let { start, end } = event;
let [sh, sm] = start.split(":").map(Number);
let [eh, em] = end.split(":").map(Number);
let top = sh * 60 + sm; // Convert start time to minutes
let height = (eh * 60 + em) - top; // Calculate duration in minutes
let left = columns.findIndex((col) => col.end <= start);
if (left === -1) {
left = columns.length;
columns.push({ end });
} else {
columns[left].end = end;
}
eventData.push({
title: event.name,
time: `${this.to12HourFormat(sh)} - ${this.to12HourFormat(eh)}`,
top,
height,
left: (left * 100) / columns.length,
width: 100 / columns.length,
zIndex: left,
});
});
});
return eventData;
}
4. サンプルデータと初期化
イベントデータを定義してCalendar
を初期化します:
const events = [
{ name: "Meeting with Donna", start: "09:00", end: "10:30" },
{ name: "Project Sync", start: "10:00", end: "11:00" },
{ name: "Lunch Break", start: "12:00", end: "13:00" },
{ name: "Client Call", start: "11:30", end: "12:30" },
];
new Calendar(events);
5. 完全なコード例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<title>Calendar Component</title>
</head>
<body>
<div class="calendar">
<div class="calendar-time">
<ul id="timelist" class="calendar-timelist"></ul>
</div>
<div id="events" class="calendar-events"></div>
</div>
<script src="script.js"></script>
</body>
</html>
結論
このアプローチでは、プレーンなJavaScriptを使用して、Googleカレンダーのようなコンポーネントを動的に生成します。 レンダリング時間、イベントのグループ化、スタイルの計算に問題を分解することで、スケーラブルでインタラクティブなコンポーネントを構築できます。 ドラッグ可能なイベントや追加のスタイリングなどの機能を追加するためにコードを実験することができます!
Source:
https://dzone.com/articles/building-a-google-calendar-like-component-using-javascript