🤝 Як долучитися

Додайте власну симуляцію, виправте помилку або напишіть статтю. Весь проєкт працює на статичних файлах — без інструментів збірки, без npm.

Продуктивність

  • ≥ 30 FPS на інтегрованому GPU (Intel UHD 620)
  • Використовуйте InstancedMesh для > 50 однакових об'єктів
  • Цикл requestAnimationFrame (без setInterval)
  • Масштабування devicePixelRatio для HiDPI-дисплеїв

Адаптивність

  • Сенсорні події: щипок, перетягування на мобільних
  • Полотно змінює розмір при зміні розміру вікна
  • Елементи керування читабельні при ширині вікна 360px
  • Мінімальна сенсорна ціль 44×44 px

Доступність

  • aria-label або role="img" на полотні
  • Усі повзунки мають aria-valuemin/max/now
  • Елементи керування доступні з клавіатури
  • Кнопка інформації про симуляцію (опис алгоритму)

SEO

  • Унікальні <title> та meta description
  • og:title, og:description, og:image
  • Посилання canonical та hreflang
  • JSON-LD SoftwareApplication + BreadcrumbList
  1. Створіть теку

    Додайте нову теку в корені проєкту зі слагом вашої симуляції (малі літери, дефіси). Скопіюйте файл шаблону як відправну точку:

    • Назва теки = ID симуляції, напр. double-pendulum/
    • Один файл: double-pendulum/index.html
    • Без підтек, без зовнішніх JS-файлів, увесь код вбудований
  2. Використайте HTML-шаблон

    Почніть із мінімального шаблону нижче. Він містить усі необхідні метатеги, спільну панель навігації/футер та полотно з правильними атрибутами ARIA.

    HTML
    <!DOCTYPE html>
    <html lang="uk" data-theme="dark">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link rel="canonical" href="https://www.mysimulator.uk/your-sim/">
      <title>Ваша симуляція — 3D Browser Simulations</title>
      <meta name="description" content="Короткий опис (≤ 160 символів).">
      <meta property="og:title" content="Ваша симуляція — 3D Browser Simulations">
      <meta property="og:description" content="Короткий опис.">
      <meta property="og:image" content="https://www.mysimulator.uk/preview/your-sim.jpg">
      <meta property="og:url" content="https://www.mysimulator.uk/your-sim/">
      <meta property="og:type" content="website">
      <meta name="twitter:card" content="summary_large_image">
      <link rel="preconnect" href="https://cdn.jsdelivr.net">
      <link rel="dns-prefetch" href="https://cdnjs.cloudflare.com">
      <link rel="stylesheet" href="../../shared/theme.css">
      <link rel="stylesheet" href="../../shared/components.css">
    </head>
    <body>
      <a href="#main-content" class="skip-link">Перейти до вмісту</a>
      <header id="navbar-root" data-base="../../" aria-label="Головна навігація"></header>
    
      <main id="main-content">
        <canvas id="canvas"
          role="img"
          aria-label="Інтерактивна Ваша симуляція — використовуйте мишу для взаємодії">
        </canvas>
        <!-- HUD додається через initSimHUD() -->
      </main>
    
      <footer id="footer-root" aria-label="Футер сайту"></footer>
    
      <script src="https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.min.js"></script>
      <script src="../../shared/components.js"></script>
      <script>
        /* ── Конфігурація симуляції для HUD ── */
        window.__SIM_INFO__ = {
          title: 'Ваша симуляція',
          category: 'physics',
          categoryPath: '../categories/physics/',
          description: 'Що показує ця симуляція та який алгоритм лежить в її основі.',
          controls: 'Миша: перетягуйте для обертання | Скрол: масштаб | R: скидання',
          tags: ['Three.js', 'Your-tag'],
          relatedIds: ['fluid', 'nbody']
        };
    
        /* ── Налаштування Three.js ── */
        const canvas = document.getElementById('canvas');
        const renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
        renderer.setSize(window.innerWidth, window.innerHeight);
    
        const scene  = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 0.1, 1000);
        camera.position.set(0, 0, 5);
    
        /* ── Код вашої симуляції ── */
        // TODO: фізика, геометрія, animate()
    
        function animate() {
          requestAnimationFrame(animate);
          // TODO: оновлення фізики
          renderer.render(scene, camera);
        }
        animate();
    
        /* ── Зміна розміру ── */
        window.addEventListener('resize', () => {
          camera.aspect = innerWidth / innerHeight;
          camera.updateProjectionMatrix();
          renderer.setSize(innerWidth, innerHeight);
        });
    
        /* ── Ініціалізація HUD (FPS, кнопка назад, повний екран, модальне вікно інфо) ── */
        if (typeof initSimHUD === 'function') initSimHUD(window.__SIM_INFO__);
      </script>
    </body>
    </html>
  3. Зареєструйте в simulations.json

    Додайте запис до shared/data/simulations.json. Усі поля обов'язкові, крім thumbnail та articleId:

    JSON
    {
      "id": "your-sim",
      "title": "Your Simulation Name",
      "titleUk": "Ваша Симуляція",
      "emoji": "🔬",
      "category": "physics",
      "description": "Одне речення, яке пояснює, що це симулює.",
      "tags": ["Three.js", "GLSL", "Your-Algorithm"],
      "difficulty": 3,
      "status": "ready",
      "featured": false,
      "dateAdded": "2026-03-14",
      "thumbnail": "/preview/your-sim.jpg",
      "controls": "Миша: перетягування | Скрол: масштаб | R: скидання",
      "algorithms": ["Algorithm Name"],
      "articleId": null,
      "fps": 60
    }
    • difficulty: 1 (тривіальна) → 5 (дослідницького рівня)
    • status: "ready" | "wip" | "planned"
    • category: одна з space physics nature life chaos math algorithms geometry chemistry sound
  4. Перебудуйте пошуковий індекс

    Після додавання до simulations.json перегенеруйте пошуковий індекс, щоб ваша симуляція з'явилася у глобальному пошуку:

    Shell
    node shared/scripts/build-search-index.js

    Це зчитує simulations.json, articles.json та categories.json і генерує shared/data/search-index.json.

  5. Протестуйте локально

    Відкрийте проєкт через локальний HTTP-сервер (не file:// — Service Worker потребує HTTP):

    Shell
    # Python (вбудований)
    python -m http.server 8080
    
    # Node.js (npx, встановлення не потрібне)
    npx serve .
    
    # VS Code: використайте розширення "Live Server"
    • Перевірте лічильник FPS — прагніть до ≥ 30 FPS на інтегрованому GPU
    • Протестуйте на мобільному вікні (Chrome DevTools → режим адаптивності)
    • Пройдіть Tab'ом усі елементи керування — кожен елемент має бути досяжним
    • Перевірте, що модальне вікно інфо (кнопка ⓘ в HUD) показує правильний текст

Ідеї для нових симуляцій

Назва Категорія Складність Алгоритм
Подвійний маятник Фізика Легка Лагранжева механіка, RK4
Лінії електричного поля Фізика Легка Закон Кулона, лінії течії
Діаграма Вороного Математика Легка Алгоритм Форчуна
Множина Мандельброта Математика Середня Час виходу у фрагментному шейдері GLSL
Дифузія тепла Фізика Середня Скінченні різниці, Кранк-Ніколсон
Квантовий гармонічний осцилятор Фізика Середня Хвильова функція Шредінгера
Реакція-дифузія (Грей-Скотт) Хімія Середня Розв'язання ДРЧП на текстурах GPU (ping-pong)
Симуляція розриву тканини Фізика Складна Позиційна динаміка, розщеплення сітки
Зв'язування SPH + твердих тіл Фізика Складна Зв'язування SPH + Cannon-es
Фрактали через ray marching Математика Складна Знакові функції відстані GLSL

📜 Кодекс поведінки

Цей проєкт відкритий і привітний до всіх. Беручи участь, ви погоджуєтеся дотримуватися цих правил:

✅ Робіть

  • Будьте шанобливими та конструктивними в усіх обговореннях
  • Вітайте новачків незалежно від рівня навичок
  • Надавайте чіткі, відтворювані звіти про помилки
  • Зосереджуйте кожен внесок на одній функції або виправленні
  • Пишіть самодокументований код зі змістовними іменами змінних
  • Зазначайте джерела зовнішніх алгоритмів і статей у коментарях коду

🚫 Не робіть

  • Не надсилайте симуляції із зовнішнім трекінгом чи аналітикою
  • Не копіюйте код шейдерів із закритим кодом без сумісної ліцензії
  • Не додавайте інструменти збірки, бандлери чи npm-залежності
  • Не вносьте зміни, що ламають сумісність, до shared/components.js без обговорення
  • Не використовуйте образливу, ворожу чи дискримінаційну лексику

Порушення можуть призвести до відхилення вашого внеску або позбавлення доступу. У серйозних випадках, будь ласка, звʼяжіться з нами.

🌟 Учасники

Дякуємо всім, хто допомагав створювати цей проєкт — симуляції, звіти про помилки, статті та відгуки щодо дизайну цінуються однаково.

Автори симуляцій

Створили та додали WebGL-симуляції до бібліотеки

Автори статей

Написали пояснення з математики та фізики в /content/

Репортери помилок

Подавали детальні звіти, що призвели до реальних покращень

Перекладачі

Допомогли втілити українську версію в життя

Хочете побачити своє ім'я тут? Виконайте кроки вище і надішліть нам свою роботу — ми будемо раді показати її.

🔌 API для вбудовування

Кожну симуляцію на цьому сайті можна вбудувати в будь-яку вебсторінку як самодостатній <iframe>. Без API-ключа, без облікового запису — просто скопіюйте фрагмент і вставте його у свій HTML.

Базовий iframe

Замініть fluid на слаг будь-якої симуляції (напр. rain, galaxy, double-slit).

HTML
<iframe
  src="https://www.mysimulator.uk/fluid/"
  title="Симуляція Рідини — 3D Browser Simulations"
  width="800"
  height="600"
  loading="lazy"
  allowfullscreen
  sandbox="allow-scripts allow-same-origin">
</iframe>

Параметри URL

Додайте параметри запиту, щоб налаштувати вбудовану симуляцію:

Параметр Значення Опис
?dark=1 0 / 1 Примусово світла (0) або темна (1) тема незалежно від системних налаштувань відвідувача
?ui=0 0 / 1 Сховати (0) або показати (1) накладку елементів керування HUD
?autoplay=1 0 / 1 Запустити симуляцію негайно (1) без очікування кліку користувача

Адаптивна обгортка

Використайте CSS-контейнер aspect-ratio, щоб iframe масштабувався коректно за будь-якої ширини екрана:

HTML
<!-- Адаптивний контейнер вбудовування 4:3 -->
<div style="position:relative;width:100%;aspect-ratio:4/3;overflow:hidden;border-radius:8px;">
  <iframe
    src="https://www.mysimulator.uk/fluid/"
    title="Симуляція Рідини — 3D Browser Simulations"
    style="position:absolute;inset:0;width:100%;height:100%;border:0;"
    loading="lazy"
    allowfullscreen
    sandbox="allow-scripts allow-same-origin">
  </iframe>
</div>

Атрибут sandbox="allow-scripts allow-same-origin" наполегливо рекомендований — він не дає вбудованій сторінці перенаправляти батьківський фрейм, відкривати спливні вікна чи отримувати доступ до файлів cookie поза власним джерелом.

Готові створити щось своє?

Проєкт має пласку структуру тек — без етапу збірки, без залежностей. Просто додайте теку та відкрийте її у браузері.