Files
Maxim Dolgolyov 239e54540e feat(phys9): единая палитра цветов PHYS9_COLORS (Phase 2)
Новый модуль 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 <noreply@anthropic.com>
2026-05-30 09:30:37 +03:00

161 lines
6.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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;
})();