JavaScript | 実際に Map / Set を操作するデモ

JavaScript
スポンサーリンク

「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 の特徴体感既存キーを再設定すると「上書き」される動作が直感的にわかる

試してみると…

  1. 「key: name」「value: Halu」を追加 → 線がつながる
  2. 「key: age」「value: 25」を追加 → もう1本線が出る
  3. 再び「key: name」「value: Taro」→ 値が更新されてハイライト💡
タイトルとURLをコピーしました