239e54540e
Новый модуль 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>
161 lines
6.4 KiB
JavaScript
161 lines
6.4 KiB
JavaScript
// 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;
|
||
|
||
})();
|