「Map のキーと値が線で結ばれるアニメーションつきデモ」です。
値を追加すると、キー → 値 が線で結ばれて「対応関係」が視覚的に表示されます。
すでにあるキーを再追加すると「更新される」様子もアニメーションでわかります。
See the Pen Map Operation Simulation (with Key and Value Lines) by MONO365 -Color your days- (@monoqlo365) on CodePen.
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Map の動作シミュレーション(キーと値の線つき)</title>
<style>
body {
font-family: "Segoe UI", sans-serif;
background: #f9fafb;
color: #333;
text-align: center;
padding: 30px;
}
h1 { color: #0078d7; }
.map-area {
display: flex;
justify-content: center;
align-items: flex-start;
flex-wrap: wrap;
gap: 40px;
position: relative;
margin-top: 40px;
}
.column {
display: flex;
flex-direction: column;
gap: 15px;
}
.key, .value {
background: #0078d7;
color: white;
padding: 10px 16px;
border-radius: 20px;
font-weight: bold;
min-width: 100px;
transition: transform 0.4s, background 0.4s;
}
.value { background: #00b894; }
.highlight { background: #ffb700 !important; transform: scale(1.1); }
svg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 300px;
pointer-events: none;
}
input {
padding: 8px;
margin: 5px;
border: 2px solid #0078d7;
border-radius: 8px;
}
button {
padding: 8px 14px;
border: none;
background: #0078d7;
color: white;
border-radius: 8px;
font-weight: bold;
cursor: pointer;
}
button:hover { background: #005fa3; }
.message {
margin-top: 20px;
font-size: 1.1em;
}
</style>
</head>
<body>
<h1>🗺️ Map のキーと値アニメーション</h1>
<p>Map に「キー」と「値」を追加してみよう!
キーと値が線で結ばれ、対応関係が見えるよ。</p>
<div>
<input id="keyInput" type="text" placeholder="キー(例: name)">
<input id="valueInput" type="text" placeholder="値(例: Halu)">
<button id="addBtn">追加</button>
</div>
<div class="map-area">
<div class="column" id="keysColumn"></div>
<svg id="lines"></svg>
<div class="column" id="valuesColumn"></div>
</div>
<div class="message" id="message"></div>
<script>
const map = new Map();
const keysColumn = document.getElementById("keysColumn");
const valuesColumn = document.getElementById("valuesColumn");
const svg = document.getElementById("lines");
const message = document.getElementById("message");
function drawLines() {
svg.innerHTML = "";
const keyEls = keysColumn.querySelectorAll(".key");
const valEls = valuesColumn.querySelectorAll(".value");
keyEls.forEach((kEl, i) => {
const vEl = valEls[i];
const kRect = kEl.getBoundingClientRect();
const vRect = vEl.getBoundingClientRect();
const svgRect = svg.getBoundingClientRect();
const x1 = kRect.right - svgRect.left;
const y1 = kRect.top + kRect.height / 2 - svgRect.top;
const x2 = vRect.left - svgRect.left;
const y2 = vRect.top + vRect.height / 2 - svgRect.top;
const line = document.createElementNS("http://www.w3.org/2000/svg", "line");
line.setAttribute("x1", x1);
line.setAttribute("y1", y1);
line.setAttribute("x2", x2);
line.setAttribute("y2", y2);
line.setAttribute("stroke", "#555");
line.setAttribute("stroke-width", "2");
line.setAttribute("stroke-linecap", "round");
svg.appendChild(line);
});
}
document.getElementById("addBtn").addEventListener("click", () => {
const key = document.getElementById("keyInput").value.trim();
const value = document.getElementById("valueInput").value.trim();
if (!key || !value) return;
const keyEls = [...keysColumn.children];
const existingIndex = keyEls.findIndex(el => el.textContent === key);
if (existingIndex >= 0) {
// 既存キー → 値更新
const valueEl = valuesColumn.children[existingIndex];
valueEl.textContent = value;
keyEls[existingIndex].classList.add("highlight");
valueEl.classList.add("highlight");
message.textContent = `🔄 キー "${key}" の値を "${value}" に更新しました。`;
setTimeout(() => {
keyEls[existingIndex].classList.remove("highlight");
valueEl.classList.remove("highlight");
}, 800);
} else {
// 新規追加
const keyEl = document.createElement("div");
keyEl.className = "key";
keyEl.textContent = key;
const valueEl = document.createElement("div");
valueEl.className = "value";
valueEl.textContent = value;
keysColumn.appendChild(keyEl);
valuesColumn.appendChild(valueEl);
message.textContent = `✅ 新しいペアを追加: 「${key} → ${value}」`;
}
map.set(key, value);
drawLines();
document.getElementById("keyInput").value = "";
document.getElementById("valueInput").value = "";
});
window.addEventListener("resize", drawLines);
</script>
</body>
</html>
HTMLこのデモのポイント
| 機能 | 内容 |
|---|---|
| 🎯 目的 | Map の「キー → 値」対応関係を視覚的に理解 |
| 🧭 構造 | 左:キー → 線 → 右:値 |
| ✨ アニメーション効果 | 新規追加はフェード表示、更新時はキー・値がハイライト |
| 🔁 リアルタイム再描画 | ウィンドウサイズ変更時も線を再計算 |
| 🧩 Map の特徴体感 | 既存キーを再設定すると「上書き」される動作が直感的にわかる |
試してみると…
- 「key: name」「value: Halu」を追加 → 線がつながる
- 「key: age」「value: 25」を追加 → もう1本線が出る
- 再び「key: name」「value: Taro」→ 値が更新されてハイライト💡


