| Cỡ chữ:   
<!DOCTYPE html> <html> <head> <link rel="stylesheet" href="style.css"> </head> <body> <div id="controls"> <h3>Bảng Điều Khiển ????</h3> <input type="text" id="idea-text" placeholder="Nhập ý tưởng..."> <button id="add-planet-btn">Thêm Hành Tinh (Ý tưởng chính)</button> <p style="font-size: 12px; margin: 0; text-align: center; opacity: 0.8;"><i>*Chọn một hành tinh trước*</i></p> <button id="add-asteroid-btn" disabled>Thêm Tiểu Hành Tinh (Ý tưởng con)</button> </div> <div id="mindmap-container"></div> <script src="script.js"></script> </body> </html>
/* CSS cho giao diện */ :root { --background-color: #00001a; --text-color: #f0f0f0; --control-panel-bg: rgba(25, 25, 55, 0.85); --control-panel-border: #4a4a8a; --button-bg: #4a4a8a; --button-hover-bg: #6a6acc; --input-bg: #1a1a3a; --planet-shadow: rgba(255, 255, 200, 0.6); --planet-selected-glow: #ffdd44; --orbit-color: rgba(255, 255, 255, 0.4); } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: var(--background-color); color: var(--text-color); margin: 0; padding: 0; overflow: hidden; /* Ngăn thanh cuộn xuất hiện */ display: flex; justify-content: center; align-items: center; } #mindmap-container { position: relative; width: 100vw; height: 100vh; /* Tạo hiệu ứng các vì sao lấp lánh bằng background */ background-image: radial-gradient(1px 1px at 20px 30px, white, transparent), radial-gradient(1px 1px at 40px 70px, white, transparent), radial-gradient(1px 1px at 80px 120px, white, transparent), radial-gradient(1.5px 1.5px at 150px 80px, white, transparent), radial-gradient(1px 1px at 180px 20px, white, transparent); background-repeat: repeat; background-size: 200px 200px; } #controls { position: fixed; top: 20px; left: 20px; background: var(--control-panel-bg); padding: 15px 20px; border-radius: 12px; z-index: 1000; display: flex; flex-direction: column; gap: 12px; border: 1px solid var(--control-panel-border); backdrop-filter: blur(5px); box-shadow: 0 4px 20px rgba(0, 0, 0, 0.4); } #controls h3 { margin: 0; padding-bottom: 5px; border-bottom: 1px solid var(--control-panel-border); text-align: center; } #idea-text { padding: 10px; border-radius: 8px; border: 1px solid var(--control-panel-border); background-color: var(--input-bg); color: var(--text-color); width: 200px; outline: none; transition: border-color 0.3s; } #idea-text:focus { border-color: var(--button-hover-bg); } button { padding: 10px; border-radius: 8px; border: none; background-color: var(--button-bg); color: var(--text-color); cursor: pointer; font-weight: bold; transition: background-color 0.3s, transform 0.1s; } button:hover { background-color: var(--button-hover-bg); } button:active { transform: scale(0.98); } button:disabled { background-color: #333; cursor: not-allowed; opacity: 0.6; } .planet, .asteroid { position: absolute; border-radius: 50%; display: flex; justify-content: center; align-items: center; text-align: center; padding: 5px; box-sizing: border-box; cursor: pointer; color: #000; font-weight: bold; transition: box-shadow 0.3s ease-in-out; user-select: none; /* Ngăn chọn văn bản */ } .planet { width: 120px; height: 120px; background: radial-gradient(circle, #ffcc00, #ff6600); box-shadow: 0 0 20px 5px var(--planet-shadow); z-index: 10; font-size: 16px; } .asteroid { width: 60px; height: 60px; background: radial-gradient(circle, #c0c0c0, #808080); box-shadow: 0 0 10px rgba(200, 200, 200, 0.5); z-index: 20; font-size: 12px; } .planet.selected { box-shadow: 0 0 30px 10px var(--planet-selected-glow); } .orbit { position: absolute; border: 1px dashed var(--orbit-color); border-radius: 50%; /* Sẽ thành elip vì width != height */ pointer-events: none; /* Cho phép click xuyên qua quỹ đạo */ z-index: 5; }
document.addEventListener('DOMContentLoaded', () => { // --- Lấy các phần tử DOM cần thiết --- const container = document.getElementById('mindmap-container'); const ideaText = document.getElementById('idea-text'); const addPlanetBtn = document.getElementById('add-planet-btn'); const addAsteroidBtn = document.getElementById('add-asteroid-btn'); let selectedPlanet = null; // Lưu trữ hành tinh đang được chọn // --- Hàm tạo một hành tinh mới --- function createPlanet(text) { const planet = document.createElement('div'); planet.className = 'planet'; planet.textContent = text; planet.dataset.asteroids = 0; // Dùng để đếm số tiểu hành tinh của hành tinh này // Đặt hành tinh ở một vị trí ngẫu nhiên, tránh các cạnh màn hình const containerRect = container.getBoundingClientRect(); const planetSize = 120; const x = Math.random() * (containerRect.width - planetSize * 2) + planetSize; const y = Math.random() * (containerRect.height - planetSize * 2) + planetSize; planet.style.left = `${x}px`; planet.style.top = `${y}px`; // Sự kiện khi click vào hành tinh planet.addEventListener('click', (e) => { e.stopPropagation(); // Ngăn sự kiện click lan ra container selectPlanet(planet); }); container.appendChild(planet); return planet; } // --- Hàm tạo một tiểu hành tinh mới --- function createAsteroid(text, parentPlanet) { const asteroid = document.createElement('div'); asteroid.className = 'asteroid'; asteroid.textContent = text; container.appendChild(asteroid); // Tăng số lượng tiểu hành tinh của hành tinh mẹ const numAsteroids = parseInt(parentPlanet.dataset.asteroids) + 1; parentPlanet.dataset.asteroids = numAsteroids; // --- Thiết lập quỹ đạo Elip --- const parentRect = parentPlanet.getBoundingClientRect(); const parentCenterX = parentRect.left + parentRect.width / 2; const parentCenterY = parentRect.top + parentRect.height / 2; // Bán kính trục x và y của elip, tăng dần cho mỗi tiểu hành tinh mới const rx = 100 + numAsteroids * 45; const ry = 70 + numAsteroids * 30; const angleOffset = Math.random() * Math.PI * 2; // Góc bắt đầu ngẫu nhiên để chúng không bị xếp chồng const speed = (0.005 + Math.random() * 0.005) * (Math.random() > 0.5 ? 1 : -1); // Tốc độ và hướng quay ngẫu nhiên // Vẽ quỹ đạo (một div hình elip) const orbit = document.createElement('div'); orbit.className = 'orbit'; orbit.style.width = `${rx * 2}px`; orbit.style.height = `${ry * 2}px`; orbit.style.left = `${parentCenterX - rx}px`; orbit.style.top = `${parentCenterY - ry}px`; container.appendChild(orbit); // --- Animation cho tiểu hành tinh --- let angle = 0; function animate() { angle += speed; // Công thức tính tọa độ trên một elip const x = parentCenterX + rx * Math.cos(angle + angleOffset) - asteroid.offsetWidth / 2; const y = parentCenterY + ry * Math.sin(angle + angleOffset) - asteroid.offsetHeight / 2; asteroid.style.left = `${x}px`; asteroid.style.top = `${y}px`; requestAnimationFrame(animate); // Lặp lại animation cho khung hình tiếp theo } animate(); // Bắt đầu animation } // --- Hàm quản lý việc chọn hành tinh --- function selectPlanet(planet) { // Bỏ chọn hành tinh cũ (nếu có) if (selectedPlanet) { selectedPlanet.classList.remove('selected'); } // Chọn hành tinh mới và làm nó phát sáng selectedPlanet = planet; selectedPlanet.classList.add('selected'); addAsteroidBtn.disabled = false; // Kích hoạt nút thêm tiểu hành tinh } // --- Hàm bỏ chọn tất cả --- function deselectAll() { if (selectedPlanet) { selectedPlanet.classList.remove('selected'); } selectedPlanet = null; addAsteroidBtn.disabled = true; // Vô hiệu hóa lại nút } // --- Gán sự kiện cho các nút điều khiển --- addPlanetBtn.addEventListener('click', () => { const text = ideaText.value.trim(); if (text) { createPlanet(text); ideaText.value = ''; ideaText.focus(); } else { alert('Vui lòng nhập tên cho hành tinh!'); } }); addAsteroidBtn.addEventListener('click', () => { const text = ideaText.value.trim(); if (text && selectedPlanet) { createAsteroid(text, selectedPlanet); ideaText.value = ''; ideaText.focus(); } else if (!text) { alert('Vui lòng nhập tên cho tiểu hành tinh!'); } }); // Cho phép nhấn Enter để thêm ideaText.addEventListener('keyup', (e) => { if (e.key === 'Enter') { if (selectedPlanet && !addAsteroidBtn.disabled) { addAsteroidBtn.click(); } else { addPlanetBtn.click(); } } }); // Bỏ chọn khi click ra nền không gian container.addEventListener('click', deselectAll); });