From 239e54540ed11e9e95e8565f9fdf4186e9cef43b Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Sat, 30 May 2026 09:30:37 +0300 Subject: [PATCH] =?UTF-8?q?feat(phys9):=20=D0=B5=D0=B4=D0=B8=D0=BD=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=B0=D0=BB=D0=B8=D1=82=D1=80=D0=B0=20=D1=86?= =?UTF-8?q?=D0=B2=D0=B5=D1=82=D0=BE=D0=B2=20PHYS9=5FCOLORS=20(Phase=202)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Новый модуль frontend/js/phys9_palette.js — экспортирует window.PHYS9_COLORS с цветами для всех кинематических, динамических, энергетических и геометрических величин Физики 9. Структура палитры: - velocity / acceleration / displacement / position / time - force / forceGravity / forceFriction / forceNormal / forceSpring / forceTension - energyK / energyP / work / power - body / bodyAccent / liquid / gas / surface - angle / axis / grid / dashed - plotPrimary / plotSecondary / plotTertiary - text / textMuted / textLabel - bg / bgSubtle / bgCard - ok / warn / fail Палитра автоматически переключается между светлой и тёмной темой через get-проперти, проверяющий html.dark / body.dark. Утилиты: - PHYS9_COLORS.vector('F'|'v'|'mg'|...) — цвет вектора по типу - PHYS9_COLORS.byClass('kinematic'|'dynamic'|...) — цвет по классу Подключён во все 5 ch-страниц до phys9_legacy.js. Подготовка к Phase 3 — перенос hardcoded #цветов в legacy на ссылки PHYS9_COLORS.*. Co-Authored-By: Claude Opus 4.7 --- frontend/js/phys9_palette.js | 160 ++++++++++++++++++++++++++ frontend/textbooks/physics_9_ch1.html | 1 + frontend/textbooks/physics_9_ch2.html | 1 + frontend/textbooks/physics_9_ch3.html | 1 + frontend/textbooks/physics_9_ch4.html | 1 + frontend/textbooks/physics_9_ch5.html | 1 + 6 files changed, 165 insertions(+) create mode 100644 frontend/js/phys9_palette.js diff --git a/frontend/js/phys9_palette.js b/frontend/js/phys9_palette.js new file mode 100644 index 0000000..ad8149e --- /dev/null +++ b/frontend/js/phys9_palette.js @@ -0,0 +1,160 @@ +// phys9_palette.js — единая палитра цветов для всех визуализаций Физики 9. +// Экспорт в window.PHYS9_COLORS. Используется в phys9_legacy.js для canvas/SVG. +// Цвета синхронизированы с phys.js и optics.js (Физика 8). +(function(){ +'use strict'; + +// === Базовые цвета (для светлой темы) === +const LIGHT = { + /* Кинематические величины */ + velocity: '#0891b2', /* cyan-600 — скорость v */ + acceleration: '#ea580c', /* orange-600 — ускорение a */ + displacement: '#2563eb', /* blue-600 — перемещение Δr */ + position: '#475569', /* slate-600 — положение */ + time: '#6b7280', /* gray-500 — ось времени */ + + /* Динамические величины */ + force: '#10b981', /* emerald-500 — сила F */ + forceGravity: '#2563eb', /* blue-600 — сила тяжести mg */ + forceFriction:'#7c3aed', /* violet-600 — трение */ + forceNormal: '#94a3b8', /* slate-400 — реакция опоры N */ + forceSpring: '#d97706', /* amber-600 — упругая сила */ + forceTension: '#16a34a', /* green-600 — натяжение нити */ + + /* Энергетика */ + energyK: '#dc2626', /* red-600 — кинетическая Ek */ + energyP: '#2563eb', /* blue-600 — потенциальная Ep */ + work: '#9333ea', /* purple-600 — работа A */ + power: '#db2777', /* pink-600 — мощность N */ + + /* Тела */ + body: '#475569', /* slate-600 — основной цвет тела */ + bodyAccent: '#1e293b', /* slate-800 — обводка/штрих */ + bodyLight: '#cbd5e1', /* slate-300 — заливка для светлых тел */ + surface: '#a16207', /* yellow-700 — поверхность/опора */ + liquid: '#3b82f6', /* blue-500 — жидкость */ + liquidLight: '#bfdbfe', /* blue-200 — поверхность жидкости */ + gas: '#dbeafe', /* blue-100 — газ/воздух */ + + /* Углы и геометрия */ + angle: '#dc2626', /* red-600 — углы α, β, φ */ + axis: '#1e293b', /* slate-800 — координатные оси */ + grid: '#e5e7eb', /* gray-200 — сетка */ + dashed: '#94a3b8', /* slate-400 — пунктир/перпендикуляр */ + + /* Графики */ + plotPrimary: '#dc2626', /* основной график */ + plotSecondary:'#2563eb', /* второй график для сравнения */ + plotTertiary: '#10b981', /* третий график */ + + /* Текст и подписи на канвасе */ + text: '#0f172a', /* slate-900 — главный текст */ + textMuted: '#64748b', /* slate-500 — приглушённый текст */ + textLabel: '#1e293b', /* slate-800 — подписи переменных */ + + /* Фоны */ + bg: '#fafafa', /* фон сцены */ + bgSubtle: '#f8fafc', /* мягкий фон */ + bgCard: '#ffffff', /* карточка */ + + /* Состояния */ + ok: '#16a34a', /* зелёный — успех */ + warn: '#f59e0b', /* янтарный — внимание */ + fail: '#dc2626' /* красный — ошибка */ +}; + +// === Цвета для тёмной темы === +const DARK = { + velocity: '#22d3ee', + acceleration: '#fb923c', + displacement: '#60a5fa', + position: '#94a3b8', + time: '#9ca3af', + force: '#34d399', + forceGravity: '#60a5fa', + forceFriction:'#a78bfa', + forceNormal: '#cbd5e1', + forceSpring: '#fbbf24', + forceTension: '#4ade80', + energyK: '#f87171', + energyP: '#60a5fa', + work: '#c084fc', + power: '#f472b6', + body: '#94a3b8', + bodyAccent: '#e2e8f0', + bodyLight: '#64748b', + surface: '#ca8a04', + liquid: '#60a5fa', + liquidLight: '#3b82f6', + gas: '#1e3a8a', + angle: '#f87171', + axis: '#e2e8f0', + grid: '#374151', + dashed: '#94a3b8', + plotPrimary: '#f87171', + plotSecondary:'#60a5fa', + plotTertiary: '#34d399', + text: '#f1f5f9', + textMuted: '#94a3b8', + textLabel: '#e2e8f0', + bg: '#0f172a', + bgSubtle: '#1e293b', + bgCard: '#1f2937', + ok: '#4ade80', + warn: '#fbbf24', + fail: '#f87171' +}; + +// === Активная палитра — возвращает значения текущей темы === +function isDark(){ + try { + return document.documentElement.classList.contains('dark') || + document.body.classList.contains('dark'); + } catch(e){ return false; } +} + +// Объект, который пересчитывает значения через геттеры +const PHYS9_COLORS = {}; +for (const key of Object.keys(LIGHT)) { + Object.defineProperty(PHYS9_COLORS, key, { + enumerable: true, + configurable: false, + get(){ return isDark() ? (DARK[key] || LIGHT[key]) : LIGHT[key]; } + }); +} + +// === Утилиты === + +// Получить цвет вектора по типу величины (для drawArrow и т.п.) +PHYS9_COLORS.vector = function(kind){ + switch(kind){ + case 'v': case 'velocity': return PHYS9_COLORS.velocity; + case 'a': case 'acceleration': return PHYS9_COLORS.acceleration; + case 'F': case 'force': return PHYS9_COLORS.force; + case 'mg': case 'gravity': return PHYS9_COLORS.forceGravity; + case 'N': case 'normal': return PHYS9_COLORS.forceNormal; + case 'Ftr': case 'friction': return PHYS9_COLORS.forceFriction; + case 'Fspr': case 'spring': return PHYS9_COLORS.forceSpring; + case 'T': case 'tension': return PHYS9_COLORS.forceTension; + default: return PHYS9_COLORS.text; + } +}; + +// Получить цвет по классу величины (kinematic / dynamic / energy / geometry) +PHYS9_COLORS.byClass = function(cls){ + switch(cls){ + case 'kinematic': return PHYS9_COLORS.velocity; + case 'dynamic': return PHYS9_COLORS.force; + case 'energy': return PHYS9_COLORS.energyK; + case 'geometry': return PHYS9_COLORS.angle; + default: return PHYS9_COLORS.text; + } +}; + +// Полная схема для тёмной/светлой — для отладки +PHYS9_COLORS._LIGHT = LIGHT; +PHYS9_COLORS._DARK = DARK; + +window.PHYS9_COLORS = PHYS9_COLORS; + +})(); diff --git a/frontend/textbooks/physics_9_ch1.html b/frontend/textbooks/physics_9_ch1.html index 473384b..dfb591b 100644 --- a/frontend/textbooks/physics_9_ch1.html +++ b/frontend/textbooks/physics_9_ch1.html @@ -15,6 +15,7 @@ +