dfe26a4771
Tracker проверяет 'LS.getToken()' перед каждым POST'ом. Без api.js объект LS undefined, и tracker возвращает из syncToServer ничего не делая. Поэтому в physics8_thermal/electro/optics прогресс не писался вообще (ни last_para, ни mark_read). Добавил <script src="/js/api.js" defer> перед xp.js во все 3 файла. Chemistry-9 и physics-9 не затронуты — у них api.js уже подключён в конце body перед tracker'ом.
3763 lines
252 KiB
HTML
3763 lines
252 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru" id="root">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Физика 8 — Световые явления</title>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css">
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.js"></script>
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/contrib/auto-render.min.js"></script>
|
||
<script src="/js/api.js" defer></script>
|
||
<script src="/js/xp.js" defer></script>
|
||
<script src="/js/textbook-tracker.js" defer></script>
|
||
<script src="/js/textbook-xp-widget.js" defer></script>
|
||
<style>
|
||
/* ═══════════ ДИЗАЙН-ТОКЕНЫ v2 ═══════════ */
|
||
:root{
|
||
/* Палитра — 9 ступеней */
|
||
--pri-50:#faf5ff; --pri-100:#f3e8ff; --pri-200:#e9d5ff; --pri-300:#d8b4fe;
|
||
--pri-400:#c084fc; --pri-500:#a855f7; --pri-600:#9333ea; --pri-700:#7c3aed;
|
||
--pri-800:#6b21a8; --pri-900:#581c87;
|
||
--acc-300:#f9a8d4; --acc-400:#f472b6; --acc-500:#ec4899; --acc-600:#db2777; --acc-700:#be185d;
|
||
--pri:var(--pri-600); --acc:var(--acc-500);
|
||
|
||
/* Статусы */
|
||
--ok:#16a34a; --ok-bg:#dcfce7; --ok-border:#86efac;
|
||
--fail:#dc2626; --fail-bg:#fee2e2; --fail-border:#fca5a5;
|
||
--warn:#d97706; --warn-bg:#fef3c7;
|
||
|
||
/* Поверхности */
|
||
--bg:#faf5ff; --card:#fff;
|
||
--surface-1:#ffffff; --surface-2:#faf5ff; --surface-3:#f3e8ff;
|
||
--text:#1a1a2e; --muted:#64748b; --border:#e9d5ff;
|
||
--glass-bg:rgba(255,255,255,.65); --glass-border:rgba(255,255,255,.4);
|
||
|
||
/* Тени и свечение */
|
||
--sh:0 2px 10px rgba(147,51,234,.08);
|
||
--shadow-sm:0 1px 2px rgba(15,23,42,.06);
|
||
--shadow-md:0 4px 14px rgba(15,23,42,.08);
|
||
--shadow-lg:0 12px 32px rgba(15,23,42,.10);
|
||
--shadow-glow:0 0 24px rgba(147,51,234,.25);
|
||
--shadow-pop:0 8px 22px rgba(147,51,234,.16);
|
||
|
||
/* Радиусы */
|
||
--r-sm:8px; --r-md:12px; --r-lg:16px; --r-xl:22px; --r-full:999px;
|
||
|
||
/* Анимации */
|
||
--ease:cubic-bezier(.4,0,.2,1);
|
||
--ease-out:cubic-bezier(.16,1,.3,1);
|
||
--ease-bounce:cubic-bezier(.34,1.56,.64,1);
|
||
--dur-1:.16s; --dur-2:.22s; --dur-3:.36s; --dur-4:.56s;
|
||
}
|
||
html.dark{
|
||
--bg:#0f0a1f; --card:#1a0f2e;
|
||
--surface-1:#1a0f2e; --surface-2:#241640; --surface-3:#2e1d52;
|
||
--text:#f0e6ff; --muted:#a8a29e; --border:#4c1d95;
|
||
--glass-bg:rgba(26,15,46,.6); --glass-border:rgba(255,255,255,.08);
|
||
--ok:#22c55e; --ok-bg:rgba(34,197,94,.12); --ok-border:rgba(34,197,94,.3);
|
||
--fail:#f87171; --fail-bg:rgba(248,113,113,.12); --fail-border:rgba(248,113,113,.3);
|
||
--shadow-sm:0 1px 2px rgba(0,0,0,.4);
|
||
--shadow-md:0 4px 14px rgba(0,0,0,.5);
|
||
--shadow-lg:0 12px 32px rgba(0,0,0,.6);
|
||
--shadow-glow:0 0 28px rgba(192,132,252,.35);
|
||
--shadow-pop:0 8px 22px rgba(147,51,234,.4);
|
||
}
|
||
@media (prefers-reduced-motion: reduce){
|
||
*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
|
||
}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
body{font-family:'Outfit',system-ui,sans-serif;background:var(--bg);color:var(--text);overflow-x:hidden}
|
||
::-webkit-scrollbar{width:5px;height:5px}
|
||
::-webkit-scrollbar-thumb{background:var(--border);border-radius:99px}
|
||
|
||
/* ═══════════ FLOATING BUTTONS ═══════════ */
|
||
.theme-btn{position:fixed;top:12px;right:12px;z-index:80;width:38px;height:38px;
|
||
border-radius:10px;background:rgba(147,51,234,.18);border:1px solid rgba(147,51,234,.3);
|
||
cursor:pointer;display:grid;place-items:center;font-size:1rem;
|
||
color:rgba(240,236,255,.8);box-shadow:0 2px 10px rgba(147,51,234,.2);transition:.18s}
|
||
.theme-btn:hover{background:rgba(147,51,234,.28);color:#d4a843;transform:scale(1.06)}
|
||
html.dark .theme-btn{background:rgba(147,51,234,.25);border-color:rgba(147,51,234,.4);color:#c084fc}
|
||
|
||
.ref-toggle{position:fixed;bottom:16px;right:16px;z-index:80;width:46px;height:46px;
|
||
border-radius:13px;background:var(--pri);color:#fff;border:none;cursor:pointer;
|
||
display:grid;place-items:center;font-size:1.1rem;
|
||
box-shadow:0 4px 16px rgba(147,51,234,.4);transition:transform .18s,box-shadow .18s}
|
||
.ref-toggle:hover{transform:scale(1.06) rotate(-4deg);box-shadow:0 8px 24px rgba(147,51,234,.55)}
|
||
|
||
/* ═══════════ POPUP СПРАВОЧНИК ═══════════ */
|
||
.ref-panel{position:fixed;bottom:72px;right:16px;z-index:75;width:300px;max-height:72vh;
|
||
overflow-y:auto;background:var(--card);border:1px solid var(--border);
|
||
border-radius:16px;padding:16px 18px;box-shadow:0 8px 32px rgba(0,0,0,.18);
|
||
display:none;font-size:.8rem;line-height:1.85;scrollbar-width:thin;
|
||
scrollbar-color:var(--border) transparent}
|
||
.ref-panel.show{display:block;animation:fadeUp .2s ease}
|
||
.ref-panel h3{font-size:.78rem;font-weight:800;color:var(--pri);margin:12px 0 5px;
|
||
text-transform:uppercase;letter-spacing:.08em}
|
||
.ref-panel h3:first-child{margin-top:0}
|
||
.ref-panel .rf{background:rgba(147,51,234,.06);border-radius:8px;padding:7px 12px;margin:3px 0;text-align:center;border:1px solid rgba(147,51,234,.1)}
|
||
html.dark .ref-panel .rf{background:rgba(147,51,234,.12)}
|
||
|
||
/* ═══════════ HDR ═══════════ */
|
||
.hdr{background:linear-gradient(135deg,#581c87 0%,#7c3aed 55%,#a855f7 100%);
|
||
color:#fff;padding:24px 20px 20px;text-align:center;position:relative;overflow:hidden}
|
||
.hdr::before{content:'';position:absolute;inset:0;opacity:.5;pointer-events:none;
|
||
background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='80' viewBox='0 0 140 80'><g fill='none' stroke='%23ffffff' stroke-width='1.2' opacity='0.18'><path d='M0 20 Q35 0 70 20 T140 20'/><path d='M0 40 Q35 20 70 40 T140 40'/><path d='M0 60 Q35 40 70 60 T140 60'/></g></svg>")}
|
||
.hdr h1{font-size:1.5rem;font-weight:900;position:relative}
|
||
.hdr p{font-size:.82rem;opacity:.82;margin-top:5px;position:relative}
|
||
@media(max-width:600px){.hdr h1{font-size:1.2rem}.hdr p{font-size:.74rem}}
|
||
|
||
/* ═══════════ LAYOUT ═══════════ */
|
||
.page-wrap{display:flex;min-height:calc(100vh - 90px)}
|
||
.sidebar{width:220px;flex-shrink:0;
|
||
background:linear-gradient(180deg,#2e1065 0%,#1e0a40 100%);
|
||
border-right:1px solid rgba(147,51,234,.2);
|
||
overflow-y:auto;overflow-x:hidden;
|
||
scrollbar-width:thin;scrollbar-color:rgba(147,51,234,.2) transparent}
|
||
.sidebar::-webkit-scrollbar{width:3px}
|
||
.sidebar::-webkit-scrollbar-thumb{background:rgba(147,51,234,.25);border-radius:99px}
|
||
html.dark .sidebar{background:linear-gradient(180deg,#1a0831 0%,#0f0520 100%);border-right-color:rgba(147,51,234,.15)}
|
||
|
||
.sb-brand{display:flex;align-items:center;gap:10px;padding:18px 14px 14px;
|
||
border-bottom:1px solid rgba(147,51,234,.2)}
|
||
.sb-logo{font-size:1.4rem;flex-shrink:0}
|
||
.sb-title{font-size:.9rem;font-weight:800;color:#f3e8ff;letter-spacing:-.02em;line-height:1.1}
|
||
.sb-sub{font-size:.55rem;color:rgba(200,160,255,.45);margin-top:2px;letter-spacing:.03em}
|
||
|
||
.sb-nav{padding:10px 8px 20px}
|
||
.sb-item{display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:8px;
|
||
cursor:pointer;border:none;background:transparent;width:100%;text-align:left;
|
||
color:rgba(200,170,255,.68);font-size:.71rem;font-weight:700;font-family:inherit;
|
||
border-left:2.5px solid transparent;transition:.15s}
|
||
.sb-item:hover{background:rgba(147,51,234,.12);color:rgba(230,200,255,.9);border-left-color:rgba(168,85,247,.4)}
|
||
.sb-item.active{background:rgba(147,51,234,.22);color:#e9d5ff;border-left-color:#a855f7;box-shadow:inset 0 0 0 1px rgba(168,85,247,.12)}
|
||
.sb-item .sb-icon{font-size:.95rem;width:20px;text-align:center;flex-shrink:0;opacity:.65}
|
||
.sb-item.active .sb-icon{opacity:1}
|
||
.sb-item .sb-num{font-family:monospace;font-size:.65rem;color:rgba(168,85,247,.55);flex-shrink:0;min-width:26px}
|
||
.sb-item.active .sb-num{color:#c084fc}
|
||
.sb-item .sb-name{flex:1;line-height:1.3;white-space:normal;font-size:.7rem}
|
||
.sb-divider{height:1px;background:rgba(147,51,234,.18);margin:6px 8px}
|
||
|
||
.main-col{flex:1;min-width:0;overflow-x:hidden}
|
||
|
||
/* ═══════════ КОНТЕНТ ═══════════ */
|
||
.content-area{max-width:820px;margin:0 auto;padding:0 4px 40px}
|
||
.content{display:none;padding:20px 14px;animation:fadeUp .25s ease}
|
||
.content.active{display:block}
|
||
@keyframes fadeUp{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
|
||
|
||
/* ═══════════ АДАПТИВНОСТЬ ═══════════ */
|
||
@media(max-width:768px){
|
||
.page-wrap{flex-direction:column}
|
||
.sidebar{width:100%;border-right:none;border-bottom:1px solid rgba(147,51,234,.2)}
|
||
.sb-nav{display:flex;flex-wrap:nowrap;overflow-x:auto;padding:6px 8px;gap:2px;scrollbar-width:none}
|
||
.sb-nav::-webkit-scrollbar{display:none}
|
||
.sb-item{white-space:nowrap;flex-shrink:0;border-left:none;border-bottom:2.5px solid transparent;border-radius:0;padding:7px 10px;flex-direction:column;gap:3px;align-items:center;text-align:center;min-width:48px}
|
||
.sb-item:hover{border-left-color:transparent;border-bottom-color:rgba(168,85,247,.4)}
|
||
.sb-item.active{border-left-color:transparent!important;border-bottom-color:#a855f7;box-shadow:none}
|
||
.sb-item .sb-name{display:none}
|
||
.sb-item .sb-num{min-width:auto}
|
||
.sb-brand{padding:10px 14px 8px}
|
||
.sb-divider{display:none}
|
||
}
|
||
|
||
/* ═══════════ PARA-HERO ═══════════ */
|
||
.para-hero{border-radius:18px;padding:22px 24px;margin-bottom:22px;color:#fff;position:relative;overflow:hidden}
|
||
.para-hero::after{content:'';position:absolute;right:-30px;top:-30px;width:160px;height:160px;
|
||
border-radius:50%;background:rgba(255,255,255,.1);pointer-events:none}
|
||
.ph-num{font-size:.72rem;font-weight:700;opacity:.75;letter-spacing:.1em;text-transform:uppercase;margin-bottom:5px}
|
||
.ph-title{font-size:1.15rem;font-weight:900;line-height:1.3}
|
||
.ph-32{background:linear-gradient(135deg,#1a1a2e,#7c3aed,#a855f7)}
|
||
.ph-32::after{background:#e9d5ff}
|
||
.ph-33{background:linear-gradient(135deg,#0f172a,#0ea5e9,#7c3aed)}
|
||
.ph-33::after{background:#bae6fd}
|
||
.ph-34{background:linear-gradient(135deg,#1e1b4b,#4338ca,#818cf8)}
|
||
.ph-34::after{background:#c7d2fe}
|
||
.ph-35{background:linear-gradient(135deg,#312e81,#6366f1,#a5b4fc)}
|
||
.ph-35::after{background:#e0e7ff}
|
||
.ph-36{background:linear-gradient(135deg,#0c4a6e,#0891b2,#7c3aed)}
|
||
.ph-36::after{background:#cffafe}
|
||
.ph-37{background:linear-gradient(135deg,#4c1d95,#7c3aed,#f59e0b);color:#fff}
|
||
.ph-37::after{background:#fde68a}
|
||
.ph-38{background:linear-gradient(135deg,#7c3aed,#a855f7,#f59e0b)}
|
||
.ph-38::after{background:#fde68a}
|
||
.ph-39{background:linear-gradient(135deg,#064e3b,#059669,#7c3aed)}
|
||
.ph-39::after{background:#a7f3d0}
|
||
.ph-40{background:linear-gradient(135deg,#7c3aed,#6d28d9,#1e1b4b)}
|
||
.ph-40::after{background:#ede9fe}
|
||
/* para-badge colours */
|
||
.para-badge.b32{background:rgba(124,58,237,.13);color:#7c3aed}
|
||
.para-badge.b33{background:rgba(14,165,233,.13);color:#0369a1}
|
||
.para-badge.b34{background:rgba(67,56,202,.13);color:#4338ca}
|
||
.para-badge.b35{background:rgba(99,102,241,.13);color:#6366f1}
|
||
.para-badge.b36{background:rgba(8,145,178,.13);color:#0891b2}
|
||
.para-badge.b37{background:rgba(124,58,237,.13);color:#7c3aed}
|
||
.para-badge.b38{background:rgba(168,85,247,.13);color:#a855f7}
|
||
.para-badge.b39{background:rgba(5,150,105,.13);color:#059669}
|
||
.para-badge.b40{background:rgba(109,40,217,.13);color:#6d28d9}
|
||
|
||
/* ═══════════ ТЕОРИЯ ═══════════ */
|
||
.section-title{font-size:.7rem;font-weight:800;text-transform:uppercase;letter-spacing:.14em;
|
||
color:var(--pri);display:flex;align-items:center;gap:8px;margin-bottom:16px}
|
||
.section-title::before{content:'';display:block;width:16px;height:2px;background:var(--pri);border-radius:1px}
|
||
.def-box{background:rgba(124,58,237,.05);border-left:4px solid var(--pri);border-radius:10px;
|
||
padding:12px 16px;margin-bottom:16px;font-size:.88rem;line-height:1.8}
|
||
html.dark .def-box{background:rgba(124,58,237,.09)}
|
||
.formula-box{background:var(--card);border:2px solid var(--border);border-radius:14px;
|
||
padding:16px 20px;margin-bottom:16px;box-shadow:var(--sh)}
|
||
.formula-box .main-f{font-size:1.05rem;font-weight:700;text-align:center;padding:10px;
|
||
background:rgba(124,58,237,.06);border-radius:8px;margin:8px 0}
|
||
html.dark .formula-box .main-f{background:rgba(124,58,237,.12)}
|
||
.info-row{display:flex;gap:10px;align-items:flex-start;padding:10px 14px;
|
||
background:var(--card);border:1px solid var(--border);border-radius:10px;margin-bottom:10px;font-size:.85rem;line-height:1.7}
|
||
.ovr-card{background:var(--card);border:1px solid var(--border);border-radius:14px;
|
||
padding:16px 18px;margin-bottom:14px;box-shadow:var(--sh)}
|
||
|
||
/* ═══════════ CANVAS ═══════════ */
|
||
canvas{width:100%;border-radius:10px;background:var(--card);display:block}
|
||
.ctrl-row{display:flex;align-items:center;gap:10px;margin:8px 0;flex-wrap:wrap;font-size:.83rem}
|
||
.slider-row{display:flex;align-items:center;gap:10px;margin:8px 0;font-size:.82rem;flex-wrap:wrap}
|
||
.slider-lbl{min-width:100px;font-weight:600;color:var(--text);flex-shrink:0}
|
||
.slider-val{min-width:72px;font-weight:800;color:var(--pri);font-family:monospace;font-size:.82rem}
|
||
input[type=range]{flex:1;min-width:100px;accent-color:var(--pri);cursor:pointer}
|
||
|
||
/* ═══════════ ЗАДАЧИ: ПИЛЮЛИ ═══════════ */
|
||
.para-pills{display:flex;flex-wrap:wrap;gap:6px;padding:14px;background:var(--card);
|
||
border-bottom:1px solid var(--border);border-radius:14px 14px 0 0;margin-bottom:0}
|
||
.para-pill{padding:6px 13px;border:2px solid var(--border);border-radius:9px;font-size:.72rem;
|
||
font-weight:700;cursor:pointer;white-space:nowrap;background:var(--card);color:var(--muted);transition:.16s}
|
||
.para-pill:hover{border-color:var(--pri);color:var(--pri)}
|
||
.para-pill.active{background:var(--pri);color:#fff;border-color:var(--pri)}
|
||
|
||
/* ═══════════ ЗАДАЧИ: ДВИЖОК ═══════════ */
|
||
.score-bar{display:flex;gap:10px;align-items:center;margin-bottom:12px;font-size:.85rem;font-weight:600;flex-wrap:wrap}
|
||
.chip{padding:5px 13px;border-radius:50px;display:inline-flex;align-items:center;gap:5px}
|
||
.chip-ok{background:var(--ok-bg);color:#166534}
|
||
html.dark .chip-ok{color:#86efac}
|
||
.chip-tot{background:var(--card);color:var(--muted);border:1px solid var(--border)}
|
||
.prog-wrap{width:100%;height:6px;background:var(--border);border-radius:3px;overflow:hidden;margin-bottom:14px}
|
||
.prog-fill{height:100%;background:linear-gradient(90deg,var(--pri),var(--acc));border-radius:3px;transition:width .4s}
|
||
.nav-dots{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:14px}
|
||
.nav-dot{min-width:30px;height:30px;padding:0 6px;border-radius:7px;border:2px solid var(--border);
|
||
background:var(--card);font-size:.72rem;font-weight:700;cursor:pointer;display:grid;place-items:center;
|
||
transition:.15s;color:var(--muted);font-family:monospace}
|
||
.nav-dot:hover{border-color:var(--pri);color:var(--pri)}
|
||
.nav-dot.nd-cur{background:var(--pri);border-color:var(--pri);color:#fff}
|
||
.nav-dot.nd-ok{background:var(--ok-bg);border-color:var(--ok);color:#166534}
|
||
.nav-dot.nd-fail{background:var(--fail-bg);border-color:var(--fail);color:#991b1b}
|
||
.task-card{background:var(--card);border:1px solid var(--border);border-radius:14px;
|
||
padding:20px 22px;box-shadow:var(--sh);margin-bottom:12px}
|
||
.task-num{font-size:.72rem;font-weight:700;color:var(--acc);text-transform:uppercase;
|
||
letter-spacing:.06em;margin-bottom:6px}
|
||
.task-text{font-size:.96rem;font-weight:700;line-height:1.85;margin-bottom:14px}
|
||
.task-hint{font-size:.8rem;color:var(--muted);margin-bottom:12px;display:flex;align-items:flex-start;gap:6px}
|
||
.task-hint i{margin-top:2px;color:var(--warn);flex-shrink:0}
|
||
.ans-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}
|
||
.ans-inp{width:120px;padding:11px 10px;border:2px solid var(--border);border-radius:10px;
|
||
font-size:1.05rem;font-family:monospace;text-align:center;outline:none;
|
||
background:var(--card);color:var(--text);transition:.18s}
|
||
.ans-inp:focus{border-color:var(--pri);box-shadow:0 0 0 3px rgba(124,58,237,.12)}
|
||
.unit-lbl{font-size:.82rem;color:var(--muted);font-weight:600;white-space:nowrap}
|
||
.btn{padding:10px 18px;border:none;border-radius:10px;font-weight:700;font-size:.84rem;
|
||
cursor:pointer;transition:.18s;display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
|
||
.btn:active{transform:scale(.96)}
|
||
.btn-pri{background:var(--pri);color:#fff}
|
||
.btn-pri:hover{filter:brightness(1.1)}
|
||
.btn-ghost{background:transparent;border:2px solid var(--border);color:var(--muted)}
|
||
.btn-ghost:hover{border-color:var(--pri);color:var(--pri)}
|
||
.btn-next{background:var(--ok);color:#fff}
|
||
.btn-next:hover{filter:brightness(1.1)}
|
||
.mcq-opts{display:flex;flex-direction:column;gap:8px;margin-top:4px}
|
||
.opt-btn{width:100%;text-align:left;padding:11px 16px;border:2px solid var(--border);border-radius:10px;
|
||
background:var(--card);color:var(--text);font-size:.9rem;font-weight:500;cursor:pointer;
|
||
transition:.18s;line-height:1.5;font-family:inherit}
|
||
.opt-btn:hover:not(:disabled){border-color:var(--pri);background:rgba(124,58,237,.05)}
|
||
.opt-btn:disabled{cursor:default}
|
||
.opt-btn.mcq-cor{border-color:var(--ok)!important;background:var(--ok-bg)!important;color:#166534!important;font-weight:700}
|
||
.opt-btn.mcq-wrong{border-color:var(--fail)!important;background:var(--fail-bg)!important;color:#991b1b!important}
|
||
.feedback{padding:13px 18px;border-radius:11px;font-size:.87rem;font-weight:600;
|
||
display:none;line-height:1.7;margin-top:10px}
|
||
.feedback.show{display:block;animation:pop .25s ease}
|
||
.fb-ok{background:var(--ok-bg);color:#166534}
|
||
html.dark .fb-ok{color:#86efac}
|
||
.fb-fail{background:var(--fail-bg);color:#991b1b}
|
||
html.dark .fb-fail{color:#fca5a5}
|
||
@keyframes pop{from{opacity:0;transform:scale(.94)}to{opacity:1;transform:scale(1)}}
|
||
.summary{background:var(--card);border:1px solid var(--border);border-radius:16px;
|
||
padding:28px;text-align:center;box-shadow:var(--sh);display:none}
|
||
.summary.show{display:block;animation:pop .35s ease}
|
||
.summary h2{font-size:1.2rem;font-weight:800;margin-bottom:8px}
|
||
.big-score{font-size:3.5rem;font-weight:900;color:var(--pri);line-height:1;margin:10px 0}
|
||
.sum-grade{color:var(--muted);font-size:.9rem;margin-bottom:20px}
|
||
.sum-btns{display:flex;gap:10px;justify-content:center;flex-wrap:wrap}
|
||
|
||
/* ═══════════ СПРАВОЧНИК (legacy overrides removed — see floating buttons CSS above) ═══════════ */
|
||
/* #refToggle и #refPanel теперь управляются через .ref-toggle и .ref-panel */
|
||
.ref-body{padding:2px 0;font-size:.8rem;line-height:1.85}
|
||
.ref-body h3{font-size:.78rem;font-weight:800;color:var(--pri);margin:12px 0 5px;
|
||
text-transform:uppercase;letter-spacing:.08em}
|
||
.ref-body h3:first-child{margin-top:0}
|
||
.ref-body p{margin-bottom:6px;font-size:.78rem;color:var(--muted)}
|
||
.ref-tbl{width:100%;border-collapse:collapse;font-size:.78rem;margin:4px 0 10px}
|
||
.ref-tbl td{padding:4px 8px;border:1px solid var(--border)}
|
||
.ref-tbl tr:nth-child(odd) td{background:rgba(124,58,237,.04)}
|
||
|
||
/* ═══════════ PTAB ═══════════ */
|
||
[id^="ptab-"]{display:none;padding:14px}
|
||
|
||
/* ── Карточки формул ── */
|
||
.formula-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:20px}
|
||
@media(max-width:560px){.formula-grid{grid-template-columns:1fr}}
|
||
.fcard{background:var(--card);border:2px solid var(--border);border-radius:14px;padding:16px 18px;box-shadow:var(--sh);transition:transform .18s,box-shadow .18s}
|
||
.fcard:hover{transform:translateY(-2px);box-shadow:0 6px 22px rgba(124,58,237,.1)}
|
||
.fcard.highlight{border-color:var(--pri);background:linear-gradient(135deg,rgba(124,58,237,.04),rgba(249,115,22,.04))}
|
||
.fcard h3{font-size:.8rem;font-weight:700;color:var(--pri);text-transform:uppercase;letter-spacing:.06em;margin-bottom:8px}
|
||
.fcard .main-f{font-size:1.05rem;font-weight:700;text-align:center;margin:8px 0;padding:10px;background:rgba(124,58,237,.06);border-radius:9px}
|
||
.fcard p{font-size:.83rem;color:var(--muted);line-height:1.7;margin-top:6px}
|
||
.fcard ul{font-size:.83rem;color:var(--muted);line-height:1.8;padding-left:18px;margin-top:6px}
|
||
|
||
/* ── Интерактивные диаграммы ── */
|
||
.idiag{background:var(--card);border:2px solid var(--border);border-radius:14px;padding:16px 18px;margin:14px 0;box-shadow:var(--sh)}
|
||
.idiag h3{font-size:.79rem;font-weight:700;color:var(--pri);text-transform:uppercase;letter-spacing:.05em;margin-bottom:12px;display:flex;align-items:center;gap:6px}
|
||
.idiag-2col{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:14px 0}
|
||
@media(max-width:560px){.idiag-2col{grid-template-columns:1fr}}
|
||
.idiag-result{background:rgba(124,58,237,.08);border-radius:10px;padding:10px 14px;margin-top:10px;font-size:.9rem;font-weight:700;text-align:center;letter-spacing:.02em;border:1px solid rgba(124,58,237,.15)}
|
||
.slider-lbl{min-width:90px;font-weight:600;color:var(--text);flex-shrink:0;font-size:.82rem}
|
||
.slider-val{min-width:72px;font-weight:800;color:var(--pri);font-size:.82rem;flex-shrink:0}
|
||
|
||
/* ── Запомни! ── */
|
||
.remember-box{background:linear-gradient(135deg,rgba(124,58,237,.06),rgba(124,58,237,.03));border:2px solid rgba(124,58,237,.3);border-radius:13px;padding:14px 17px;margin:16px 0}
|
||
.remember-box-title{font-weight:800;font-size:.82rem;color:#b91c1c;margin-bottom:8px;display:flex;align-items:center;gap:7px}
|
||
html.dark .remember-box{border-color:rgba(124,58,237,.4);background:rgba(124,58,237,.07)}
|
||
html.dark .remember-box-title{color:#fca5a5}
|
||
.remember-box ul,.remember-box p{font-size:.83rem;color:var(--text);line-height:1.9;margin:0}
|
||
.remember-box ul{padding-left:18px}
|
||
.remember-box li{margin-bottom:3px}
|
||
|
||
/* ── Частые ошибки ── */
|
||
.mistakes-box{background:linear-gradient(135deg,rgba(245,158,11,.06),rgba(251,191,36,.03));border:2px solid rgba(245,158,11,.35);border-radius:13px;padding:14px 17px;margin:16px 0}
|
||
.mistakes-box-title{font-weight:800;font-size:.82rem;color:#92400e;margin-bottom:8px;display:flex;align-items:center;gap:7px}
|
||
html.dark .mistakes-box-title{color:#fcd34d}
|
||
.mistakes-box ul{padding-left:18px;margin:0}
|
||
.mistakes-box li{font-size:.83rem;color:var(--text);line-height:1.9}
|
||
|
||
/* ── Объяснение по-человечески ── */
|
||
.student-box{background:linear-gradient(135deg,rgba(254,243,199,.7),rgba(255,237,213,.7));border:1.5px solid #f59e0b;border-radius:14px;padding:16px 18px;margin:16px 0;line-height:1.75}
|
||
html.dark .student-box{background:linear-gradient(135deg,rgba(120,80,0,.18),rgba(100,50,0,.18));border-color:#d97706}
|
||
.student-box-title{font-weight:800;font-size:.88rem;color:#92400e;margin-bottom:10px;display:flex;align-items:center;gap:7px}
|
||
html.dark .student-box-title{color:#fbbf24}
|
||
.student-box p{margin:0 0 9px;font-size:.84rem;color:var(--text)}
|
||
.student-box p:last-child{margin-bottom:0}
|
||
.student-box b{color:#92400e}
|
||
html.dark .student-box b{color:#fbbf24}
|
||
|
||
/* ── Инсайт ── */
|
||
.insight-box{background:linear-gradient(135deg,rgba(124,58,237,.07),rgba(249,115,22,.04));border:2px solid rgba(124,58,237,.22);border-radius:13px;padding:14px 17px;margin:16px 0}
|
||
.insight-title{font-weight:800;font-size:.82rem;color:var(--pri);margin-bottom:7px;display:flex;align-items:center;gap:7px}
|
||
.insight-box p{font-size:.83rem;color:var(--text);line-height:1.8;margin:0 0 6px}
|
||
|
||
/* ── Примеры из жизни ── */
|
||
.life-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:10px;margin:14px 0}
|
||
.life-item{background:var(--card);border:1.5px solid var(--border);border-radius:12px;padding:12px 10px;text-align:center}
|
||
.life-item .li-icon{font-size:1.9rem;margin-bottom:5px}
|
||
.life-item .li-title{font-size:.79rem;font-weight:700;color:var(--text);margin-bottom:3px}
|
||
.life-item .li-desc{font-size:.71rem;color:var(--muted);line-height:1.55}
|
||
|
||
/* ── Иконки в сайдбаре ── */
|
||
.para-icon{margin-right:8px;display:inline-flex;align-items:center;vertical-align:-3px;flex-shrink:0}
|
||
|
||
/* ═══════════ REF-PANEL TABS ═══════════ */
|
||
.ref-tabs{display:flex;gap:0;border-bottom:2px solid var(--border);margin-bottom:16px}
|
||
.ref-tab-btn{flex:1;padding:10px 12px;border:none;background:transparent;cursor:pointer;font-size:.76rem;font-weight:700;color:var(--muted);transition:.18s;border-bottom:2px solid transparent;margin-bottom:-2px;font-family:inherit}
|
||
.ref-tab-btn:hover{color:var(--text)}
|
||
.ref-tab-btn.active{color:var(--pri);border-bottom-color:var(--pri)}
|
||
.ref-tab-content{display:none}
|
||
.ref-tab-content.active{display:block}
|
||
/* Formula table в ref-panel */
|
||
.ref-formula-table{width:100%;font-size:.73rem;margin:8px 0;border-collapse:collapse}
|
||
.ref-formula-table th,.ref-formula-table td{padding:7px 9px;border:1px solid var(--border);text-align:left;vertical-align:top}
|
||
.ref-formula-table th{background:rgba(147,51,234,.08);font-weight:700;color:var(--pri);position:sticky;top:0;z-index:1}
|
||
.ref-formula-table tr:nth-child(odd) td{background:rgba(147,51,234,.04)}
|
||
.ref-formula-table tr:nth-child(even) td{background:var(--card)}
|
||
html.dark .ref-formula-table th{background:rgba(147,51,234,.16)}
|
||
html.dark .ref-formula-table tr:nth-child(odd) td{background:rgba(147,51,234,.07)}
|
||
.ref-formula-table-wrap{max-height:65vh;overflow-y:auto}
|
||
|
||
/* ── Ключевые выводы ── */
|
||
.key-points{background:rgba(168,85,247,.08);border-left:4px solid #a855f7;border-radius:8px;padding:16px;margin:24px 0;box-shadow:var(--shadow-sm)}
|
||
.key-points-title{font-weight:800;font-size:.82rem;color:#a855f7;text-transform:uppercase;letter-spacing:.06em;margin-bottom:12px;display:flex;align-items:center;gap:7px}
|
||
.key-points-list{list-style:none;padding:0;margin:0}
|
||
.key-points-list li{font-size:.83rem;color:var(--text);line-height:1.8;margin-bottom:8px;padding-left:20px;position:relative}
|
||
.key-points-list li::before{content:'✓';position:absolute;left:0;color:#a855f7;font-weight:800}
|
||
html.dark .key-points{background:rgba(168,85,247,.12);border-left-color:#c084fc}
|
||
html.dark .key-points-title{color:#c084fc}
|
||
|
||
/* ── Para-hero доп. элементы ── */
|
||
.para-hero .ph-formula{display:inline-block;font-size:1rem;background:rgba(255,255,255,.17);border-radius:10px;padding:7px 16px;margin:2px 0 8px;font-weight:700;border:1px solid rgba(255,255,255,.22)}
|
||
.para-hero .ph-desc{font-size:.79rem;opacity:.87;line-height:1.65;margin-bottom:10px}
|
||
.para-hero .ph-tags{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}
|
||
.para-hero .ph-tag{background:rgba(255,255,255,.17);border:1px solid rgba(255,255,255,.25);border-radius:20px;padding:3px 11px;font-size:.7rem;font-weight:700}
|
||
.para-hero .ph-label{font-size:.7rem;font-weight:700;opacity:.75;letter-spacing:.1em;text-transform:uppercase;margin-bottom:5px}
|
||
.para-hero h2{font-size:1.12rem;font-weight:900;margin-bottom:8px;line-height:1.3}
|
||
|
||
/* ── Разделитель ── */
|
||
hr.divider{border:none;border-top:1px solid var(--border);margin:20px 0}
|
||
|
||
/* ── Шаги решения ── */
|
||
.sol-steps{list-style:none;padding:0;margin:8px 0}
|
||
.sol-steps li{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px;font-size:.86rem;line-height:1.75}
|
||
.step-n{min-width:24px;height:24px;border-radius:50%;background:var(--pri);color:#fff;font-size:.69rem;font-weight:800;display:grid;place-items:center;margin-top:1px;flex-shrink:0}
|
||
|
||
/* ═══════════════════════════════════════════════ */
|
||
/* ═══════════ PRO MAX UPGRADE ═════════════════ */
|
||
/* ═══════════════════════════════════════════════ */
|
||
|
||
/* ── Body тонкий фоновый градиент ── */
|
||
body{background:radial-gradient(1200px 600px at 80% -10%,rgba(236,72,153,.08),transparent 60%),radial-gradient(900px 500px at -10% 30%,rgba(147,51,234,.07),transparent 55%),var(--bg);min-height:100vh}
|
||
html.dark body{background:radial-gradient(1200px 600px at 80% -10%,rgba(147,51,234,.20),transparent 60%),radial-gradient(900px 500px at -10% 30%,rgba(236,72,153,.10),transparent 55%),var(--bg)}
|
||
|
||
/* ── A5. Motion: появление секций ── */
|
||
.fx-rise{opacity:0;transform:translateY(18px);transition:opacity var(--dur-3) var(--ease-out),transform var(--dur-3) var(--ease-out)}
|
||
.fx-rise.is-in{opacity:1;transform:none}
|
||
.fx-stagger>*{opacity:0;transform:translateY(12px);transition:opacity var(--dur-3) var(--ease-out),transform var(--dur-3) var(--ease-out)}
|
||
.fx-stagger.is-in>*{opacity:1;transform:none}
|
||
.fx-stagger.is-in>*:nth-child(1){transition-delay:0ms}
|
||
.fx-stagger.is-in>*:nth-child(2){transition-delay:60ms}
|
||
.fx-stagger.is-in>*:nth-child(3){transition-delay:120ms}
|
||
.fx-stagger.is-in>*:nth-child(4){transition-delay:180ms}
|
||
.fx-stagger.is-in>*:nth-child(5){transition-delay:240ms}
|
||
.fx-stagger.is-in>*:nth-child(6){transition-delay:300ms}
|
||
|
||
/* ── A4. Типографика fluid + gradient ── */
|
||
.section-title{font-size:clamp(.68rem,.62rem + .25vw,.78rem)}
|
||
.fcard h3{font-size:clamp(.78rem,.72rem + .3vw,.92rem)}
|
||
.task-text{font-size:clamp(.92rem,.86rem + .35vw,1.05rem)}
|
||
.para-hero h2{font-size:clamp(1.1rem,.95rem + .8vw,1.5rem);background:linear-gradient(135deg,#fff,rgba(255,255,255,.78));-webkit-background-clip:text;background-clip:text;color:transparent;text-shadow:0 2px 18px rgba(0,0,0,.18)}
|
||
|
||
/* KaTeX inline подсветка */
|
||
.katex{font-size:1.02em}
|
||
.katex-html{padding:0 .15em;border-radius:5px;transition:background var(--dur-1) var(--ease)}
|
||
.def-box .katex-html:hover,.task-text .katex-html:hover,.fcard .katex-html:hover{background:rgba(147,51,234,.08)}
|
||
|
||
/* ── A2. Para-hero v2: SVG-узор + параллакс + glow ── */
|
||
.para-hero{box-shadow:var(--shadow-lg),0 0 50px rgba(147,51,234,.18);position:relative;isolation:isolate;transform:translateZ(0);transition:transform var(--dur-2) var(--ease)}
|
||
.para-hero::before{content:'';position:absolute;inset:0;z-index:-1;opacity:.32;mix-blend-mode:overlay;
|
||
background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='80' viewBox='0 0 140 80'><g fill='none' stroke='%23ffffff' stroke-width='1.2' opacity='0.55'><path d='M0 20 Q35 0 70 20 T140 20'/><path d='M0 40 Q35 20 70 40 T140 40'/><path d='M0 60 Q35 40 70 60 T140 60'/></g></svg>")}
|
||
.para-hero::after{transition:transform .5s var(--ease-out);transform:translate(var(--phx,0),var(--phy,0))}
|
||
.para-hero:hover{transform:translateY(-2px)}
|
||
.para-hero:hover::after{transform:translate(var(--phx,0),var(--phy,0)) scale(1.1)}
|
||
.para-hero .ph-glow{position:absolute;left:-10%;bottom:-40%;width:60%;height:120%;background:radial-gradient(closest-side,rgba(255,255,255,.32),transparent);pointer-events:none;z-index:-1;animation:phPulse 4s ease-in-out infinite alternate}
|
||
@keyframes phPulse{from{opacity:.6;transform:scale(.92)}to{opacity:.95;transform:scale(1.06)}}
|
||
.ph-badge{position:absolute;top:14px;right:16px;background:rgba(255,255,255,.22);border:1px solid rgba(255,255,255,.4);border-radius:var(--r-full);padding:4px 10px;font-size:.68rem;font-weight:800;letter-spacing:.05em;backdrop-filter:blur(6px);z-index:1}
|
||
|
||
/* ── A3. Карточки формул v2 ── */
|
||
.fcard{transition:transform var(--dur-2) var(--ease-out),box-shadow var(--dur-2) var(--ease-out),border-color var(--dur-2) var(--ease);position:relative;overflow:hidden;backdrop-filter:blur(8px);background:linear-gradient(180deg,var(--card),color-mix(in srgb,var(--card) 96%,var(--pri-300)))}
|
||
.fcard::before{content:'';position:absolute;inset:0;background:radial-gradient(220px circle at var(--mx,50%) var(--my,0%),rgba(147,51,234,.10),transparent 60%);opacity:0;transition:opacity var(--dur-2) var(--ease);pointer-events:none}
|
||
.fcard:hover{transform:translateY(-3px) scale(1.005);box-shadow:var(--shadow-pop);border-color:var(--pri-400)}
|
||
.fcard:hover::before{opacity:1}
|
||
.fcard .main-f{transition:transform var(--dur-2) var(--ease-bounce)}
|
||
.fcard:hover .main-f{transform:scale(1.03)}
|
||
html.dark .fcard{background:linear-gradient(180deg,var(--card),color-mix(in srgb,var(--card) 92%,var(--pri-700)))}
|
||
|
||
/* Семантические бордеры для разных типов карточек */
|
||
.fcard.is-def{border-color:var(--pri-400)}
|
||
.fcard.is-law{border-color:#0891b2}
|
||
.fcard.is-formula{border-color:#a16207}
|
||
.fcard.is-rule{border-color:#7c3aed}
|
||
|
||
/* ── Кнопки v2: ripple + улучшенные ── */
|
||
.btn{transition:transform var(--dur-1) var(--ease-bounce),box-shadow var(--dur-2) var(--ease),filter var(--dur-2) var(--ease),background var(--dur-2) var(--ease);position:relative;overflow:hidden}
|
||
.btn-pri{background:linear-gradient(135deg,var(--pri-500),var(--pri-700));box-shadow:0 4px 14px rgba(147,51,234,.3)}
|
||
.btn-pri:hover{box-shadow:0 6px 20px rgba(147,51,234,.45);transform:translateY(-1px)}
|
||
.btn-next{background:linear-gradient(135deg,#16a34a,#15803d);box-shadow:0 4px 14px rgba(22,163,74,.3)}
|
||
.btn-next:hover{box-shadow:0 6px 20px rgba(22,163,74,.45);transform:translateY(-1px)}
|
||
.btn::after{content:'';position:absolute;inset:0;background:radial-gradient(circle at var(--rx,50%) var(--ry,50%),rgba(255,255,255,.6),transparent 40%);opacity:0;transition:opacity var(--dur-3) var(--ease);pointer-events:none}
|
||
.btn.is-ripple::after{opacity:1;animation:rippleOut .55s var(--ease-out) forwards}
|
||
@keyframes rippleOut{from{opacity:.5;transform:scale(.4)}to{opacity:0;transform:scale(2.2)}}
|
||
|
||
/* ── Табы v2 ── */
|
||
.tab{transition:transform var(--dur-1) var(--ease),border-color var(--dur-1) var(--ease),background var(--dur-2) var(--ease),color var(--dur-2) var(--ease);position:relative}
|
||
.tab:hover{transform:translateY(-1px)}
|
||
.tab.active{box-shadow:0 4px 14px rgba(147,51,234,.32)}
|
||
.tab.active::after{content:'';position:absolute;left:50%;bottom:-9px;width:6px;height:6px;background:var(--pri);border-radius:50%;transform:translateX(-50%);box-shadow:0 0 8px var(--pri)}
|
||
|
||
/* Pills параграфов в задачах */
|
||
.para-pill{transition:all var(--dur-1) var(--ease)}
|
||
.para-pill:hover{transform:translateY(-1px);box-shadow:var(--shadow-sm)}
|
||
.para-pill.active{box-shadow:0 3px 10px rgba(147,51,234,.3)}
|
||
|
||
/* ── Nav-dots v2: пульс активного ── */
|
||
.nav-dot{transition:transform var(--dur-1) var(--ease),box-shadow var(--dur-2) var(--ease),background var(--dur-2) var(--ease)}
|
||
.nav-dot:hover{transform:scale(1.08)}
|
||
.nav-dot.nd-cur{box-shadow:0 0 0 4px rgba(147,51,234,.18),0 4px 12px rgba(147,51,234,.3);animation:dotPulse 2.4s ease-in-out infinite}
|
||
@keyframes dotPulse{0%,100%{box-shadow:0 0 0 4px rgba(147,51,234,.18),0 4px 12px rgba(147,51,234,.3)}50%{box-shadow:0 0 0 7px rgba(147,51,234,.08),0 4px 14px rgba(147,51,234,.4)}}
|
||
|
||
/* ── Task-card v2 ── */
|
||
.task-card{transition:box-shadow var(--dur-2) var(--ease);background:linear-gradient(180deg,var(--card),color-mix(in srgb,var(--card) 95%,var(--pri-300)))}
|
||
.task-card:focus-within{box-shadow:var(--shadow-pop),0 0 0 3px rgba(147,51,234,.15)}
|
||
.ans-inp{transition:border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease),transform var(--dur-1) var(--ease)}
|
||
.ans-inp:focus{transform:scale(1.02)}
|
||
|
||
/* ── Feedback v2: с иконкой и slide ── */
|
||
.feedback{border-left:4px solid transparent;backdrop-filter:blur(4px)}
|
||
.fb-ok{border-left-color:var(--ok);background:linear-gradient(135deg,var(--ok-bg),color-mix(in srgb,var(--ok-bg) 70%,transparent))}
|
||
.fb-fail{border-left-color:var(--fail);background:linear-gradient(135deg,var(--fail-bg),color-mix(in srgb,var(--fail-bg) 70%,transparent))}
|
||
|
||
/* ── Канвас-контейнер v2 ── */
|
||
.idiag{transition:border-color var(--dur-2) var(--ease),box-shadow var(--dur-2) var(--ease)}
|
||
.idiag:hover{border-color:var(--pri-400);box-shadow:var(--shadow-md)}
|
||
canvas{transition:filter var(--dur-2) var(--ease)}
|
||
|
||
/* Подпись под канвасом */
|
||
.cv-cap{font-size:.74rem;color:var(--muted);margin-top:8px;line-height:1.6;display:flex;align-items:flex-start;gap:6px}
|
||
.cv-cap i{color:var(--pri);margin-top:2px;flex-shrink:0}
|
||
|
||
/* ── Чипы значений интерактивов ── */
|
||
.val-chip{display:inline-flex;align-items:center;gap:5px;padding:4px 10px;border-radius:var(--r-full);background:rgba(147,51,234,.1);color:var(--pri-700);font-weight:800;font-family:monospace;font-size:.78rem;border:1px solid rgba(147,51,234,.2);transition:all var(--dur-1) var(--ease)}
|
||
html.dark .val-chip{color:var(--pri-300);background:rgba(147,51,234,.18);border-color:rgba(147,51,234,.3)}
|
||
|
||
/* ── C1. Sticky mini-TOC слева ── */
|
||
#miniToc{position:fixed;left:14px;top:130px;width:50px;z-index:55;display:none;flex-direction:column;gap:6px;max-height:calc(100vh - 180px);overflow-y:auto;padding:8px;background:var(--card);border:1px solid var(--border);border-radius:var(--r-lg);box-shadow:var(--shadow-md);scrollbar-width:none}
|
||
#miniToc::-webkit-scrollbar{display:none}
|
||
#miniToc .mt-item{display:grid;place-items:center;width:34px;height:34px;border-radius:var(--r-sm);font-size:.66rem;font-weight:800;color:var(--muted);background:transparent;border:1.5px solid var(--border);cursor:pointer;transition:all var(--dur-1) var(--ease);font-family:inherit;padding:0;flex-shrink:0}
|
||
#miniToc .mt-item:hover{color:var(--pri);border-color:var(--pri);transform:translateX(2px)}
|
||
#miniToc .mt-item.is-active{background:var(--pri);color:#fff;border-color:var(--pri);box-shadow:0 4px 10px rgba(147,51,234,.3)}
|
||
#miniToc .mt-divider{height:1px;background:var(--border);margin:4px 0;flex-shrink:0}
|
||
@media(min-width:1180px){#miniToc{display:flex}}
|
||
|
||
/* ── Скролл — плавный ── */
|
||
html{scroll-behavior:smooth}
|
||
|
||
/* ── Hint для канваса при касании/hover ── */
|
||
.cv-hint{position:absolute;top:8px;right:8px;background:rgba(0,0,0,.45);color:#fff;padding:3px 9px;border-radius:var(--r-full);font-size:.65rem;font-weight:700;pointer-events:none;backdrop-filter:blur(4px);letter-spacing:.04em;text-transform:uppercase;opacity:.9}
|
||
|
||
/* ── Hover на iconified элементах ── */
|
||
.life-item{transition:transform var(--dur-2) var(--ease-out),box-shadow var(--dur-2) var(--ease),border-color var(--dur-2) var(--ease)}
|
||
.life-item:hover{transform:translateY(-3px);box-shadow:var(--shadow-md);border-color:var(--pri-300)}
|
||
.life-item .li-icon{transition:transform var(--dur-2) var(--ease-bounce)}
|
||
.life-item:hover .li-icon{transform:scale(1.15) rotate(-4deg)}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<!-- Floating: тема -->
|
||
<button class="theme-btn" id="themeBtn" title="Тема"><i class="fas fa-moon"></i></button>
|
||
|
||
<!-- Floating: справочник -->
|
||
<button class="ref-toggle" id="refToggle" title="Справочник"><i class="fas fa-book-open"></i></button>
|
||
|
||
<!-- Popup справочник -->
|
||
<div class="ref-panel" id="refPanel">
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;padding-bottom:8px;border-bottom:1px solid var(--border)">
|
||
<span style="font-size:.82rem;font-weight:800;color:var(--pri)"><i class="fas fa-book-open"></i> Справочник · §32–40</span>
|
||
<button onclick="document.getElementById('refPanel').classList.remove('show')"
|
||
style="background:none;border:none;cursor:pointer;color:var(--muted);font-size:1rem;line-height:1;padding:2px 4px;border-radius:5px" title="Закрыть">✕</button>
|
||
</div>
|
||
|
||
<!-- Вкладки -->
|
||
<div class="ref-tabs">
|
||
<button class="ref-tab-btn active" onclick="switchRefTab('para')">Параграф</button>
|
||
<button class="ref-tab-btn" onclick="switchRefTab('cheat')">Шпаргалка</button>
|
||
<button class="ref-tab-btn" onclick="switchRefTab('tasks')">Задачи</button>
|
||
</div>
|
||
|
||
<!-- Вкладка: Параграф -->
|
||
<div class="ref-tab-content active" id="reftab-para">
|
||
<div class="ref-body">
|
||
<h3>Скорость и распространение</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>$c = 3 \times 10^8$ м/с — скорость света в вакууме</div>
|
||
<div style="margin-top:4px">Вода: $v \approx 2{,}25 \times 10^8$ м/с; Стекло: $v \approx 2{,}00 \times 10^8$ м/с</div>
|
||
<div>Алмаз: $v \approx 1{,}24 \times 10^8$ м/с</div>
|
||
</div>
|
||
<h3>Отражение</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>$\gamma = \alpha$ (угол отражения = углу падения)</div>
|
||
<div>Зеркальное: параллельные → параллельные</div>
|
||
<div>Диффузное: рассеивается во все стороны</div>
|
||
</div>
|
||
<h3>Плоское зеркало</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>$l_1 = l_2$ (изображение на том же расстоянии за зеркалом)</div>
|
||
<div>Мнимое · прямое · равных размеров</div>
|
||
</div>
|
||
<h3>Преломление</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>$n = c/v$ (показатель преломления)</div>
|
||
<div>Плотнее среда → $\beta < \alpha$</div>
|
||
<div>Менее плотная → $\beta > \alpha$</div>
|
||
<div>$\alpha = 0°$ → преломления нет</div>
|
||
</div>
|
||
<h3>Линзы и оптическая сила</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>$D = 1/F$ [дптр]; $F$ [м]</div>
|
||
<div>Собирающая: $D > 0$, $F > 0$</div>
|
||
<div>Рассеивающая: $D < 0$, $F < 0$</div>
|
||
</div>
|
||
<h3>Изображения в линзах</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>$d > 2F$ → действ., перевёрн., уменьш.</div>
|
||
<div>$F < d < 2F$ → действ., перевёрн., увелич.</div>
|
||
<div>$d < F$ → мнимое, прямое, увелич. (лупа)</div>
|
||
<div>Рассеивающая → только мнимое, прямое, уменьш.</div>
|
||
</div>
|
||
<h3>Дефекты зрения</h3>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:10px">
|
||
<div>Близорукость: $D < 0$ (рассеивающие очки)</div>
|
||
<div>Дальнозоркость: $D > 0$ (собирающие очки)</div>
|
||
<div>Расстояние наилучшего видения: 25 см</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Вкладка: Шпаргалка -->
|
||
<div class="ref-tab-content" id="reftab-cheat">
|
||
<div style="font-size:.72rem;color:var(--muted);margin-bottom:8px">Все формулы §32–40 — сверь с параграфом</div>
|
||
<div class="ref-formula-table-wrap">
|
||
<table class="ref-formula-table">
|
||
<thead>
|
||
<tr><th>§</th><th>Формула</th><th>Описание</th><th>Ед.</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr><td>§32</td><td>—</td><td>Источники: тепловые и нетепловые</td><td>—</td></tr>
|
||
<tr><td>§33</td><td>$c = 3\times10^8\ \text{м/с}$</td><td>Скорость света в вакууме</td><td>м/с</td></tr>
|
||
<tr><td>§33</td><td>$t = l/c$</td><td>Время пробега света</td><td>с</td></tr>
|
||
<tr><td>§34</td><td>$\gamma = \alpha$</td><td>Закон отражения (угол отражения = углу падения)</td><td>°</td></tr>
|
||
<tr><td>§35</td><td>$l_1 = l_2$</td><td>Изображение в плоском зеркале: расстояния равны</td><td>м</td></tr>
|
||
<tr><td>§36</td><td>$n = \dfrac{c}{v}$</td><td>Абсолютный показатель преломления</td><td>б/р</td></tr>
|
||
<tr><td>§36</td><td>$\dfrac{\sin\alpha}{\sin\beta} = n$</td><td>Закон преломления (в/из воздуха)</td><td>—</td></tr>
|
||
<tr><td>§37</td><td>$D = \dfrac{1}{F}$</td><td>Оптическая сила линзы</td><td>дптр</td></tr>
|
||
<tr><td>§38</td><td>$\dfrac{1}{F} = \dfrac{1}{d} + \dfrac{1}{f}$</td><td>Формула тонкой линзы</td><td>м⁻¹</td></tr>
|
||
<tr><td>§38</td><td>$\Gamma = \dfrac{f}{d}$</td><td>Линейное увеличение линзы</td><td>б/р</td></tr>
|
||
<tr><td>§39</td><td>$D_{\text{глаз}} \approx 60\ \text{дптр}$</td><td>Оптическая сила нормального глаза</td><td>дптр</td></tr>
|
||
<tr><td>§39</td><td>$d_{\text{набл}} = 25\ \text{см}$</td><td>Расстояние наилучшего видения</td><td>см</td></tr>
|
||
<tr><td>§40</td><td>$D < 0$</td><td>Близорукость: рассеивающие очки</td><td>дптр</td></tr>
|
||
<tr><td>§40</td><td>$D > 0$</td><td>Дальнозоркость: собирающие очки</td><td>дптр</td></tr>
|
||
<tr><td>§40</td><td>$F = 1/D$</td><td>Фокусное расстояние очковой линзы</td><td>м</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Вкладка: Задачи -->
|
||
<div class="ref-tab-content" id="reftab-tasks">
|
||
<div style="font-size:.72rem;color:var(--muted);margin-bottom:10px">Типовые задачи и подсказки к решению</div>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:8px">
|
||
<div style="font-weight:800;font-size:.76rem;color:var(--pri);margin-bottom:5px">§33 — Скорость света</div>
|
||
<div style="font-size:.76rem">Расстояние и время: $t = l/c$, $l = ct$</div>
|
||
<div style="font-size:.76rem;color:var(--muted)">Перевести км→м (умножить на 1000)</div>
|
||
</div>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:8px">
|
||
<div style="font-weight:800;font-size:.76rem;color:var(--pri);margin-bottom:5px">§34 — Отражение</div>
|
||
<div style="font-size:.76rem">Угол к нормали! $\varphi$ к поверхности → $\alpha = 90° - \varphi$</div>
|
||
<div style="font-size:.76rem;color:var(--muted)">Поворот зеркала на φ → луч повернётся на 2φ</div>
|
||
</div>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:8px">
|
||
<div style="font-weight:800;font-size:.76rem;color:var(--pri);margin-bottom:5px">§35 — Зеркало</div>
|
||
<div style="font-size:.76rem">$l_1 = l_2$; расстояние предмет–изображение = $2l$</div>
|
||
<div style="font-size:.76rem;color:var(--muted)">Скорость сближения с изображением = 2v</div>
|
||
</div>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:8px">
|
||
<div style="font-weight:800;font-size:.76rem;color:var(--pri);margin-bottom:5px">§37 — Оптическая сила</div>
|
||
<div style="font-size:.76rem">$D = 1/F$ [дптр], $F$ в метрах!</div>
|
||
<div style="font-size:.76rem;color:var(--muted)">$F$ в см: разделить на 100 для перевода в м</div>
|
||
</div>
|
||
<div style="background:rgba(124,58,237,.06);border-radius:9px;padding:10px 12px;margin-bottom:8px">
|
||
<div style="font-weight:800;font-size:.76rem;color:var(--pri);margin-bottom:5px">§38 — Формула линзы</div>
|
||
<div style="font-size:.76rem">$1/F = 1/d + 1/f$; $\Gamma = f/d$</div>
|
||
<div style="font-size:.76rem;color:var(--muted)">$d > 2F$: уменьш.; $F < d < 2F$: увелич.; $d < F$: лупа</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Шапка -->
|
||
<div class="hdr">
|
||
<h1><i class="fas fa-eye"></i> Физика 8 — Световые явления</h1>
|
||
<p>Свет · Отражение · Преломление · Линзы · Оптические приборы</p>
|
||
</div>
|
||
|
||
<!-- Двухколоночный layout -->
|
||
<div class="page-wrap">
|
||
|
||
<!-- Sidebar -->
|
||
<aside class="sidebar">
|
||
<div class="sb-brand">
|
||
<span class="sb-logo">🔭</span>
|
||
<div>
|
||
<span class="sb-title">Физика 8</span>
|
||
<span class="sb-sub">Световые явления · §32–40</span>
|
||
</div>
|
||
</div>
|
||
<nav class="sb-nav">
|
||
<button class="sb-item active" data-target="ref32">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="10" cy="10" r="4"/><line x1="10" y1="1" x2="10" y2="3"/><line x1="10" y1="17" x2="10" y2="19"/><line x1="1" y1="10" x2="3" y2="10"/><line x1="17" y1="10" x2="19" y2="10"/><line x1="3.5" y1="3.5" x2="5" y2="5"/><line x1="15" y1="15" x2="16.5" y2="16.5"/><line x1="16.5" y1="3.5" x2="15" y2="5"/><line x1="5" y1="15" x2="3.5" y2="16.5"/></svg></span>
|
||
<span class="sb-num">§32</span>
|
||
<span class="sb-name">Источники света</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref33">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><path d="M2 14 Q6 10 10 10 Q14 10 18 6"/><line x1="14" y1="6" x2="18" y2="6"/><line x1="18" y1="6" x2="18" y2="10"/></svg></span>
|
||
<span class="sb-num">§33</span>
|
||
<span class="sb-name">Скорость и прямолинейность</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref34">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><line x1="2" y1="14" x2="18" y2="14"/><line x1="10" y1="14" x2="10" y2="4" stroke-dasharray="2,2"/><path d="M3 4 L10 14"/><path d="M10 14 L17 4"/></svg></span>
|
||
<span class="sb-num">§34</span>
|
||
<span class="sb-name">Отражение света</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref35">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><line x1="10" y1="2" x2="10" y2="18"/><path d="M4 6 L10 10 L4 14" stroke-linecap="round"/><path d="M16 6 L10 10 L16 14" stroke-linecap="round" stroke-dasharray="2,2"/></svg></span>
|
||
<span class="sb-num">§35</span>
|
||
<span class="sb-name">Зеркала. Плоское зеркало</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref36">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><line x1="10" y1="2" x2="10" y2="18" stroke-dasharray="3,2"/><path d="M2 5 L10 10"/><path d="M10 10 L18 13"/><line x1="2" y1="10" x2="18" y2="10" stroke-opacity=".4"/></svg></span>
|
||
<span class="sb-num">§36</span>
|
||
<span class="sb-name">Преломление света</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref37">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><ellipse cx="10" cy="10" rx="3" ry="8"/><line x1="2" y1="10" x2="18" y2="10"/><line x1="2" y1="7" x2="7" y2="7"/><line x1="7" y1="7" x2="16" y2="10"/><line x1="2" y1="13" x2="7" y2="13"/><line x1="7" y1="13" x2="16" y2="10"/></svg></span>
|
||
<span class="sb-num">§37</span>
|
||
<span class="sb-name">Линзы. Оптическая сила</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref38">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><ellipse cx="10" cy="10" rx="3" ry="7"/><line x1="2" y1="10" x2="18" y2="10"/><line x1="3" y1="6" x2="10" y2="6"/><line x1="10" y1="6" x2="17" y2="9"/><line x1="3" y1="14" x2="10" y2="14"/><line x1="10" y1="14" x2="17" y2="11"/><circle cx="17" cy="10" r="2" fill="currentColor" stroke="none" opacity=".7"/></svg></span>
|
||
<span class="sb-num">§38</span>
|
||
<span class="sb-name">Изображения в линзах</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref39">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><ellipse cx="10" cy="10" rx="8" ry="6"/><circle cx="10" cy="10" r="2.5"/><circle cx="10" cy="10" r="1" fill="currentColor" stroke="none"/></svg></span>
|
||
<span class="sb-num">§39</span>
|
||
<span class="sb-name">Глаз как оптическая система</span>
|
||
</button>
|
||
<button class="sb-item" data-target="ref40">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><circle cx="7" cy="11" r="3.5"/><circle cx="13" cy="11" r="3.5"/><line x1="10.5" y1="11" x2="10.5" y2="11"/><path d="M3.5 11 Q3 8 7 8"/><path d="M16.5 11 Q17 8 13 8"/><line x1="1" y1="11" x2="3.5" y2="11"/><line x1="16.5" y1="11" x2="19" y2="11"/><line x1="10" y1="8.5" x2="10" y2="7"/></svg></span>
|
||
<span class="sb-num">§40</span>
|
||
<span class="sb-name">Дефекты зрения. Очки</span>
|
||
</button>
|
||
<div class="sb-divider"></div>
|
||
<button class="sb-item" data-target="tasks">
|
||
<span class="para-icon"><svg viewBox="0 0 20 20" width="20" height="20" fill="none" stroke="currentColor" stroke-width="1.6"><rect x="4" y="2" width="12" height="16" rx="2"/><line x1="7" y1="7" x2="13" y2="7"/><line x1="7" y1="10" x2="13" y2="10"/><line x1="7" y1="13" x2="11" y2="13"/></svg></span>
|
||
<span class="sb-num"></span>
|
||
<span class="sb-name">Задачи</span>
|
||
</button>
|
||
</nav>
|
||
</aside>
|
||
|
||
<!-- Main content -->
|
||
<main class="main-col">
|
||
<div class="content-area">
|
||
|
||
<!-- §32 -->
|
||
<div class="content active" id="tab-ref32">
|
||
<div class="para-hero ph-32">
|
||
<div class="ph-label">§32 · Физика 8 кл</div>
|
||
<h2>Источники света</h2>
|
||
<div class="ph-desc">Тела, излучающие свет — источники. Тепловые (Солнце, лампа, свеча) и нетепловые (светлячки, лазер, флуоресценция). Точечный источник: размерами в условии задачи можно пренебречь.</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">☀️ тепловые и холодные</span>
|
||
<span class="ph-tag">🔦 точечный источник</span>
|
||
<span class="ph-tag">➡️ луч = линия света</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-sun"></i> §32. Источники света</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Виды источников</h3>
|
||
<div class="main-f" style="font-size:.85rem">тепловые · нетепловые (люминесцентные)</div>
|
||
<p><b>Тепловые:</b> тела, нагретые до высокой температуры → Солнце, лампа накаливания, пламя свечи.</p>
|
||
<p><b>Нетепловые:</b> светлячки, флуоресцеин, лазер — свечение без нагрева.</p>
|
||
<p><b>Точечный источник:</b> размерами в условии задачи можно пренебречь.</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Луч света</h3>
|
||
<div class="main-f" style="font-size:.85rem">линия, вдоль которой распространяется свет</div>
|
||
<p>Лучи от точечного источника расходятся во все стороны.</p>
|
||
<p>Чем меньше отверстие — тем ближе пучок к идеальному лучу.</p>
|
||
<p>Большинство видимых нами тел мы видим благодаря <b>отражённому</b> от них свету.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="life-grid">
|
||
<div class="life-item"><div class="li-icon">☀️</div><div class="li-title">Солнце</div><div class="li-desc">Тепловой источник: температура поверхности ~6000°C → белый свет</div></div>
|
||
<div class="life-item"><div class="li-icon">🔦</div><div class="li-title">Лампа накаливания</div><div class="li-desc">Тепловой источник: нить нагрета током до ~2600°C</div></div>
|
||
<div class="life-item"><div class="li-icon">🐛</div><div class="li-title">Светлячок</div><div class="li-desc">Нетепловой (биолюминесценция): химическая реакция без нагрева</div></div>
|
||
<div class="life-item"><div class="li-icon">🔴</div><div class="li-title">Лазер</div><div class="li-desc">Нетепловой: когерентное монохроматическое излучение, применяется в медицине, связи</div></div>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>Источник света — тело, <b>само излучающее</b> свет (не отражённый).</li>
|
||
<li>Луна, книга, деревья — <b>не источники</b>: мы их видим в отражённом свете.</li>
|
||
<li>Точечный источник — упрощение задачи: его размером пренебрегаем.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §32</div>
|
||
<ul class="key-points-list">
|
||
<li>Источник света — тело, которое само излучает свет (не отражённый): Солнце, лампа, свеча.</li>
|
||
<li>Тепловые источники светятся из-за нагрева; нетепловые (светлячки, лазер) — без нагрева.</li>
|
||
<li>Луч — линия, вдоль которой распространяется свет; идеальный луч — упрощение модели.</li>
|
||
<li>Точечный источник — источник, размерами которого в данной задаче можно пренебречь.</li>
|
||
<li>Большинство видимых предметов видны в отражённом свете — сами не являются источниками.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Точечный источник и лучи</div>
|
||
<div class="idiag">
|
||
<h3>☀️ Лучи от точечного источника</h3>
|
||
<canvas id="cv32" style="width:100%;height:240px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<div class="slider-row" style="flex:1;min-width:200px">
|
||
<span class="slider-lbl">Число лучей:</span>
|
||
<input type="range" id="sl32n" min="4" max="36" value="12" style="flex:1" oninput="lbl32n.textContent=this.value;upd32();">
|
||
<span class="slider-val"><span id="lbl32n">12</span></span>
|
||
</div>
|
||
<select id="sel32src" onchange="upd32()" style="padding:6px 10px;border-radius:8px;border:2px solid var(--border);background:var(--card);color:var(--text)">
|
||
<option value="point">Точечный источник</option>
|
||
<option value="wide">Протяжённый источник</option>
|
||
</select>
|
||
</div>
|
||
<p style="font-size:.78rem;color:var(--muted);margin-top:8px">Точечный источник излучает лучи равномерно во все стороны. Экран с отверстием выделяет один луч.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §33 -->
|
||
<div class="content" id="tab-ref33">
|
||
<div class="para-hero ph-33">
|
||
<div class="ph-label">§33 · Физика 8 кл</div>
|
||
<h2>Скорость света. Прямолинейность</h2>
|
||
<div class="ph-formula">$c = 3 \times 10^8$ м/с</div>
|
||
<div class="ph-desc">Скорость света в вакууме — максимальная в природе. В оптически более плотных средах скорость меньше. В однородной среде свет распространяется прямолинейно → тень и полутень.</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">$c = 3 \times 10^8$ м/с</span>
|
||
<span class="ph-tag">🌫️ оптически плотные среды</span>
|
||
<span class="ph-tag">🌑 тень и полутень</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-bolt-lightning"></i> §33. Скорость света. Прямолинейность распространения</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Скорость света</h3>
|
||
<div class="main-f">$c = 3 \times 10^8$ м/с</div>
|
||
<p>Скорость света в вакууме — максимальная скорость в природе.</p>
|
||
<p>В среде: $v < c$. Чем <b>оптически плотнее</b> среда — тем медленнее.</p>
|
||
<table style="width:100%;font-size:.78rem;margin-top:6px;border-collapse:collapse">
|
||
<tr><td style="padding:2px 4px">Вода</td><td style="padding:2px 4px;font-weight:700">$2{,}25 \times 10^8$ м/с</td><td style="padding:2px 4px">Стекло</td><td style="padding:2px 4px;font-weight:700">$2{,}00 \times 10^8$ м/с</td></tr>
|
||
<tr><td style="padding:2px 4px">Алмаз</td><td style="padding:2px 4px;font-weight:700">$1{,}24 \times 10^8$ м/с</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Прямолинейность. Тень и полутень</h3>
|
||
<div class="main-f" style="font-size:.85rem">в однородной среде — прямолинейно</div>
|
||
<p>От <b>точечного</b> источника — только тень (чёткая граница).</p>
|
||
<p>От <b>протяжённого</b> — тень и полутень.</p>
|
||
<p>Солнечное затмение: Луна создаёт тень и полутень на Земле.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="idiag">
|
||
<h3>🌑 Тень и полутень от разных источников</h3>
|
||
<svg width="100%" viewBox="0 0 320 130" style="display:block">
|
||
<!-- Точечный источник -->
|
||
<text x="30" y="12" font-size="8.5" fill="#fbbf24" font-family="sans-serif" font-weight="bold">Точечный источник S</text>
|
||
<circle cx="20" cy="65" r="6" fill="#fbbf24"/>
|
||
<text x="20" y="69" font-size="7" fill="#1e1b4b" font-family="sans-serif" text-anchor="middle">S</text>
|
||
<!-- Предмет -->
|
||
<rect x="85" y="50" width="8" height="30" rx="2" fill="#475569"/>
|
||
<!-- Тень -->
|
||
<path d="M20,59 L85,50 L160,40 M20,71 L85,80 L160,90" stroke="rgba(251,191,36,0.4)" stroke-width="1" fill="none"/>
|
||
<rect x="160" y="40" width="12" height="50" rx="2" fill="rgba(15,23,42,0.9)" stroke="#334155" stroke-width="1"/>
|
||
<text x="166" y="100" font-size="7" fill="#94a3b8" font-family="sans-serif" text-anchor="middle">тень</text>
|
||
<!-- Протяжённый источник -->
|
||
<text x="185" y="12" font-size="8.5" fill="#f97316" font-family="sans-serif" font-weight="bold">Протяжённый источник</text>
|
||
<rect x="180" y="50" width="6" height="30" rx="2" fill="#f97316"/>
|
||
<!-- Предмет 2 -->
|
||
<rect x="240" y="52" width="7" height="26" rx="2" fill="#475569"/>
|
||
<!-- Тень+полутень -->
|
||
<path d="M180,50 L240,52 L300,45 M180,80 L240,78 L300,85" stroke="rgba(249,115,22,0.3)" stroke-width="1" fill="none"/>
|
||
<path d="M183,50 L240,52 L300,52 M183,80 L240,78 L300,78" stroke="rgba(249,115,22,0.2)" stroke-width="1" fill="none"/>
|
||
<rect x="300" y="45" width="12" height="40" rx="2" fill="rgba(15,23,42,0.9)"/>
|
||
<rect x="300" y="40" width="12" height="5" rx="1" fill="rgba(50,40,40,0.5)"/>
|
||
<rect x="300" y="85" width="12" height="5" rx="1" fill="rgba(50,40,40,0.5)"/>
|
||
<text x="306" y="108" font-size="6" fill="#94a3b8" font-family="sans-serif" text-anchor="middle">тень</text>
|
||
<text x="306" y="42" font-size="6" fill="#94a3b8" font-family="sans-serif" text-anchor="middle">полутень</text>
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="insight-box">
|
||
<div class="insight-title"><i class="fas fa-lightbulb"></i> Мы смотрим в прошлое!</div>
|
||
<p>Свет от ближайшей к нам (после Солнца) звезды Проксима Центавра летит <b>4,2 года</b>. Свет от далёких галактик — <b>миллиарды лет</b>. Глядя на звёзды, мы видим, какими они были в момент испускания света — буквально «путешествие в прошлое».</p>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>$c = 3 \times 10^8$ м/с — скорость в вакууме; в среде — меньше.</li>
|
||
<li>Оптически более плотная среда: $v$ меньше — не путать с механической плотностью!</li>
|
||
<li>От точечного источника — только чёткая тень; от протяжённого — тень + полутень.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §33</div>
|
||
<ul class="key-points-list">
|
||
<li>Скорость света в вакууме $c = 3\times10^8$ м/с — максимальная скорость в природе.</li>
|
||
<li>В оптически более плотной среде скорость меньше: $v < c$ (вода: 2,25×10⁸; стекло: 2,00×10⁸ м/с).</li>
|
||
<li>В однородной среде свет распространяется прямолинейно — отсюда тени и полутени.</li>
|
||
<li>От точечного источника образуется только тень (чёткая граница); от протяжённого — тень и полутень.</li>
|
||
<li>Глядя на далёкие звёзды, мы видим их в прошлом: свет летит миллионы лет.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Тень и полутень</div>
|
||
<div class="idiag">
|
||
<h3>🌑 Наблюдай тень и полутень на экране</h3>
|
||
<canvas id="cv33" style="width:100%;height:260px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<select id="sel33src" onchange="upd33()" style="padding:6px 10px;border-radius:8px;border:2px solid var(--border);background:var(--card);color:var(--text)">
|
||
<option value="point">Точечный источник</option>
|
||
<option value="wide">Протяжённый источник</option>
|
||
</select>
|
||
<div class="slider-row" style="flex:1;min-width:180px">
|
||
<span class="slider-lbl">Размер предмета:</span>
|
||
<input type="range" id="sl33obj" min="10" max="60" value="30" style="flex:1" oninput="upd33();">
|
||
<span class="slider-val" id="lbl33obj">30</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §34 -->
|
||
<div class="content" id="tab-ref34">
|
||
<div class="para-hero ph-34">
|
||
<div class="ph-label">§34 · Физика 8 кл</div>
|
||
<h2>Отражение света</h2>
|
||
<div class="ph-formula">$\gamma = \alpha$</div>
|
||
<div class="ph-desc">Угол отражения равен углу падения. Падающий луч, отражённый и нормаль лежат в одной плоскости. Зеркальное отражение (гладкие) и диффузное (шероховатые).</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">$\gamma = \alpha$</span>
|
||
<span class="ph-tag">🪞 зеркальное</span>
|
||
<span class="ph-tag">⬜ диффузное</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-arrows-left-right"></i> §34. Отражение света</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Законы отражения</h3>
|
||
<div class="main-f">$\gamma = \alpha$</div>
|
||
<p>1. Угол отражения равен углу падения.</p>
|
||
<p>2. Падающий луч, отражённый и нормаль к поверхности лежат в <b>одной плоскости</b>.</p>
|
||
<p>$\alpha$ — угол падения (к нормали!), $\gamma$ — угол отражения.</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Зеркальное и диффузное</h3>
|
||
<div class="main-f" style="font-size:.85rem">зеркальное · диффузное (рассеянное)</div>
|
||
<p><b>Зеркальное:</b> гладкая поверхность → параллельные лучи → параллельные (зеркало, вода).</p>
|
||
<p><b>Диффузное:</b> шероховатая → рассеивание во все стороны → поверхность видна с любой точки.</p>
|
||
<p>Именно благодаря диффузному отражению мы видим все матовые предметы вокруг!</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="idiag-2col">
|
||
<div class="idiag">
|
||
<h3>📐 Закон отражения — схема</h3>
|
||
<svg width="100%" viewBox="0 0 200 120" style="display:block">
|
||
<!-- Зеркало -->
|
||
<line x1="10" y1="80" x2="190" y2="80" stroke="#64748b" stroke-width="2.5"/>
|
||
<rect x="10" y="80" width="180" height="6" fill="rgba(99,102,241,0.3)"/>
|
||
<!-- Нормаль -->
|
||
<line x1="100" y1="80" x2="100" y2="15" stroke="#94a3b8" stroke-width="1.5" stroke-dasharray="4,3"/>
|
||
<text x="106" y="20" font-size="8" fill="#94a3b8" font-family="sans-serif">нормаль</text>
|
||
<!-- Падающий луч -->
|
||
<line x1="40" y1="20" x2="100" y2="80" stroke="#ef4444" stroke-width="2.5"/>
|
||
<polygon points="100,80 90,60 96,62" fill="#ef4444"/>
|
||
<text x="52" y="25" font-size="8" fill="#ef4444" font-family="sans-serif">падающий</text>
|
||
<!-- Отражённый луч -->
|
||
<line x1="100" y1="80" x2="160" y2="20" stroke="#3b82f6" stroke-width="2.5"/>
|
||
<polygon points="160,20 150,40 156,38" fill="#3b82f6"/>
|
||
<text x="140" y="25" font-size="8" fill="#3b82f6" font-family="sans-serif">отражённый</text>
|
||
<!-- Дуги углов -->
|
||
<path d="M100,60 A20,20 0 0,0 85,70" stroke="#ef4444" stroke-width="1.5" fill="none"/>
|
||
<text x="72" y="62" font-size="9" fill="#ef4444" font-family="sans-serif" font-weight="bold">α</text>
|
||
<path d="M100,60 A20,20 0 0,1 115,70" stroke="#3b82f6" stroke-width="1.5" fill="none"/>
|
||
<text x="116" y="62" font-size="9" fill="#3b82f6" font-family="sans-serif" font-weight="bold">γ</text>
|
||
<!-- Формула -->
|
||
<text x="100" y="110" text-anchor="middle" font-size="10" fill="#a855f7" font-family="sans-serif" font-weight="bold">γ = α</text>
|
||
</svg>
|
||
</div>
|
||
<div class="idiag">
|
||
<h3>🪞 Зеркальное vs диффузное</h3>
|
||
<svg width="100%" viewBox="0 0 200 120" style="display:block">
|
||
<!-- Зеркальное -->
|
||
<text x="50" y="12" text-anchor="middle" font-size="8.5" fill="#94a3b8" font-family="sans-serif">Зеркальное</text>
|
||
<line x1="10" y1="60" x2="90" y2="60" stroke="#6366f1" stroke-width="2"/>
|
||
<!-- параллельные лучи падают -->
|
||
<line x1="15" y1="35" x2="30" y2="60" stroke="#fbbf24" stroke-width="1.5"/>
|
||
<line x1="40" y1="30" x2="50" y2="60" stroke="#fbbf24" stroke-width="1.5"/>
|
||
<line x1="65" y1="35" x2="70" y2="60" stroke="#fbbf24" stroke-width="1.5"/>
|
||
<!-- параллельные лучи отражаются -->
|
||
<line x1="30" y1="60" x2="15" y2="35" stroke="#3b82f6" stroke-width="1.5" transform="scale(-1,1) translate(-90,0)"/>
|
||
<line x1="30" y1="60" x2="45" y2="35" stroke="#3b82f6" stroke-width="1.5"/>
|
||
<line x1="50" y1="60" x2="65" y2="35" stroke="#3b82f6" stroke-width="1.5"/>
|
||
<line x1="70" y1="60" x2="85" y2="35" stroke="#3b82f6" stroke-width="1.5"/>
|
||
<!-- Диффузное -->
|
||
<text x="150" y="12" text-anchor="middle" font-size="8.5" fill="#94a3b8" font-family="sans-serif">Диффузное</text>
|
||
<line x1="110" y1="65" x2="190" y2="65" stroke="#78716c" stroke-width="2"/>
|
||
<!-- Волнистость шероховатой -->
|
||
<path d="M110,65 Q120,62 130,65 Q140,68 150,65 Q160,62 170,65 Q180,68 190,65" stroke="#92400e" stroke-width="1.5" fill="none"/>
|
||
<!-- лучи рассеиваются -->
|
||
<line x1="140" y1="65" x2="115" y2="40" stroke="#f97316" stroke-width="1" opacity=".7"/>
|
||
<line x1="145" y1="65" x2="130" y2="35" stroke="#f97316" stroke-width="1" opacity=".7"/>
|
||
<line x1="150" y1="65" x2="150" y2="30" stroke="#f97316" stroke-width="1" opacity=".7"/>
|
||
<line x1="155" y1="65" x2="170" y2="35" stroke="#f97316" stroke-width="1" opacity=".7"/>
|
||
<line x1="160" y1="65" x2="185" y2="40" stroke="#f97316" stroke-width="1" opacity=".7"/>
|
||
<text x="150" y="100" text-anchor="middle" font-size="7.5" fill="#94a3b8" font-family="sans-serif">видна с любой стороны</text>
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>Углы $\alpha$ и $\gamma$ отсчитываются от <b>нормали</b>, а не от поверхности!</li>
|
||
<li>Свойство обратимости: если пустить луч обратно по отражённому — он пойдёт по падающему.</li>
|
||
<li>Зеркальное отражение: блестящие поверхности (зеркало, вода, полированный металл).</li>
|
||
<li>Диффузное: матовые поверхности (бумага, стены, снег, кожа) — видны с любой точки.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §34</div>
|
||
<ul class="key-points-list">
|
||
<li>Закон отражения: угол отражения равен углу падения ($\gamma = \alpha$). Углы — к нормали!</li>
|
||
<li>Падающий луч, отражённый луч и нормаль лежат в одной плоскости.</li>
|
||
<li>Зеркальное отражение: гладкая поверхность → параллельные лучи остаются параллельными.</li>
|
||
<li>Диффузное отражение: шероховатая поверхность → лучи рассеиваются во все стороны → предмет виден с любой точки.</li>
|
||
<li>Поворот зеркала на угол φ вызывает поворот отражённого луча на 2φ.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Закон отражения (Pro Max, мышью!)</div>
|
||
<div class="idiag">
|
||
<h3>🪞 Двигай мышью — лазер падает в точку курсора, отражение строится автоматически</h3>
|
||
<canvas id="cv34" style="width:100%;height:280px;border-radius:12px;background:#0f172a;cursor:crosshair;display:block;touch-action:none"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<button class="btn btn-ghost" type="button" onclick="reset34()" style="padding:6px 14px;font-size:.78rem">🔄 Сброс</button>
|
||
<select id="sel34type" onchange="upd34()" style="padding:6px 10px;border-radius:8px;border:2px solid var(--border);background:var(--card);color:var(--text)">
|
||
<option value="mirror">Зеркальное отражение</option>
|
||
<option value="diffuse">Диффузное отражение</option>
|
||
</select>
|
||
<span class="val-chip" id="chip34a">α = 35°</span>
|
||
<span class="val-chip" id="chip34b" style="background:rgba(34,197,94,.12);color:#16a34a;border-color:rgba(34,197,94,.3)">β = 35° ✓</span>
|
||
</div>
|
||
<div class="cv-cap"><i class="fas fa-mouse-pointer"></i> Двигай мышью над канвасом — наблюдай закон отражения: угол падения $\alpha$ = углу отражения $\gamma$. Кнопка «Сброс» вернёт луч под 45°.</div>
|
||
<div class="idiag-result" id="res34">$\alpha = 35°$ → $\gamma = 35°$ (закон отражения)</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §35 -->
|
||
<div class="content" id="tab-ref35">
|
||
<div class="para-hero ph-35">
|
||
<div class="ph-label">§35 · Физика 8 кл</div>
|
||
<h2>Зеркала. Изображение в плоском зеркале</h2>
|
||
<div class="ph-formula">$l_1 = l_2$</div>
|
||
<div class="ph-desc">Изображение в плоском зеркале: мнимое, прямое, равных размеров, на том же расстоянии за зеркалом. Вогнутые — собирают, выпуклые — рассеивают.</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">🪞 мнимое и прямое</span>
|
||
<span class="ph-tag">$l_1 = l_2$</span>
|
||
<span class="ph-tag">🔭 вогнутые и выпуклые</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-clone"></i> §35. Зеркала. Изображение в плоском зеркале</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Изображение в плоском зеркале</h3>
|
||
<div class="main-f">$l_1 = l_2$</div>
|
||
<p>Изображение: <b>мнимое</b> (за зеркалом), <b>прямое</b>, <b>равных размеров</b>.</p>
|
||
<p>Расстояние от предмета до зеркала = расстоянию от изображения до зеркала.</p>
|
||
<p>Образовано пересечением <b>продолжений</b> отражённых лучей — световой энергии за зеркалом нет!</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Вогнутое и выпуклое зеркала</h3>
|
||
<div class="main-f" style="font-size:.85rem">вогнутое → сходящееся · выпуклое → расходящееся</div>
|
||
<p><b>Вогнутое:</b> собирает параллельные лучи в фокусе — телескопы, прожекторы, зубные зеркала врача.</p>
|
||
<p><b>Выпуклое:</b> даёт широкий обзор — автомобильные зеркала заднего вида, зеркала безопасности в магазинах.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="insight-box">
|
||
<div class="insight-title"><i class="fas fa-lightbulb"></i> Почему «правое» становится «левым»?</div>
|
||
<p>Зеркало не переворачивает право–лево физически. Оно разворачивает изображение по оси, перпендикулярной его плоскости. Когда вы смотрите в зеркало, <b>вы видите себя повёрнутым на 180° вокруг вертикальной оси</b>. Поднятая правая рука кажется «левой», потому что для сравнения вы мысленно разворачиваете зеркальную копию — и получается «зеркальный двойник».</p>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>Мнимое изображение — фотоплёнка в той точке ничего не запишет (энергии там нет).</li>
|
||
<li>Расстояние до зеркала: $l_1 = l_2$ — изображение «симметрично» предмету.</li>
|
||
<li>Скорость изображения = скорости предмета; при сближении с зеркалом — скорость сближения с изображением вдвое больше.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="life-grid">
|
||
<div class="life-item"><div class="li-icon">🚗</div><div class="li-title">Зеркало заднего вида</div><div class="li-desc">Выпуклое зеркало — широкий угол обзора, изображение уменьшенное</div></div>
|
||
<div class="life-item"><div class="li-icon">🔭</div><div class="li-title">Телескоп-рефлектор</div><div class="li-desc">Вогнутое зеркало собирает свет далёких звёзд в фокусе</div></div>
|
||
<div class="life-item"><div class="li-icon">🦷</div><div class="li-title">Зубное зеркало</div><div class="li-desc">Вогнутое — увеличивает изображение для осмотра зубов</div></div>
|
||
<div class="life-item"><div class="li-icon">🏪</div><div class="li-title">Зеркало безопасности</div><div class="li-desc">Выпуклое в углу магазина — широкий обзор для охраны</div></div>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §35</div>
|
||
<ul class="key-points-list">
|
||
<li>Изображение в плоском зеркале: мнимое (за зеркалом), прямое, равных размеров, $l_1 = l_2$.</li>
|
||
<li>Мнимое — образовано продолжениями отражённых лучей; на экране не получить.</li>
|
||
<li>Расстояние предмет–изображение = $2l_1$; скорость сближения с изображением = $2v$.</li>
|
||
<li>Вогнутое зеркало собирает параллельные лучи в фокусе (телескопы, прожекторы).</li>
|
||
<li>Выпуклое зеркало рассеивает лучи, даёт широкий обзор (зеркала заднего вида, магазины).</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Изображение в плоском зеркале</div>
|
||
<div class="idiag">
|
||
<h3>🪞 Перемещай предмет — изображение строится автоматически</h3>
|
||
<canvas id="cv35" style="width:100%;height:280px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<div class="slider-row" style="flex:1;min-width:200px">
|
||
<span class="slider-lbl">Расстояние до зеркала $l_1$:</span>
|
||
<input type="range" id="sl35d" min="30" max="200" value="100" style="flex:1" oninput="lbl35d.textContent=this.value+' усл.ед.';upd35();">
|
||
<span class="slider-val"><span id="lbl35d">100 усл.ед.</span></span>
|
||
</div>
|
||
<label style="font-size:.82rem;display:flex;align-items:center;gap:6px;cursor:pointer">
|
||
<input type="checkbox" id="chk35rays" onchange="upd35()" checked> Показать лучи
|
||
</label>
|
||
</div>
|
||
<div class="idiag-result" id="res35">$l_1 = l_2 = 100$ усл.ед. Изображение мнимое, прямое, равных размеров.</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §36 -->
|
||
<div class="content" id="tab-ref36">
|
||
<div class="para-hero ph-36">
|
||
<div class="ph-label">§36 · Физика 8 кл</div>
|
||
<h2>Преломление света</h2>
|
||
<div class="ph-desc">При переходе в оптически более плотную среду: $\beta < \alpha$. В менее плотную: $\beta > \alpha$. Падающий и преломлённый лучи лежат в одной плоскости с нормалью.</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">💧 оптическая плотность</span>
|
||
<span class="ph-tag">↗ $\beta < \alpha$ (плотнее)</span>
|
||
<span class="ph-tag">↘ $\beta > \alpha$ (менее плотно)</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-layer-group"></i> §36. Преломление света</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Законы преломления</h3>
|
||
<div class="main-f" style="font-size:.82rem">плотнее → $\beta < \alpha$ · менее плотная → $\beta > \alpha$</div>
|
||
<p>1. Падающий и преломлённый лучи лежат в одной плоскости с нормалью к границе раздела.</p>
|
||
<p>2. При переходе в <b>оптически более плотную</b> среду: $\beta < \alpha$.</p>
|
||
<p>3. При переходе в <b>менее плотную</b>: $\beta > \alpha$.</p>
|
||
<p>4. При $\alpha = 0°$ преломления нет.</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Оптическая плотность среды</h3>
|
||
<div class="main-f" style="font-size:.82rem">чем плотнее — тем медленнее свет</div>
|
||
<table style="width:100%;font-size:.78rem;border-collapse:collapse;margin-top:6px">
|
||
<tr style="background:rgba(124,58,237,.08)"><th style="padding:3px 5px;border:1px solid var(--border)">Среда</th><th>$v$, $\times 10^8$ м/с</th><th>Плотнее воздуха?</th></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">Воздух</td><td style="text-align:center">≈3,0</td><td style="text-align:center">—</td></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">Вода</td><td style="text-align:center">2,25</td><td style="text-align:center;color:#7c3aed">✓</td></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">Стекло</td><td style="text-align:center">2,0</td><td style="text-align:center;color:#7c3aed">✓✓</td></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">Алмаз</td><td style="text-align:center">1,24</td><td style="text-align:center;color:#7c3aed">✓✓✓</td></tr>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="life-grid">
|
||
<div class="life-item"><div class="li-icon">🏊</div><div class="li-title">Ноги «короче» в воде</div><div class="li-desc">Лучи от ног преломляются на границе вода→воздух: $\beta > \alpha$ → мнимое изображение выше реального</div></div>
|
||
<div class="life-item"><div class="li-icon">🌅</div><div class="li-title">Мираж</div><div class="li-desc">Слои воздуха разной температуры — разной оптической плотности → лучи искривляются</div></div>
|
||
<div class="life-item"><div class="li-icon">💎</div><div class="li-title">Блеск алмаза</div><div class="li-desc">Очень высокая оптическая плотность → сильное преломление → полное внутреннее отражение → блеск</div></div>
|
||
<div class="life-item"><div class="li-icon">🔭</div><div class="li-title">Оптоволокно</div><div class="li-desc">Полное внутреннее отражение: свет «скачет» внутри стеклянной нити — передача данных</div></div>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>Оптическая плотность ≠ механической плотности (скипидар оптически плотнее воды, хотя легче).</li>
|
||
<li>При $\alpha = 0°$ (перпендикулярное падение) — преломления нет, луч идёт прямо.</li>
|
||
<li>Мнимое изображение дна водоёма — выше реального (поэтому дно «кажется мельче»).</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §36</div>
|
||
<ul class="key-points-list">
|
||
<li>При переходе в оптически более плотную среду: $\beta < \alpha$ (луч «прижимается» к нормали).</li>
|
||
<li>В менее плотную: $\beta > \alpha$ (луч «отходит» от нормали).</li>
|
||
<li>Показатель преломления: $n = c/v$ — чем плотнее среда, тем больше $n$.</li>
|
||
<li>При $\alpha = 0°$ (перпендикулярное падение) преломления нет — луч идёт прямо.</li>
|
||
<li>Оптическая плотность ≠ механической: скипидар оптически плотнее воды, хотя легче.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Преломление на границе сред</div>
|
||
<div class="idiag">
|
||
<h3>💧 Меняй угол и среды — наблюдай преломление</h3>
|
||
<canvas id="cv36" style="width:100%;height:270px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<div class="slider-row" style="flex:1;min-width:180px">
|
||
<span class="slider-lbl">Угол падения $\alpha$:</span>
|
||
<input type="range" id="sl36a" min="0" max="80" value="40" style="flex:1" oninput="lbl36a.textContent=this.value+'°';upd36();">
|
||
<span class="slider-val"><span id="lbl36a">40°</span></span>
|
||
</div>
|
||
<select id="sel36med" onchange="upd36()" style="padding:6px 10px;border-radius:8px;border:2px solid var(--border);background:var(--card);color:var(--text)">
|
||
<option value="water">Воздух → Вода (n=1,33)</option>
|
||
<option value="glass">Воздух → Стекло (n=1,50)</option>
|
||
<option value="diamond">Воздух → Алмаз (n=2,42)</option>
|
||
<option value="rev_water">Вода → Воздух (n=0,75)</option>
|
||
</select>
|
||
</div>
|
||
<div class="idiag-result" id="res36">$\alpha = 40°$; среда: вода (n=1,33); $\beta \approx 29°$</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §37 -->
|
||
<div class="content" id="tab-ref37">
|
||
<div class="para-hero ph-37">
|
||
<div class="ph-label">§37 · Физика 8 кл</div>
|
||
<h2>Линзы. Оптическая сила линзы</h2>
|
||
<div class="ph-formula">$D = 1/F$</div>
|
||
<div class="ph-desc">Собирающая линза: параллельные лучи сходятся в фокусе ($D > 0$). Рассеивающая: расходятся ($D < 0$). Оптическая сила $D = 1/F$ [дптр].</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">$D = 1/F$ [дптр]</span>
|
||
<span class="ph-tag">⊕ собирающая $D > 0$</span>
|
||
<span class="ph-tag">⊖ рассеивающая $D < 0$</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-circle-half-stroke"></i> §37. Линзы. Оптическая сила линзы</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Оптическая сила линзы</h3>
|
||
<div class="main-f">$D = 1/F$</div>
|
||
<p>$D$ — оптическая сила [дптр]; $F$ — фокусное расстояние [м].</p>
|
||
<p><b>Собирающая:</b> $D > 0$, $F > 0$ — параллельные лучи сходятся в фокусе.</p>
|
||
<p><b>Рассеивающая:</b> $D < 0$, $F < 0$ — параллельные лучи расходятся (продолжения сходятся в мнимом фокусе).</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Фокус и главная оптическая ось</h3>
|
||
<div class="main-f" style="font-size:.85rem">главный фокус $F$ · оптический центр $O$</div>
|
||
<p><b>Главная оптическая ось</b> — прямая через центры кривизны поверхностей.</p>
|
||
<p><b>Оптический центр $O$</b> — луч через него не меняет направления.</p>
|
||
<p><b>Фокус $F$</b> — точка, где пересекаются лучи, параллельные оси (у собирающей — действительный; у рассеивающей — мнимый).</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="idiag">
|
||
<h3>📊 Примеры оптической силы</h3>
|
||
<table style="width:100%;border-collapse:collapse;font-size:.8rem">
|
||
<thead><tr style="background:rgba(124,58,237,.08)"><th style="padding:6px 8px;border:1px solid var(--border)">Устройство</th><th style="padding:6px 8px;border:1px solid var(--border)">$D$, дптр</th><th style="padding:6px 8px;text-align:left;border:1px solid var(--border)">Применение</th></tr></thead>
|
||
<tr><td style="padding:5px 8px;border:1px solid var(--border)">Лупа</td><td style="padding:5px 8px;border:1px solid var(--border);text-align:center;font-weight:700;color:#059669">+5 … +20</td><td style="padding:5px 8px;border:1px solid var(--border)">Часовщик, исследования</td></tr>
|
||
<tr style="background:rgba(124,58,237,.03)"><td style="padding:5px 8px;border:1px solid var(--border)">Нормальный глаз</td><td style="padding:5px 8px;border:1px solid var(--border);text-align:center;font-weight:700;color:#0369a1">≈ 60</td><td style="padding:5px 8px;border:1px solid var(--border)">Роговица + хрусталик</td></tr>
|
||
<tr><td style="padding:5px 8px;border:1px solid var(--border)">Очки при близорукости</td><td style="padding:5px 8px;border:1px solid var(--border);text-align:center;font-weight:700;color:#dc2626">−1 … −6</td><td style="padding:5px 8px;border:1px solid var(--border)">Рассеивающие линзы</td></tr>
|
||
<tr style="background:rgba(124,58,237,.03)"><td style="padding:5px 8px;border:1px solid var(--border)">Очки при дальнозоркости</td><td style="padding:5px 8px;border:1px solid var(--border);text-align:center;font-weight:700;color:#059669">+1 … +4</td><td style="padding:5px 8px;border:1px solid var(--border)">Собирающие линзы</td></tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>$D = 1/F$: чем меньше $F$ — тем больше $D$ — тем сильнее линза.</li>
|
||
<li>У собирающей линзы середина <b>толще краёв</b>; у рассеивающей — тоньше.</li>
|
||
<li>Луч через оптический центр не преломляется; луч параллельно оси — через фокус.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §37</div>
|
||
<ul class="key-points-list">
|
||
<li>Оптическая сила линзы: $D = 1/F$ [дптр]; $F$ — фокусное расстояние в метрах.</li>
|
||
<li>Собирающая линза: $D > 0$, $F > 0$; середина толще краёв.</li>
|
||
<li>Рассеивающая линза: $D < 0$, $F < 0$; края толще середины.</li>
|
||
<li>Луч через оптический центр O не преломляется; луч || оси — проходит через фокус F.</li>
|
||
<li>Чем меньше $F$ — тем больше $D$ — тем сильнее линза преломляет.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Фокус и оптическая сила</div>
|
||
<div class="idiag">
|
||
<h3>🔍 Параллельные лучи через линзу</h3>
|
||
<canvas id="cv37" style="width:100%;height:240px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<div class="slider-row" style="flex:1;min-width:200px">
|
||
<span class="slider-lbl">Фокусное расстояние $F$:</span>
|
||
<input type="range" id="sl37F" min="-200" max="200" step="10" value="80" style="flex:1" oninput="lbl37F.textContent=this.value+' усл.';upd37();">
|
||
<span class="slider-val"><span id="lbl37F">80 усл.</span></span>
|
||
</div>
|
||
</div>
|
||
<div class="idiag-result" id="res37">$F = 80$ усл.; $D = 12{,}5$ дптр (собирающая)</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §38 -->
|
||
<div class="content" id="tab-ref38">
|
||
<div class="para-hero ph-38">
|
||
<div class="ph-label">§38 · Физика 8 кл</div>
|
||
<h2>Построение изображений в тонких линзах</h2>
|
||
<div class="ph-desc">$d > 2F$: действит., перевёрн., уменьш. $F < d < 2F$: действит., перевёрн., увелич. $d < F$: мнимое, прямое, увелич. (лупа). Рассеивающая — только мнимое, прямое, уменьш.</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">🔍 лупа: $d < F$</span>
|
||
<span class="ph-tag">📷 $d > 2F$: уменьш.</span>
|
||
<span class="ph-tag">✏️ два луча → изображение</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-drafting-compass"></i> §38. Построение изображений в тонких линзах</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Типы изображений в собирающей линзе</h3>
|
||
<div class="main-f" style="font-size:.78rem">два луча строят изображение</div>
|
||
<table style="width:100%;font-size:.78rem;border-collapse:collapse;margin-top:6px">
|
||
<tr style="background:rgba(124,58,237,.08)"><th style="padding:3px 5px;border:1px solid var(--border)">Положение</th><th style="padding:3px 5px;border:1px solid var(--border)">Изображение</th></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">$d > 2F$</td><td style="padding:3px 5px;border:1px solid var(--border)">действ., перевёрн., уменьш.</td></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">$d = 2F$</td><td style="padding:3px 5px;border:1px solid var(--border)">действ., перевёрн., равное</td></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">$F < d < 2F$</td><td style="padding:3px 5px;border:1px solid var(--border)">действ., перевёрн., увелич.</td></tr>
|
||
<tr><td style="padding:3px 5px;border:1px solid var(--border)">$d < F$ (лупа)</td><td style="padding:3px 5px;border:1px solid var(--border)">мнимое, прямое, увелич.</td></tr>
|
||
</table>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Два главных луча</h3>
|
||
<div class="main-f" style="font-size:.82rem">✦ параллельный → через $F$ · ✦ через $O$</div>
|
||
<p><b>Луч 1:</b> параллельно главной оси → после линзы идёт через фокус $F$.</p>
|
||
<p><b>Луч 2:</b> через оптический центр $O$ → не меняет направления.</p>
|
||
<p>Пересечение (или продолжений) этих лучей = изображение точки.</p>
|
||
<p><b>Рассеивающая</b> → всегда: мнимое, прямое, уменьшенное.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>Действительное изображение — можно спроецировать на экран (лучи реально пересекаются).</li>
|
||
<li>Мнимое — только продолжения лучей пересекаются; экраном не поймаешь, но видно в линзу.</li>
|
||
<li>Все действительные изображения — <b>перевёрнутые</b>; все мнимые — <b>прямые</b>.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §38</div>
|
||
<ul class="key-points-list">
|
||
<li>Два главных луча строят изображение: 1) || оси → через F'; 2) через оптический центр O.</li>
|
||
<li>$d > 2F$: действительное, перевёрнутое, уменьшенное (фотоаппарат, глаз).</li>
|
||
<li>$F < d < 2F$: действительное, перевёрнутое, увеличенное (проектор).</li>
|
||
<li>$d < F$: мнимое, прямое, увеличенное (лупа); $1/F = 1/d + 1/f$; $\Gamma = f/d$.</li>
|
||
<li>Рассеивающая линза — всегда мнимое, прямое, уменьшенное при любом положении предмета.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Оптический стол Pro Max (тяни предмет!)</div>
|
||
<div class="idiag">
|
||
<h3>🔬 Drag-and-drop: тяни стрелку-предмет или саму линзу — три луча и изображение строятся в реальном времени</h3>
|
||
<canvas id="cv38" style="width:100%;height:320px;border-radius:12px;background:#0f172a;cursor:grab;display:block;touch-action:none"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<div class="slider-row" style="flex:1;min-width:200px">
|
||
<span class="slider-lbl">Фокусное расстояние F:</span>
|
||
<input type="range" id="sl38F" min="30" max="120" value="70" style="flex:1" oninput="lbl38F.textContent=this.value+' усл.';upd38();">
|
||
<span class="slider-val"><span id="lbl38F">70 усл.</span></span>
|
||
</div>
|
||
<select id="sel38type" onchange="upd38()" style="padding:6px 10px;border-radius:8px;border:2px solid var(--border);background:var(--card);color:var(--text)">
|
||
<option value="conv">Собирающая линза</option>
|
||
<option value="div">Рассеивающая линза</option>
|
||
</select>
|
||
<label style="font-size:.82rem;display:flex;align-items:center;gap:6px;cursor:pointer">
|
||
<input type="checkbox" id="chk38r3" checked onchange="upd38()"> Луч 3 (через F)
|
||
</label>
|
||
<button class="btn btn-ghost" type="button" onclick="reset38()" style="padding:6px 14px;font-size:.78rem">🔄 Сброс</button>
|
||
</div>
|
||
<div style="margin-top:8px;display:flex;flex-wrap:wrap;gap:8px;align-items:center">
|
||
<span class="val-chip" id="chip38lens">1/F = 1/d + 1/f</span>
|
||
<span class="val-chip" id="chip38mag" style="background:rgba(34,197,94,.12);color:#16a34a;border-color:rgba(34,197,94,.3)">Γ = h'/h = 1.00</span>
|
||
<span class="val-chip" id="chip38type" style="background:rgba(249,115,22,.12);color:#c2410c;border-color:rgba(249,115,22,.3)">действ., перевёрн.</span>
|
||
</div>
|
||
<div style="margin-top:8px">
|
||
<div class="slider-row">
|
||
<span class="slider-lbl">Положение предмета d:</span>
|
||
<input type="range" id="sl38d" min="15" max="280" value="160" style="flex:1" oninput="lbl38d.textContent=this.value+' усл.';upd38();">
|
||
<span class="slider-val"><span id="lbl38d">160 усл.</span></span>
|
||
</div>
|
||
</div>
|
||
<div class="cv-cap"><i class="fas fa-hand-pointer"></i> Тяни мышью: за стрелку-предмет — двигаешь d; за линзу — двигаешь её по оси (изменяется d). Слайдер F меняет фокус. Луч 1 || оси → через F'. Луч 2 → через оптический центр. Луч 3 → через F → || оси.</div>
|
||
<div class="idiag-result" id="res38">Перемести предмет слайдером ↓ или потяни за объект на canvas</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §39 -->
|
||
<div class="content" id="tab-ref39">
|
||
<div class="para-hero ph-39">
|
||
<div class="ph-label">§39 · Физика 8 кл</div>
|
||
<h2>Глаз как оптическая система</h2>
|
||
<div class="ph-desc">Роговица + хрусталик = собирающая система. Аккомодация: хрусталик меняет кривизну → фокусирует на сетчатку. Расстояние наилучшего видения 25 см.</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">👁️ сетчатка = экран</span>
|
||
<span class="ph-tag">⚙️ аккомодация</span>
|
||
<span class="ph-tag">📏 $d_{\text{набл}} = 25$ см</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-eye"></i> §39. Глаз как оптическая система</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Строение глаза</h3>
|
||
<div class="main-f" style="font-size:.82rem">роговица · хрусталик · сетчатка</div>
|
||
<p><b>Роговица</b> + хрусталик + стекловидное тело = собирающая линза ($D \approx 60$ дптр).</p>
|
||
<p><b>Сетчатка</b> — «экран»: на ней образуется действительное, перевёрнутое, уменьшенное изображение.</p>
|
||
<p><b>Зрачок</b> — регулирует количество света, поступающего в глаз.</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Аккомодация глаза</h3>
|
||
<div class="main-f" style="font-size:.85rem">хрусталик меняет кривизну → меняет $F$</div>
|
||
<p>Мышцы глаза изменяют форму хрусталика:</p>
|
||
<ul style="font-size:.83rem;color:var(--muted);padding-left:16px;line-height:1.9;margin-top:4px">
|
||
<li><b>Близкий предмет</b>: хрусталик выпуклее → $F$↓ → $D$↑</li>
|
||
<li><b>Далёкий предмет</b>: хрусталик уплощается → $F$↑ → $D$↓</li>
|
||
</ul>
|
||
<p>Расстояние наилучшего видения: <b>25 см</b> (при котором глаз работает без напряжения).</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="idiag">
|
||
<h3>👁 Схема строения глаза</h3>
|
||
<svg width="100%" viewBox="0 0 300 140" style="display:block">
|
||
<!-- Глазное яблоко -->
|
||
<ellipse cx="170" cy="70" rx="65" ry="55" fill="rgba(255,240,220,0.08)" stroke="#a78bfa" stroke-width="2"/>
|
||
<!-- Склера -->
|
||
<ellipse cx="170" cy="70" rx="65" ry="55" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="3,3"/>
|
||
<!-- Роговица -->
|
||
<path d="M108,55 Q95,70 108,85" stroke="#38bdf8" stroke-width="3" fill="none"/>
|
||
<text x="82" y="48" font-size="7.5" fill="#38bdf8" font-family="sans-serif">роговица</text>
|
||
<!-- Зрачок/радужка -->
|
||
<circle cx="118" cy="70" r="12" fill="rgba(59,130,246,0.2)" stroke="#3b82f6" stroke-width="1.5"/>
|
||
<circle cx="118" cy="70" r="5" fill="#1e293b" stroke="#0369a1" stroke-width="1"/>
|
||
<text x="100" y="97" font-size="7" fill="#94a3b8" font-family="sans-serif">зрачок</text>
|
||
<!-- Хрусталик -->
|
||
<path d="M128,55 Q145,70 128,85" stroke="#fbbf24" stroke-width="3" fill="rgba(251,191,36,0.1)"/>
|
||
<path d="M132,55 Q118,70 132,85" stroke="#fbbf24" stroke-width="2" fill="none"/>
|
||
<text x="130" y="48" font-size="7.5" fill="#fbbf24" font-family="sans-serif">хрусталик</text>
|
||
<!-- Стекловидное тело -->
|
||
<text x="170" y="75" text-anchor="middle" font-size="7" fill="rgba(148,163,184,0.6)" font-family="sans-serif">стекл. тело</text>
|
||
<!-- Сетчатка -->
|
||
<path d="M220,35 Q240,70 220,105" stroke="#22c55e" stroke-width="3" fill="none"/>
|
||
<text x="240" y="60" font-size="7.5" fill="#22c55e" font-family="sans-serif">сетчатка</text>
|
||
<!-- Зрительный нерв -->
|
||
<line x1="234" y1="70" x2="255" y2="70" stroke="#94a3b8" stroke-width="2"/>
|
||
<text x="260" y="74" font-size="7" fill="#94a3b8" font-family="sans-serif">нерв</text>
|
||
<!-- Лучи -->
|
||
<line x1="20" y1="50" x2="108" y2="55" stroke="rgba(251,191,36,0.5)" stroke-width="1.5"/>
|
||
<line x1="20" y1="90" x2="108" y2="85" stroke="rgba(251,191,36,0.5)" stroke-width="1.5"/>
|
||
<!-- После преломления → к сетчатке -->
|
||
<line x1="132" y1="57" x2="225" y2="85" stroke="rgba(59,130,246,0.6)" stroke-width="1.5"/>
|
||
<line x1="132" y1="83" x2="225" y2="55" stroke="rgba(59,130,246,0.6)" stroke-width="1.5"/>
|
||
<!-- Предмет -->
|
||
<line x1="20" y1="40" x2="20" y2="100" stroke="#fbbf24" stroke-width="2.5"/>
|
||
<polygon points="20,38 16,50 24,50" fill="#fbbf24"/>
|
||
<text x="12" y="115" font-size="7.5" fill="#fbbf24" font-family="sans-serif">предмет</text>
|
||
<!-- Изображение на сетчатке -->
|
||
<text x="218" y="30" font-size="7" fill="#22c55e" font-family="sans-serif">изображение</text>
|
||
<text x="218" y="40" font-size="7" fill="#22c55e" font-family="sans-serif">(перевёрнутое)</text>
|
||
</svg>
|
||
</div>
|
||
|
||
<div class="insight-box">
|
||
<div class="insight-title"><i class="fas fa-lightbulb"></i> Мозг «видит», а не глаз!</div>
|
||
<p>На сетчатке образуется перевёрнутое изображение — но мы всё видим «правильно». Это потому что <b>мозг</b> обрабатывает сигналы и строит зрительный образ. Новорождённые поначалу видят мир перевёрнутым — мозгу нужно время, чтобы «научиться» правильно интерпретировать сигналы.</p>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li>Глаз = короткофокусная собирающая линза $D \approx 60$ дптр.</li>
|
||
<li>Изображение на сетчатке: действительное, перевёрнутое, уменьшенное.</li>
|
||
<li>Аккомодация позволяет видеть чётко на разных расстояниях (25 см … ∞).</li>
|
||
<li>Чтение при плохом освещении и с близкого расстояния утомляет хрусталик!</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §39</div>
|
||
<ul class="key-points-list">
|
||
<li>Оптическая система глаза: роговица + хрусталик ≈ собирающая линза $D \approx 60$ дптр.</li>
|
||
<li>На сетчатке образуется действительное, перевёрнутое, уменьшенное изображение.</li>
|
||
<li>Аккомодация: хрусталик меняет кривизну → изменяет $F$ → фокусирует предметы с разных расстояний.</li>
|
||
<li>Расстояние наилучшего видения: 25 см — при нём глаз работает без напряжения.</li>
|
||
<li>Мозг «видит», а не глаз: мозг переворачивает перевёрнутое изображение сетчатки.</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Аккомодация глаза</div>
|
||
<div class="idiag">
|
||
<h3>👁 Меняй расстояние — хрусталик меняет форму</h3>
|
||
<canvas id="cv39" style="width:100%;height:240px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<div class="slider-row" style="flex:1;min-width:200px">
|
||
<span class="slider-lbl">Расстояние до предмета:</span>
|
||
<input type="range" id="sl39d" min="15" max="200" value="50" style="flex:1" oninput="lbl39d.textContent=this.value+' см';upd39();">
|
||
<span class="slider-val"><span id="lbl39d">50 см</span></span>
|
||
</div>
|
||
</div>
|
||
<div class="idiag-result" id="res39">Предмет на 50 см: хрусталик слегка выпуклый</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- §40 -->
|
||
<div class="content" id="tab-ref40">
|
||
<div class="para-hero ph-40">
|
||
<div class="ph-label">§40 · Физика 8 кл</div>
|
||
<h2>Дефекты зрения. Очки</h2>
|
||
<div class="ph-desc">Близорукость: фокус перед сетчаткой → рассеивающие очки ($D < 0$). Дальнозоркость: фокус за сетчаткой → собирающие очки ($D > 0$).</div>
|
||
<div class="ph-tags">
|
||
<span class="ph-tag">👓 близорукость → $D < 0$</span>
|
||
<span class="ph-tag">🔍 дальнозоркость → $D > 0$</span>
|
||
<span class="ph-tag">🎯 лазерная коррекция</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-glasses"></i> §40. Дефекты зрения. Очки</div>
|
||
|
||
<div class="formula-grid">
|
||
<div class="fcard highlight">
|
||
<h3>Близорукость (миопия)</h3>
|
||
<div class="main-f" style="font-size:.85rem">фокус перед сетчаткой → рассеивающие очки $D < 0$</div>
|
||
<p>Причина: глазное яблоко вытянуто или хрусталик слишком сильно преломляет.</p>
|
||
<p>Дальние предметы — размыто. Ближние — чётко.</p>
|
||
<p><b>Коррекция:</b> рассеивающие линзы ($D < 0$) сдвигают фокус назад — на сетчатку.</p>
|
||
</div>
|
||
<div class="fcard">
|
||
<h3>Дальнозоркость (гиперметропия)</h3>
|
||
<div class="main-f" style="font-size:.85rem">фокус за сетчаткой → собирающие очки $D > 0$</div>
|
||
<p>Причина: хрусталик потерял эластичность (у пожилых) или глаз укороченный.</p>
|
||
<p>Ближние предметы — размыто. Дальние — лучше.</p>
|
||
<p><b>Коррекция:</b> собирающие линзы ($D > 0$) сдвигают фокус вперёд — на сетчатку.</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="idiag">
|
||
<h3>📊 Как читать рецепт на очки</h3>
|
||
<table style="width:100%;border-collapse:collapse;font-size:.8rem">
|
||
<thead><tr style="background:rgba(124,58,237,.08)"><th style="padding:6px 8px;border:1px solid var(--border)">Запись в рецепте</th><th style="padding:6px 8px;border:1px solid var(--border)">Тип линз</th><th style="padding:6px 8px;border:1px solid var(--border)">Дефект</th><th style="padding:6px 8px;border:1px solid var(--border)">$F$ линз</th></tr></thead>
|
||
<tr><td style="padding:5px 8px;border:1px solid var(--border)">−2,0 дптр</td><td style="padding:5px 8px;border:1px solid var(--border);color:#dc2626;font-weight:700">рассеивающие</td><td style="padding:5px 8px;border:1px solid var(--border)">близорукость</td><td style="padding:5px 8px;border:1px solid var(--border)">−50 см</td></tr>
|
||
<tr style="background:rgba(124,58,237,.03)"><td style="padding:5px 8px;border:1px solid var(--border)">+2,5 дптр</td><td style="padding:5px 8px;border:1px solid var(--border);color:#059669;font-weight:700">собирающие</td><td style="padding:5px 8px;border:1px solid var(--border)">дальнозоркость</td><td style="padding:5px 8px;border:1px solid var(--border)">+40 см</td></tr>
|
||
<tr><td style="padding:5px 8px;border:1px solid var(--border)">−5,0 дптр</td><td style="padding:5px 8px;border:1px solid var(--border);color:#dc2626;font-weight:700">рассеивающие</td><td style="padding:5px 8px;border:1px solid var(--border)">сильная близор.</td><td style="padding:5px 8px;border:1px solid var(--border)">−20 см</td></tr>
|
||
<tr style="background:rgba(124,58,237,.03)"><td style="padding:5px 8px;border:1px solid var(--border)">+1,0 дптр</td><td style="padding:5px 8px;border:1px solid var(--border);color:#059669;font-weight:700">собирающие</td><td style="padding:5px 8px;border:1px solid var(--border)">слаб. дальнозорк.</td><td style="padding:5px 8px;border:1px solid var(--border)">+100 см</td></tr>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="insight-box">
|
||
<div class="insight-title"><i class="fas fa-lightbulb"></i> Как определить дефект без прибора</div>
|
||
<p>Возьмите очки и поднесите к строчке текста: <b>собирающие (дальнозоркость)</b> — буквы увеличатся; <b>рассеивающие (близорукость)</b> — уменьшатся. Или поднесите к источнику света — собирающие дают яркое пятно (фокус), рассеивающие — нет.</p>
|
||
</div>
|
||
|
||
<div class="life-grid">
|
||
<div class="life-item"><div class="li-icon">📱</div><div class="li-title">Смартфон и близорукость</div><div class="li-desc">Длительное чтение с малого расстояния → постоянное напряжение хрусталика → близорукость у детей</div></div>
|
||
<div class="life-item"><div class="li-icon">👴</div><div class="li-title">Старческая дальнозоркость</div><div class="li-desc">После 40 лет хрусталик теряет эластичность → не может стать достаточно выпуклым для чтения</div></div>
|
||
<div class="life-item"><div class="li-icon">🔬</div><div class="li-title">Лазерная коррекция</div><div class="li-desc">Лазером изменяют кривизну роговицы → меняют оптическую силу → коррекция без очков</div></div>
|
||
<div class="life-item"><div class="li-icon">💎</div><div class="li-title">Контактные линзы</div><div class="li-desc">Тонкая линза прямо на роговице — полная свобода от очков, широкое поле зрения</div></div>
|
||
</div>
|
||
|
||
<div class="remember-box">
|
||
<div class="remember-box-title"><i class="fas fa-exclamation-circle"></i> Запомни!</div>
|
||
<ul>
|
||
<li><b>Близорукость</b>: $D < 0$ (−) → рассеивающие. Фокус перед сетчаткой.</li>
|
||
<li><b>Дальнозоркость</b>: $D > 0$ (+) → собирающие. Фокус за сетчаткой.</li>
|
||
<li>$F = 1/D$ [м] — фокусное расстояние линз очков.</li>
|
||
<li>Близорукий может в старости обрести нормальное зрение: потеря упругости хрусталика компенсирует его изначальную «выпуклость».</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="key-points">
|
||
<div class="key-points-title">🔑 Главное в §40</div>
|
||
<ul class="key-points-list">
|
||
<li>Близорукость: фокус перед сетчаткой → дальние предметы размыты → рассеивающие очки ($D < 0$).</li>
|
||
<li>Дальнозоркость: фокус за сетчаткой → ближние предметы размыты → собирающие очки ($D > 0$).</li>
|
||
<li>$F = 1/D$ [м] — фокусное расстояние линз очков; знак определяет тип коррекции.</li>
|
||
<li>Лазерная коррекция: лазер меняет кривизну роговицы — навсегда исправляет оптическую силу.</li>
|
||
<li>Рассеивающие линзы уменьшают видимые предметы; собирающие — увеличивают (тест без прибора).</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="section-title"><i class="fas fa-play-circle"></i> Интерактив — Дефекты зрения и коррекция</div>
|
||
<div class="idiag">
|
||
<h3>👓 Выбери дефект — надень очки — наблюдай исправление</h3>
|
||
<canvas id="cv40" style="width:100%;height:260px;border-radius:12px;background:#0f172a;display:block"></canvas>
|
||
<div class="ctrl-row" style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px;align-items:center">
|
||
<select id="sel40def" onchange="upd40()" style="padding:6px 10px;border-radius:8px;border:2px solid var(--border);background:var(--card);color:var(--text)">
|
||
<option value="normal">Нормальное зрение</option>
|
||
<option value="myopia">Близорукость (миопия)</option>
|
||
<option value="hyperopia">Дальнозоркость (гиперметропия)</option>
|
||
</select>
|
||
<label style="font-size:.82rem;display:flex;align-items:center;gap:7px;cursor:pointer">
|
||
<input type="checkbox" id="chk40glasses" onchange="upd40()"> 👓 Надеть очки
|
||
</label>
|
||
<div class="slider-row" style="flex:1;min-width:180px">
|
||
<span class="slider-lbl">D очков:</span>
|
||
<input type="range" id="sl40D" min="-6" max="6" step="0.5" value="-2" style="flex:1" oninput="lbl40D.textContent=(+this.value>0?'+':'')+this.value+' дптр';upd40();">
|
||
<span class="slider-val"><span id="lbl40D">-2 дптр</span></span>
|
||
</div>
|
||
</div>
|
||
<div class="idiag-result" id="res40">Нормальное зрение: лучи фокусируются точно на сетчатку</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ЗАДАЧИ -->
|
||
<div class="content" id="tab-tasks">
|
||
<div class="para-pills">
|
||
<button class="para-pill active" data-para="p32" onclick="setParaTab('p32')">§32 Источники</button>
|
||
<button class="para-pill" data-para="p33" onclick="setParaTab('p33')">§33 Скорость света</button>
|
||
<button class="para-pill" data-para="p34" onclick="setParaTab('p34')">§34 Отражение</button>
|
||
<button class="para-pill" data-para="p35" onclick="setParaTab('p35')">§35 Зеркала</button>
|
||
<button class="para-pill" data-para="p36" onclick="setParaTab('p36')">§36 Преломление</button>
|
||
<button class="para-pill" data-para="p37" onclick="setParaTab('p37')">§37 Линзы</button>
|
||
<button class="para-pill" data-para="p38" onclick="setParaTab('p38')">§38 Изображения</button>
|
||
<button class="para-pill" data-para="p39" onclick="setParaTab('p39')">§39 Глаз</button>
|
||
<button class="para-pill" data-para="p40" onclick="setParaTab('p40')">§40 Дефекты зрения</button>
|
||
<button class="para-pill" data-para="hard" onclick="setParaTab('hard')">⚡ Сложные</button>
|
||
</div>
|
||
|
||
<!-- ptab-p32 -->
|
||
<div id="ptab-p32">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp32">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp32">0</span> / <span id="maxp32">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p32')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp32" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp32"></div>
|
||
<div id="taskAreap32"></div>
|
||
<div class="feedback" id="fbp32"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp32" onclick="nextTask('p32')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump32">
|
||
<h2>§32 — готово!</h2>
|
||
<div class="big-score" id="sumScorep32">0/5</div>
|
||
<div class="sum-grade" id="sumGradep32"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p32')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p33')">→ §33</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p33 -->
|
||
<div id="ptab-p33">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp33">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp33">0</span> / <span id="maxp33">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p33')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp33" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp33"></div>
|
||
<div id="taskAreap33"></div>
|
||
<div class="feedback" id="fbp33"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp33" onclick="nextTask('p33')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump33">
|
||
<h2>§33 — готово!</h2>
|
||
<div class="big-score" id="sumScorep33">0/5</div>
|
||
<div class="sum-grade" id="sumGradep33"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p33')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p34')">→ §34</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p34 -->
|
||
<div id="ptab-p34">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp34">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp34">0</span> / <span id="maxp34">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p34')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp34" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp34"></div>
|
||
<div id="taskAreap34"></div>
|
||
<div class="feedback" id="fbp34"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp34" onclick="nextTask('p34')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump34">
|
||
<h2>§34 — готово!</h2>
|
||
<div class="big-score" id="sumScorep34">0/8</div>
|
||
<div class="sum-grade" id="sumGradep34"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p34')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p35')">→ §35</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p35 -->
|
||
<div id="ptab-p35">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp35">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp35">0</span> / <span id="maxp35">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p35')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp35" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp35"></div>
|
||
<div id="taskAreap35"></div>
|
||
<div class="feedback" id="fbp35"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp35" onclick="nextTask('p35')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump35">
|
||
<h2>§35 — готово!</h2>
|
||
<div class="big-score" id="sumScorep35">0/6</div>
|
||
<div class="sum-grade" id="sumGradep35"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p35')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p36')">→ §36</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p36 -->
|
||
<div id="ptab-p36">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp36">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp36">0</span> / <span id="maxp36">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p36')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp36" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp36"></div>
|
||
<div id="taskAreap36"></div>
|
||
<div class="feedback" id="fbp36"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp36" onclick="nextTask('p36')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump36">
|
||
<h2>§36 — готово!</h2>
|
||
<div class="big-score" id="sumScorep36">0/7</div>
|
||
<div class="sum-grade" id="sumGradep36"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p36')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p37')">→ §37</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p37 -->
|
||
<div id="ptab-p37">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp37">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp37">0</span> / <span id="maxp37">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p37')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp37" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp37"></div>
|
||
<div id="taskAreap37"></div>
|
||
<div class="feedback" id="fbp37"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp37" onclick="nextTask('p37')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump37">
|
||
<h2>§37 — готово!</h2>
|
||
<div class="big-score" id="sumScorep37">0/5</div>
|
||
<div class="sum-grade" id="sumGradep37"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p37')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p38')">→ §38</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p38 -->
|
||
<div id="ptab-p38">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp38">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp38">0</span> / <span id="maxp38">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p38')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp38" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp38"></div>
|
||
<div id="taskAreap38"></div>
|
||
<div class="feedback" id="fbp38"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp38" onclick="nextTask('p38')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump38">
|
||
<h2>§38 — готово!</h2>
|
||
<div class="big-score" id="sumScorep38">0/6</div>
|
||
<div class="sum-grade" id="sumGradep38"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p38')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p39')">→ §39</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p39 -->
|
||
<div id="ptab-p39">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp39">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp39">0</span> / <span id="maxp39">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p39')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp39" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp39"></div>
|
||
<div id="taskAreap39"></div>
|
||
<div class="feedback" id="fbp39"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp39" onclick="nextTask('p39')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump39">
|
||
<h2>§39 — готово!</h2>
|
||
<div class="big-score" id="sumScorep39">0/4</div>
|
||
<div class="sum-grade" id="sumGradep39"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p39')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('p40')">→ §40</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-p40 -->
|
||
<div id="ptab-p40">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okp40">0</span></div>
|
||
<div class="chip chip-tot"><span id="curp40">0</span> / <span id="maxp40">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('p40')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="progp40" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotsp40"></div>
|
||
<div id="taskAreap40"></div>
|
||
<div class="feedback" id="fbp40"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnp40" onclick="nextTask('p40')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sump40">
|
||
<h2>§40 — готово!</h2>
|
||
<div class="big-score" id="sumScorep40">0/5</div>
|
||
<div class="sum-grade" id="sumGradep40"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('p40')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
<button class="btn btn-ghost" onclick="setParaTab('hard')">→ ⚡ Сложные</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ptab-hard -->
|
||
<div id="ptab-hard">
|
||
<div class="score-bar">
|
||
<div class="chip chip-ok"><i class="fas fa-check"></i> <span id="okhard">0</span></div>
|
||
<div class="chip chip-tot"><span id="curhard">0</span> / <span id="maxhard">0</span></div>
|
||
<button class="btn btn-ghost" onclick="resetTasks('hard')" style="padding:6px 13px;font-size:.74rem"><i class="fas fa-rotate-right"></i> Заново</button>
|
||
</div>
|
||
<div class="prog-wrap"><div class="prog-fill" id="proghard" style="width:0%"></div></div>
|
||
<div class="nav-dots" id="navDotshard"></div>
|
||
<div id="taskAreahard"></div>
|
||
<div class="feedback" id="fbhard"></div>
|
||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||
<button class="btn btn-next" id="nextBtnhard" onclick="nextTask('hard')" style="display:none"><i class="fas fa-arrow-right"></i> Следующее</button>
|
||
</div>
|
||
<div class="summary" id="sumhard">
|
||
<h2>Сложные — готово!</h2>
|
||
<div class="big-score" id="sumScorehard">0/7</div>
|
||
<div class="sum-grade" id="sumGradehard"></div>
|
||
<div class="sum-btns">
|
||
<button class="btn btn-pri" onclick="resetTasks('hard')"><i class="fas fa-rotate-right"></i> Ещё раз</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div><!-- /tab-tasks -->
|
||
</div><!-- /content-area -->
|
||
</main>
|
||
</div><!-- /page-wrap -->
|
||
|
||
<script>
|
||
// ═══════════════════════════════════════
|
||
// ДАННЫЕ ЗАДАЧ
|
||
// ═══════════════════════════════════════
|
||
var TASKS_P32 = [
|
||
{q:"Что такое источник света?",opts:["Любое тело","Тело, само излучающее свет (не отражённый)","Зеркало, отражающее лучи","Тело, поглощающее весь свет"],a:1,ex:"Источник света — тело, которое САМО излучает свет. Луна, книга, стена — не источники (они отражают свет Солнца или ламп)."},
|
||
{q:"Какие из перечисленных источников являются тепловыми?",opts:["Светлячок, северное сияние","Лампа накаливания, Солнце, пламя свечи","Флуоресцентная краска, лазер","Гнилая древесина, флюоресцеин"],a:1,ex:"Тепловые источники: нагреваются до высокой температуры и начинают светиться (Солнце, лампа накаливания, свеча). Нетепловые светятся за счёт химических реакций или флуоресценции."},
|
||
{q:"В каком случае источник света можно считать точечным?",opts:["Всегда, если он маленький","Когда его размерами в конкретных условиях задачи можно пренебречь","Только если это звезда","Когда он находится далеко от экрана"],a:1,ex:"Понятие точечного источника — это упрощение. Звезды — точечные источники для нас (очень далеко). Лампа — точечный для большого экрана, но не для ближнего листа бумаги."},
|
||
{q:"Что такое луч света?",opts:["Пучок параллельных волн","Линия, вдоль которой распространяется свет","Световая волна между двумя телами","Полоса освещённости"],a:1,ex:"Луч — это линия, вдоль которой распространяется световая энергия. Реально получить идеальный луч (с нулевым поперечным сечением) невозможно, но малое отверстие даёт хорошее приближение."},
|
||
{q:"Большинство окружающих нас тел мы видим благодаря...",opts:["Собственному свечению тел","Отражённому от них свету","Теплу, которое они излучают","Магнитному полю"],a:1,ex:"Луна, книга, деревья, люди — сами не светятся. Мы их видим потому, что они отражают свет Солнца или ламп. Только тела-источники (лампы, экраны) мы видим благодаря их собственному свету."}
|
||
];
|
||
|
||
var TASKS_P33 = [
|
||
{q:"Можно ли имея точечный источник, экран и непрозрачный предмет получить только тень (без полутени)?",opts:["Нет, всегда будет полутень","Да — от точечного источника образуется только тень, без полутени","Только если экран очень близко","Только при маленьком предмете"],a:1,ex:"От точечного источника — только тень (чётко очерченная). Полутень образуется только от протяжённого источника (два и более точечных источника или большой источник)."},
|
||
{q:"Сколько времени идёт свет от Солнца до Земли? Расстояние $l = 1{,}49 \\times 10^8$ км. $c = 3 \\times 10^8$ м/с.",hint:"$t = l/c$; перевести км → м",unit:"с",a:497,ex:"$l = 1{,}49 \\times 10^{11}$ м; $t = 1{,}49 \\times 10^{11} / 3 \\times 10^8 \\approx 497$ с $\\approx 8{,}3$ мин"},
|
||
{q:"Почему астрономы говорят: «Мы изучаем прошлое звёзд»?",opts:["Потому что звёзды очень старые","Свет от далёких звёзд летит миллионы лет: мы видим не нынешнее состояние, а то, каким оно было в момент излучения","Потому что телескопы дают перевёрнутое изображение","Звёзды уже погасли, мы видим их историю в записях"],a:1,ex:"Расстояние до ближайших звёзд — световые годы. Свет от звезды летит к нам миллионы лет. Глядя на звезду, мы видим её состояние миллионы лет назад — это буквальное «путешествие в прошлое»."},
|
||
{q:"На какой высоте над поверхностью воды в бассейне глубиной $h = 3{,}9$ м нужно повесить лампочку, чтобы свет шёл в воде и воздухе одинаковое время? $v_\\text{воды} = 2{,}25 \\times 10^8$ м/с.",hint:"$t = h/v_\\text{воды} = h_\\text{возд}/c$; $h_\\text{возд} = h \\cdot c/v_\\text{воды}$",unit:"м",a:5.2,ex:"$t_\\text{воды} = 3{,}9 / 2{,}25 \\times 10^8$; $h_\\text{возд} = 3{,}9 \\times 3/2{,}25 = 5{,}2$ м"},
|
||
{q:"Почему руки хирурга, освещаемые сверху несколькими светильниками, не дают на «операционном поле» тень?",opts:["Потому что хирург держит руки высоко","Несколько источников со стороны дают перекрывающиеся тени — в зоне операции нет полной тени (только полутени от каждого)","Хирурги носят перчатки, которые прозрачны для хирургических ламп","Операционные лампы — лазерные и не дают теней"],a:1,ex:"Несколько источников с разных сторон — тени от каждого перекрываются. В «операционном поле» остаётся зона полутени (частично освещается от другого светильника). Полная тень не образуется."}
|
||
];
|
||
|
||
var TASKS_P34 = [
|
||
{q:"Под каким углом отражается луч, упавший перпендикулярно на зеркало? А упавший под углом $\\varphi = 60°$ к поверхности зеркала?",opts:["0° и 60°","0° и 30° (угол к нормали, а не к поверхности)","90° и 60°","0° и 90°"],a:1,ex:"При $\\alpha = 0°$ (перпендикулярно) → $\\gamma = 0°$ (луч уходит обратно). При $\\varphi = 60°$ к поверхности → $\\alpha = 90° - 60° = 30°$ к нормали → $\\gamma = 30°$."},
|
||
{q:"Почему поверхность классной доски должна быть матовой?",opts:["Матовая поверхность прочнее","Матовая поверхность даёт диффузное отражение → её видно с любого места в классе","Зеркальная доска была бы слишком яркой","Из матового материала дешевле делать"],a:1,ex:"Зеркальная доска отражает свет лишь в одном направлении — с большинства мест в классе её не видно. Матовая (диффузная) отражает во все стороны → видна с любой позиции."},
|
||
{q:"Зеркально или диффузно отражает свет поверхность Луны?",opts:["Зеркально — она блестит как зеркало","Диффузно — её видно с любой стороны Земли в ночном небе","Луна сама светится, не отражает","Зависит от фазы Луны"],a:1,ex:"Луна видна из любой точки Земли — это признак диффузного отражения. Если бы Луна отражала зеркально, её можно было бы видеть только в одном месте (как блик на воде)."},
|
||
{q:"Луч падающий и отражённый образуют угол $\\varphi = 70°$. Чему равен угол падения?",hint:"Угол между падающим и отражённым = $\\alpha + \\gamma = 2\\alpha$",unit:"°",a:35,ex:"$\\varphi = \\alpha + \\gamma = 2\\alpha = 70°$; $\\alpha = 35°$."},
|
||
{q:"Солнечные лучи образуют с горизонтом угол $\\varphi = 38°$. Как расположить зеркало, чтобы осветить дно колодца? Под каким углом к горизонту?",hint:"$\\sigma = (90° - \\varphi)/2 = (90° - 38°)/2$",unit:"°",a:26,ex:"Нормаль к зеркалу — биссектриса угла между падающим ($52°$ к нормали горизонта) и вертикалью вниз ($0°$). $\\sigma = (90° - 38°)/2 = 26°$ к горизонту."},
|
||
{q:"На какой угол повернётся отражённый луч, если зеркало повернуть на $\\varphi = 10°$ (направление падающего луча не меняется)?",hint:"Отражённый луч поворачивается на $2\\varphi$",unit:"°",a:20,ex:"При повороте зеркала на $\\varphi$ нормаль поворачивается на $\\varphi$, следовательно, отражённый луч поворачивается на $2\\varphi = 20°$."},
|
||
{q:"Почему отражение Луны на поверхности озера, покрытого рябью, кажется удлинённым?",opts:["Луна имеет вытянутую форму","Рябь создаёт наклонные зеркальные поверхности, каждая из которых отражает луч под разным углом — в глаз попадают лучи из широкой полосы","Водяные волны усиливают свет","Это иллюзия из-за расстояния"],a:1,ex:"На спокойной воде лишь малый участок зеркально отражает Луну в глаз. На ряби — множество наклонных поверхностей с разными углами, каждая отражает луч в глаз — в итоге полоса бликов."},
|
||
{q:"Угол между падающим и отражённым лучами $\\delta = 30°$. Каким станет угол отражения, если угол падения увеличится на $\\varphi = 5°$?",hint:"Исходно $2\\alpha = \\delta$; новый $\\alpha' = \\alpha + \\varphi$; новый $\\delta' = 2\\alpha'$",unit:"°",a:20,ex:"$\\alpha = 15°$; $\\alpha' = 20°$; $\\delta' = 2 \\times 20° = 40°$."}
|
||
];
|
||
|
||
var TASKS_P35 = [
|
||
{q:"Почему изображение предмета в плоском зеркале называют мнимым?",opts:["Потому что мы его придумываем","Оно образуется пересечением не самих лучей, а их продолжений — в точку за зеркалом свет не попадает","Оно размытое и нечёткое","Его видно только под определённым углом"],a:1,ex:"Мнимое изображение образуется продолжениями отражённых лучей (за зеркалом). Реальные лучи за зеркало не проходят — световой энергии там нет. Фотоплёнка, помещённая в точку изображения, ничего не запишет."},
|
||
{q:"Картина висит на стене перед плоским зеркалом на расстоянии $l = 3{,}0$ м. Чему равно расстояние между картиной и её изображением?",hint:"Изображение находится за зеркалом на $l = 3{,}0$ м; расстояние = $2l$",unit:"м",a:6.0,ex:"Изображение в зеркале — на расстоянии $l = 3{,}0$ м за зеркалом. Расстояние картина → изображение = $l + l = 6{,}0$ м."},
|
||
{q:"Расстояние между свечой и её изображением в зеркале увеличилось на $\\Delta l = 40$ см. На сколько и в каком направлении передвинули свечу?",hint:"$l_\\text{свеча-изображение} = 2l$; если увеличилось на 40 → свеча отдалилась на $40/2$",unit:"см",a:20,ex:"$\\Delta(2l) = 40$ см → $\\Delta l = 20$ см. Свечу отдвинули от зеркала на 20 см."},
|
||
{q:"Плоское зеркало приблизили к свече на $\\Delta l = 15$ см. На сколько и как изменилось расстояние между свечой и её изображением?",hint:"При сближении зеркала на $\\Delta l$, расстояние меняется на $2\\Delta l$",unit:"см",a:30,ex:"Зеркало приближается к свече на 15 см → изображение тоже приближается на 15 см. Суммарное расстояние уменьшается на $2 \\times 15 = 30$ см."},
|
||
{q:"Мальчик движется к зеркалу со скоростью $v = 2{,}0$ м/с. С какой скоростью он приближается к своему изображению?",hint:"Изображение тоже движется к зеркалу с той же скоростью → скорость сближения = $2v$",unit:"м/с",a:4.0,ex:"Изображение удалено от зеркала на $l$. Мальчик идёт к зеркалу: $l$ уменьшается с v=2. Изображение приближается с той же v=2. Скорость сближения мальчик–изображение = $2v = 4{,}0$ м/с."},
|
||
{q:"Почему в изображении предмета в плоском зеркале правое и левое меняются местами, а верх и низ — нет?",opts:["Это иллюзия","Зеркало переворачивает только по одной оси: поворот вокруг вертикальной оси меняет лево/право, но не верх/низ","Зеркало тяжёлое снизу","Так устроен наш глаз"],a:1,ex:"Плоское зеркало делает мнимое изображение симметричным — разворот на 180° вокруг зеркальной плоскости. При стандартном расположении (вертикальное зеркало) — ось симметрии вертикальна → лево/право меняется, верх/низ — нет."}
|
||
];
|
||
|
||
var TASKS_P36 = [
|
||
{q:"Какое явление происходит со световым лучом на границе раздела двух сред?",opts:["Только отражение","Только преломление","Частично отражается, частично преломляется (меняет направление при переходе)","Луч полностью поглощается"],a:2,ex:"На границе раздела сред всегда происходит и отражение, и преломление. При $\\alpha = 0°$ нет преломления, но есть частичное отражение. В быту мы видим оба эффекта: например, в оконном стекле одновременно отражение и прозрачность."},
|
||
{q:"Луч из воздуха падает на воду, стекло и алмаз под одним углом. В какой среде угол преломления наибольший?",opts:["В воде (наименее плотная из трёх)","В алмазе (наиболее плотный)","В стекле (средняя плотность)","Одинаковый во всех"],a:0,ex:"Чем оптически плотнее среда → тем меньше угол преломления $\\beta$. Вода — наименее плотная из трёх → $\\beta$ наибольший. Алмаз — наиболее плотный → $\\beta$ наименьший."},
|
||
{q:"Почему ноги человека, зашедшего в воду, кажутся короче?",opts:["Вода уменьшает размеры","Луч от ног преломляется при переходе вода→воздух ($\\beta > \\alpha$) → наблюдатель видит ноги как бы ближе к поверхности","Давление воды сжимает ноги","Это оптическая иллюзия мозга"],a:1,ex:"Лучи от ног идут из воды (оптически плотная) в воздух (менее плотная) → $\\beta > \\alpha$. Наблюдатель, видя расходящиеся лучи, «продолжает» их прямолинейно — мнимое изображение ног оказывается выше реального."},
|
||
{q:"Почему дно водоёма кажется более близким, чем есть на самом деле?",opts:["Дно отражает свет","Лучи от дна при выходе из воды в воздух преломляются ($\\beta > \\alpha$) → мнимое изображение дна выше реального","Вода преломляет предметы иначе","Это из-за освещения"],a:1,ex:"Лучи из более плотной среды (вода) в менее плотную (воздух): $\\beta > \\alpha$. Наблюдатель воспринимает лучи как пришедшие по прямой → видимое дно кажется ближе, чем реальное."},
|
||
{q:"Почему, находясь в лодке, трудно попасть острогой (копьём) в рыбу, плавающую вблизи дна?",opts:["Острога тупая","Из-за преломления: реальная рыба глубже и в стороне от мнимого изображения, в которое целишься","Вода отклоняет острогу","Рыба быстро уплывает"],a:1,ex:"Охотник видит мнимое изображение рыбы (из-за преломления при выходе лучей из воды). Реальная рыба — глубже и ближе к охотнику. Целясь в изображение, промажешь. Нужно целиться «ниже» изображения."},
|
||
{q:"Луч падает из воздуха под углом $\\alpha = 0°$ (перпендикулярно к границе раздела). Преломится ли он?",opts:["Да, всегда преломляется","Нет: при $\\alpha = 0°$ луч не меняет направления","Преломляется на 90°","Зависит от среды"],a:1,ex:"При нормальном падении ($\\alpha = 0°$) луч не испытывает преломления — продолжает идти по той же прямой (хотя скорость меняется). Закон преломления: при $\\alpha = 0°$ → $\\beta = 0°$."},
|
||
{q:"Два мальчика: один под водой, другой на берегу, оценивают высоту Солнца над горизонтом. Кому Солнце кажется выше?",opts:["Мальчику на берегу","Мальчику под водой — лучи от Солнца при входе в воду преломляются, $\\beta < \\alpha$ → Солнце кажется выше горизонта","Одинаково","Зависит от погоды"],a:1,ex:"Лучи Солнца переходят из воздуха (менее плотная) в воду (более плотная) → $\\beta < \\alpha$. Мальчик под водой видит Солнце под меньшим углом к нормали → Солнце кажется поднятым выше горизонта."}
|
||
];
|
||
|
||
var TASKS_P37 = [
|
||
{q:"Вычислите оптическую силу линзы с фокусным расстоянием $F = 20$ см.",hint:"$D = 1/F$; перевести в метры",unit:"дптр",a:5,ex:"$F = 0{,}20$ м; $D = 1/0{,}20 = 5$ дптр"},
|
||
{q:"Вычислите оптическую силу линзы с фокусным расстоянием $F = -10$ см.",hint:"$D = 1/F$; рассеивающая → $D < 0$",unit:"дптр",a:-10,ex:"$F = -0{,}10$ м; $D = 1/(-0{,}10) = -10$ дптр. Отрицательная оптическая сила — рассеивающая линза."},
|
||
{q:"Вычислите фокусное расстояние линзы с оптической силой $D = 2{,}5$ дптр.",hint:"$F = 1/D$",unit:"см",a:40,ex:"$F = 1/2{,}5 = 0{,}40$ м = 40 см"},
|
||
{q:"Вычислите фокусное расстояние линзы $D = -20$ дптр.",hint:"$F = 1/D$; отрицательное $F$ — рассеивающая",unit:"см",a:-5,ex:"$F = 1/(-20) = -0{,}05$ м = $-5$ см. Рассеивающая линза с мнимым фокусом."},
|
||
{q:"Какая из двух одинаковых по размеру линз имеет меньшее фокусное расстояние и большую оптическую силу?",opts:["Та, у которой поверхности менее выпуклые (плоские)","Та, у которой поверхности более выпуклые (толще в середине)","Обе одинаковы","Зависит от материала, а не от формы"],a:1,ex:"Более выпуклая поверхность сильнее преломляет лучи → меньше $F$ → больше $D$. Менее выпуклая → больше $F$ → меньше $D$. Линза 1 на рис. 267a преломляет лучи сильнее, чем линза 2."}
|
||
];
|
||
|
||
var TASKS_P38 = [
|
||
{q:"При каком условии собирающая линза даёт уменьшенное действительное изображение?",opts:["$d < F$","$d > 2F$","$F < d < 2F$","$d = F$"],a:1,ex:"При $d > 2F$: изображение действительное, перевёрнутое, уменьшенное (фотоаппарат, глаз). При $d = 2F$: равное предмету. При $F < d < 2F$: увеличенное действительное."},
|
||
{q:"Что происходит с лучами, выходящими из собирающей линзы, если предмет находится в фокусе ($d = F$)?",opts:["Сходятся в точке за линзой","Расходятся","Выходят параллельным пучком — изображение на бесконечности","Отражаются обратно"],a:2,ex:"При $d = F$ лучи после линзы выходят параллельно — изображение на бесконечности. Это используется в прожекторах и лупах: источник в фокусе → параллельный пучок."},
|
||
{q:"Свеча находится на расстоянии $d = 20$ см от линзы, изображение — на расстоянии $f = 60$ см. Во сколько раз размеры изображения отличаются от свечи? Чему равна оптическая сила линзы?",hint:"Увеличение $k = f/d$; $1/F = 1/d + 1/f$; $D = 1/F$",unit:"дптр",a:6.67,tol:0.05,ex:"$k = 60/20 = 3$ раза (увеличено). $1/F = 1/20 + 1/60 = 4/60$; $F = 15$ см = $0{,}15$ м; $D = 1/0{,}15 \\approx 6{,}7$ дптр"},
|
||
{q:"Какие изображения даёт рассеивающая линза?",opts:["Действительные, перевёрнутые","Мнимые, прямые, уменьшенные — всегда","Зависит от расстояния до предмета","Только увеличенные"],a:1,ex:"Рассеивающая линза даёт только мнимые, прямые, уменьшенные изображения при любом расстоянии до предмета. Лучи после рассеивающей линзы расходятся — пересекаются только их продолжения."},
|
||
{q:"В каком устройстве используют принцип: предмет находится между фокусом и линзой ($d < F$)?",opts:["Фотоаппарат","Лупа: даёт мнимое, прямое, увеличенное изображение","Прожектор","Объектив телескопа"],a:1,ex:"Лупа — собирающая линза. При $d < F$ получаем мнимое, прямое, увеличенное изображение. Часовщик рассматривает детали часов через лупу — его глаз видит мнимое увеличенное изображение."},
|
||
{q:"Изображение свечи в собирающей линзе оказалось уменьшенным и перевёрнутым. Где расположена свеча относительно линзы?",opts:["Между F и линзой ($d < F$)","Между F и 2F","За двойным фокусом ($d > 2F$)","В фокусе"],a:2,ex:"Уменьшенное и перевёрнутое → действительное, т.к. перевёрнутые всегда действительные. Уменьшенное действительное → $d > 2F$. При $F < d < 2F$ было бы увеличенное."}
|
||
];
|
||
|
||
var TASKS_P39 = [
|
||
{q:"Какую роль в создании зрительного образа играет оптическая система глаза?",opts:["Определяет цвет предметов","Создаёт действительное, перевёрнутое изображение на сетчатке","Фильтрует вредное излучение","Усиливает яркость изображения"],a:1,ex:"Роговица + водянистая влага + хрусталик + стекловидное тело = собирающая система. Создаёт действительное, перевёрнутое, уменьшенное изображение на сетчатке. Мозг переворачивает обратно."},
|
||
{q:"Что такое аккомодация глаза?",opts:["Привыкание к темноте","Изменение кривизны хрусталика для фокусировки на предметах разного расстояния","Расширение зрачка","Движение глазного яблока"],a:1,ex:"Аккомодация: хрусталик изменяет свою кривизну с помощью мышц. При приближении предмета — хрусталик становится более выпуклым ($F$ уменьшается). При удалении — уплощается ($F$ увеличивается). Всегда изображение остаётся на сетчатке."},
|
||
{q:"Какое изображение предмета создаётся на сетчатке глаза?",opts:["Прямое и увеличенное","Действительное, перевёрнутое, уменьшенное","Мнимое и увеличенное","Мнимое и прямое"],a:1,ex:"На сетчатке образуется действительное (реальные лучи сходятся), перевёрнутое (как в любой собирающей линзе при $d > 2F$), уменьшенное изображение. Мозг его «переворачивает» обратно."},
|
||
{q:"Что происходит с хрусталиком при переводе взгляда с близкого предмета на далёкий?",opts:["Хрусталик становится более выпуклым","Хрусталик уплощается — фокусное расстояние увеличивается","Хрусталик разрушается","Зрачок закрывается"],a:1,ex:"Для далёкого предмета: нужно большее фокусное расстояние $F$. Хрусталик уплощается — мышцы расслабляются, $F$ растёт. Для близкого: мышцы сжимают хрусталик — $F$ уменьшается."}
|
||
];
|
||
|
||
var TASKS_P40 = [
|
||
{q:"В чём суть дефекта зрения «близорукость»?",opts:["Хрусталик потерял прозрачность","Изображение удалённых предметов фокусируется перед сетчаткой, а не на ней","Сетчатка не чувствительна к цвету","Зрачок не реагирует на свет"],a:1,ex:"Близорукость (миопия): глазное яблоко вытянуто или хрусталик слишком сильно преломляет — изображение дальних предметов фокусируется перед сетчаткой. Ближние видны чётко, дальние — размыто."},
|
||
{q:"Почему в глазу дальнозоркого человека изображение близких предметов размытое?",opts:["Дальнозоркий не может смотреть близко","Хрусталик слишком плоский — при максимальном напряжении мышц всё равно не может собрать лучи от близкого предмета на сетчатку: фокус за ней","Сетчатка слишком мала","Зрачок слишком маленький"],a:1,ex:"Дальнозоркость: хрусталик потерял эластичность — даже при максимальном напряжении мышц $F$ слишком велико. Лучи от близкого предмета сошлись бы за сетчаткой → изображение размытое."},
|
||
{q:"Можно ли, не прикасаясь к очкам, определить, каким дефектом зрения обладает их владелец?",opts:["Нет, только у окулиста","Да: рассеивающие линзы (− дптр) уменьшают предметы → близорукость; собирающие (+ дптр) увеличивают → дальнозоркость","Только по цвету стёкол","По форме оправы"],a:1,ex:"Посмотрите сквозь очки на что-нибудь: рассеивающие (близорукость) уменьшают предметы. Собирающие (дальнозоркость) увеличивают. Или поднесите к источнику света: рассеивающие не дают фокуса, собирающие — дают."},
|
||
{q:"На рецепте написано: «Очки +2,5 дптр». Для какого дефекта зрения и каково фокусное расстояние линз?",hint:"$F = 1/D$",unit:"см",a:40,ex:"$D = +2{,}5$ дптр > 0 → собирающая линза → дальнозоркость. $F = 1/2{,}5 = 0{,}40$ м = 40 см."},
|
||
{q:"Почему к старости у близорукого с детства человека зрение может стать нормальным?",opts:["Глаза сами вылечиваются","С возрастом хрусталик теряет эластичность — уплощается. Близорукий видел близко, теперь хрусталик не так сильно преломляет → фокус смещается на сетчатку","Зрение улучшается от упражнений","Это невозможно"],a:1,ex:"Близорукость: хрусталик слишком выпуклый → фокус перед сетчаткой. С возрастом хрусталик уплощается (дальнозоркость). Два дефекта частично компенсируют друг друга → зрение приближается к норме."}
|
||
];
|
||
|
||
var TASKS_HARD = [
|
||
{para:"§33",q:"Тонкий непрозрачный диск диаметром $d = 30$ см. Источник на расстоянии $L = 4{,}0$ м от экрана. На экране тень диаметром $D = 1{,}2$ м. Расстояние от источника до диска?",hint:"Из подобия треугольников: $D/d = L/a$; $a = dL/D$",unit:"м",a:1.0,ex:"$a = dL/D = 0{,}30 \\times 4{,}0/1{,}2 = 1{,}0$ м"},
|
||
{para:"§33",q:"Длина тени дуба $l_{\\text{д}} = 2{,}0$ м (высота дуба $h_{\\text{д}} = 6{,}0$ м). Найти высоту берёзы, если длина её тени $l_{\\text{б}} = 2{,}6$ м.",hint:"Подобие: $h/l = \\text{const}$ для всех предметов",unit:"м",a:7.8,ex:"$h_{\\text{б}} = h_{\\text{д}} \\times l_{\\text{б}}/l_{\\text{д}} = 6{,}0 \\times 2{,}6/2{,}0 = 7{,}8$ м"},
|
||
{para:"§33",q:"Столбик высотой $h_{\\text{с}} = 80$ см отбрасывает тень длиной $l_{\\text{с}} = 40$ см. Яблоня — тень $l_{\\text{я}} = 2{,}6$ м. Высота яблони?",hint:"$h_{\\text{я}}/l_{\\text{я}} = h_{\\text{с}}/l_{\\text{с}}$",unit:"м",a:5.2,ex:"$h_{\\text{я}} = h_{\\text{с}} \\times l_{\\text{я}}/l_{\\text{с}} = 0{,}80 \\times 2{,}6/0{,}40 = 5{,}2$ м"},
|
||
{para:"§34",q:"Мальчик движется к зеркалу со скоростью $v = 2{,}0$ м/с. С какой скоростью он приближается к своему изображению?",hint:"Скорость сближения = $v_\\text{мальчик} + v_\\text{изображения} = 2v$",unit:"м/с",a:4.0,ex:"Изображение тоже движется к зеркалу с $v$. Скорость сближения = $2v = 4{,}0$ м/с."},
|
||
{para:"§37",q:"Свеча на расстоянии $d = 30$ см от линзы, изображение на экране на расстоянии $f = 60$ см. Какая это линза? Каково фокусное расстояние? Как увеличение?",hint:"$1/F = 1/d + 1/f$; $k = f/d$",unit:"дптр",a:5.0,ex:"Собирающая (изображение на экране = действительное). $1/F = 1/30 + 1/60 = 3/60$; $F = 20$ см; $D = 5$ дптр; $k = 60/30 = 2$ раза."},
|
||
{para:"§38",q:"С помощью собирающей линзы на экране получили изображение, увеличенное в 3 раза, расположенное на расстоянии $f = 36$ см от линзы. Расстояние до предмета и оптическая сила?",hint:"$k = f/d = 3$; $d = f/3$; затем $1/F = 1/d + 1/f$",unit:"дптр",a:11,tol:0.05,ex:"$d = 36/3 = 12$ см; $1/F = 1/12 + 1/36 = 4/36$; $F = 9$ см; $D = 1/0{,}09 \\approx 11$ дптр"},
|
||
{para:"§40",q:"Врач выписал очки $D = -2{,}5$ дптр. Какой дефект зрения? Каково фокусное расстояние?",hint:"$D < 0$ → рассеивающая → близорукость; $F = 1/D$",unit:"см",a:-40,ex:"$D < 0$ → близорукость (рассеивающие очки). $F = 1/(-2{,}5) = -0{,}40$ м = $-40$ см."}
|
||
];
|
||
|
||
// ═══════════════════════════════════════
|
||
// ПУЛЫ И СОСТОЯНИЯ
|
||
// ═══════════════════════════════════════
|
||
var POOLS = {
|
||
p32:TASKS_P32, p33:TASKS_P33, p34:TASKS_P34, p35:TASKS_P35, p36:TASKS_P36,
|
||
p37:TASKS_P37, p38:TASKS_P38, p39:TASKS_P39, p40:TASKS_P40, hard:TASKS_HARD
|
||
};
|
||
|
||
function mkState(pool) {
|
||
return {idx:0, answered:false, results:Array(pool.length).fill(null), selections:Array(pool.length).fill(null)};
|
||
}
|
||
|
||
var STATE = {
|
||
p32:mkState(TASKS_P32), p33:mkState(TASKS_P33), p34:mkState(TASKS_P34),
|
||
p35:mkState(TASKS_P35), p36:mkState(TASKS_P36), p37:mkState(TASKS_P37),
|
||
p38:mkState(TASKS_P38), p39:mkState(TASKS_P39), p40:mkState(TASKS_P40),
|
||
hard:mkState(TASKS_HARD)
|
||
};
|
||
|
||
// ═══════════════════════════════════════
|
||
// KaTeX рендеринг
|
||
// ═══════════════════════════════════════
|
||
function doRender(el) {
|
||
if (!window.renderMathInElement) return;
|
||
renderMathInElement(el, {
|
||
delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
|
||
throwOnError:false
|
||
});
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// ПЕРЕКЛЮЧАТЕЛЬ ПАРАГРАФОВ
|
||
// ═══════════════════════════════════════
|
||
function setParaTab(para) {
|
||
['p1','p2','p3','p4','p5','p6','p7','p8','p9','p10','p11','hard'].forEach(function(p) {
|
||
var el = document.getElementById('ptab-'+p);
|
||
if (el) el.style.display = (p===para) ? 'block' : 'none';
|
||
document.querySelectorAll('.para-pill[data-para="'+p+'"]').forEach(function(b) {
|
||
b.classList.toggle('active', p===para);
|
||
});
|
||
});
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// НАВИГАЦИЯ
|
||
// ═══════════════════════════════════════
|
||
function renderNav(sec) {
|
||
var pool = POOLS[sec], s = STATE[sec];
|
||
var el = document.getElementById('navDots'+sec);
|
||
if (!el) return;
|
||
el.innerHTML = pool.map(function(_, i) {
|
||
var cls = 'nav-dot';
|
||
if (i===s.idx) cls += ' nd-cur';
|
||
else if (s.results[i]===true) cls += ' nd-ok';
|
||
else if (s.results[i]===false) cls += ' nd-fail';
|
||
return '<button class="'+cls+'" onclick="goToTask(\''+sec+'\','+i+')" title="Задача '+(i+1)+'">'+(i+1)+'</button>';
|
||
}).join('');
|
||
}
|
||
|
||
function goToTask(sec, idx) {
|
||
var s = STATE[sec];
|
||
s.idx = idx;
|
||
s.answered = s.results[idx]!==null;
|
||
renderTask(sec);
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// ОТРИСОВКА ЗАДАЧИ
|
||
// ═══════════════════════════════════════
|
||
function renderTask(sec) {
|
||
var pool = POOLS[sec], s = STATE[sec];
|
||
var area = document.getElementById('taskArea'+sec);
|
||
var fb = document.getElementById('fb'+sec);
|
||
document.getElementById('sum'+sec).classList.remove('show');
|
||
|
||
var q = pool[s.idx];
|
||
var done = s.results[s.idx]!==null;
|
||
s.answered = done;
|
||
var isMcq = !!q.opts;
|
||
|
||
// Бейдж параграфа для раздела hard
|
||
var paraBadge = q.para ? '<span style="display:inline-flex;align-items:center;padding:2px 8px;background:rgba(124,58,237,.12);color:var(--pri);border-radius:6px;font-size:.68rem;font-weight:800;margin-left:7px">'+q.para+'</span>' : '';
|
||
|
||
if (isMcq) {
|
||
var selIdx = s.selections[s.idx];
|
||
area.innerHTML = '<div class="task-card">' +
|
||
'<div class="task-num">Задача '+(s.idx+1)+' из '+pool.length+' · Тест'+paraBadge+'</div>' +
|
||
'<div class="task-text">'+q.q+'</div>' +
|
||
'<div class="mcq-opts">' +
|
||
q.opts.map(function(opt, i) {
|
||
var cls = 'opt-btn';
|
||
if (done) {
|
||
if (i===q.a) cls += ' mcq-cor';
|
||
else if (i===selIdx) cls += ' mcq-wrong';
|
||
}
|
||
return '<button class="'+cls+'" id="mcqOpt'+sec+'_'+i+'" '+
|
||
'onclick="'+(done?'':'selectMcq(\''+sec+'\','+i+')')+'" '+
|
||
(done?'disabled':'')+'>'+
|
||
'<span style="font-weight:800;margin-right:6px">'+String.fromCharCode(65+i)+'.</span>'+opt+
|
||
'</button>';
|
||
}).join('') +
|
||
'</div></div>';
|
||
} else {
|
||
area.innerHTML = '<div class="task-card">' +
|
||
'<div class="task-num">Задача '+(s.idx+1)+' из '+pool.length+paraBadge+'</div>' +
|
||
'<div class="task-text">'+q.q+'</div>' +
|
||
'<div class="task-hint"><i class="fas fa-lightbulb"></i><span>'+q.hint+'</span></div>' +
|
||
'<div class="ans-row">' +
|
||
'<label style="font-weight:700;font-size:.88rem">Ответ:</label>' +
|
||
'<input class="ans-inp" type="text" id="ainp'+sec+'" placeholder="?" autocomplete="off"' +
|
||
(done?' disabled style="border-color:var(--'+(s.results[s.idx]?'ok':'fail')+')"':'')+'>'+
|
||
'<span class="unit-lbl">'+q.unit+'</span>' +
|
||
(done?'':'<button class="btn btn-pri" onclick="checkNum(\''+sec+'\')"><i class="fas fa-check"></i> Проверить</button>') +
|
||
'</div></div>';
|
||
}
|
||
|
||
if (done) {
|
||
var ok = s.results[s.idx];
|
||
fb.className = 'feedback show '+(ok?'fb-ok':'fb-fail');
|
||
if (isMcq) {
|
||
fb.innerHTML = ok
|
||
? '✓ Верно! '+(q.ex||'')
|
||
: '✗ Неверно. Правильный ответ: <strong>'+q.opts[q.a]+'</strong> '+(q.ex||'');
|
||
} else {
|
||
fb.innerHTML = ok
|
||
? '✓ Верно! '+q.ex
|
||
: '✗ Неверно. Правильный ответ: <strong>'+q.a+' '+q.unit+'</strong> '+q.ex;
|
||
}
|
||
document.getElementById('nextBtn'+sec).style.display = 'inline-flex';
|
||
doRender(fb);
|
||
} else {
|
||
fb.className = 'feedback';
|
||
document.getElementById('nextBtn'+sec).style.display = 'none';
|
||
}
|
||
|
||
updateScoreBar(sec);
|
||
renderNav(sec);
|
||
doRender(area);
|
||
|
||
if (!done && !isMcq) {
|
||
var inp = document.getElementById('ainp'+sec);
|
||
setTimeout(function(){ if(inp) inp.focus(); }, 80);
|
||
if (inp) inp.addEventListener('keydown', function(e){ if(e.key==='Enter') checkNum(sec); });
|
||
}
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// ПРОВЕРКА MCQ
|
||
// ═══════════════════════════════════════
|
||
function selectMcq(sec, i) {
|
||
var s = STATE[sec];
|
||
if (s.answered) return;
|
||
var pool = POOLS[sec], q = pool[s.idx];
|
||
var ok = (i===q.a);
|
||
s.results[s.idx] = ok;
|
||
s.selections[s.idx] = i;
|
||
s.answered = true;
|
||
updateScoreBar(sec);
|
||
renderNav(sec);
|
||
|
||
q.opts.forEach(function(_, j) {
|
||
var btn = document.getElementById('mcqOpt'+sec+'_'+j);
|
||
if (!btn) return;
|
||
btn.disabled = true;
|
||
if (j===q.a) btn.classList.add('mcq-cor');
|
||
else if (j===i && !ok) btn.classList.add('mcq-wrong');
|
||
});
|
||
|
||
var fb = document.getElementById('fb'+sec);
|
||
fb.className = 'feedback show '+(ok?'fb-ok':'fb-fail');
|
||
fb.innerHTML = ok
|
||
? '✓ Верно! '+(q.ex||'')
|
||
: '✗ Неверно. Правильный ответ: <strong>'+q.opts[q.a]+'</strong> '+(q.ex||'');
|
||
doRender(fb);
|
||
document.getElementById('nextBtn'+sec).style.display = 'inline-flex';
|
||
|
||
if (s.results.every(function(r){ return r!==null; })) {
|
||
setTimeout(function(){ showSummary(sec); }, 2200);
|
||
}
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// ПРОВЕРКА ЧИСЛОВЫХ
|
||
// ═══════════════════════════════════════
|
||
function checkNum(sec) {
|
||
var s = STATE[sec];
|
||
if (s.answered) return;
|
||
var pool = POOLS[sec], q = pool[s.idx];
|
||
var inp = document.getElementById('ainp'+sec);
|
||
var fb = document.getElementById('fb'+sec);
|
||
var val = inp.value.trim().replace(',','.');
|
||
var num = parseFloat(val);
|
||
|
||
if (!val || isNaN(num)) {
|
||
fb.className = 'feedback show fb-fail';
|
||
fb.innerHTML = 'Введите числовой ответ!';
|
||
return;
|
||
}
|
||
|
||
s.answered = true;
|
||
var tol = (q.tol !== undefined) ? q.tol : 0.03;
|
||
var ok = (q.a===0) ? (Math.abs(num)<0.05) : (Math.abs((num-q.a)/q.a)<tol);
|
||
s.results[s.idx] = ok;
|
||
updateScoreBar(sec);
|
||
renderNav(sec);
|
||
|
||
inp.disabled = true;
|
||
inp.style.borderColor = ok ? 'var(--ok)' : 'var(--fail)';
|
||
|
||
fb.className = 'feedback show '+(ok?'fb-ok':'fb-fail');
|
||
fb.innerHTML = ok
|
||
? '✓ Верно! '+q.ex
|
||
: '✗ Неверно. Правильный ответ: <strong>'+q.a+' '+q.unit+'</strong> '+q.ex;
|
||
doRender(fb);
|
||
document.getElementById('nextBtn'+sec).style.display = 'inline-flex';
|
||
|
||
if (s.results.every(function(r){ return r!==null; })) {
|
||
setTimeout(function(){ showSummary(sec); }, 2200);
|
||
}
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// СЛЕДУЮЩАЯ / СБРОС
|
||
// ═══════════════════════════════════════
|
||
function nextTask(sec) {
|
||
var pool = POOLS[sec], s = STATE[sec];
|
||
var next = -1;
|
||
for (var i=s.idx+1; i<pool.length; i++) {
|
||
if (s.results[i]===null) { next=i; break; }
|
||
}
|
||
if (next===-1) {
|
||
for (var j=0; j<s.idx; j++) {
|
||
if (s.results[j]===null) { next=j; break; }
|
||
}
|
||
}
|
||
if (next===-1) { showSummary(sec); return; }
|
||
s.idx = next;
|
||
s.answered = false;
|
||
renderTask(sec);
|
||
}
|
||
|
||
function resetTasks(sec) {
|
||
STATE[sec] = mkState(POOLS[sec]);
|
||
document.getElementById('sum'+sec).classList.remove('show');
|
||
renderTask(sec);
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// SCORE BAR
|
||
// ═══════════════════════════════════════
|
||
function updateScoreBar(sec) {
|
||
var pool = POOLS[sec], s = STATE[sec];
|
||
var okCnt = s.results.filter(function(r){ return r===true; }).length;
|
||
var doneCnt = s.results.filter(function(r){ return r!==null; }).length;
|
||
document.getElementById('ok'+sec).textContent = okCnt;
|
||
document.getElementById('cur'+sec).textContent = doneCnt;
|
||
document.getElementById('max'+sec).textContent = pool.length;
|
||
document.getElementById('prog'+sec).style.width = (doneCnt/pool.length*100)+'%';
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// SUMMARY
|
||
// ═══════════════════════════════════════
|
||
function showSummary(sec) {
|
||
var pool = POOLS[sec], s = STATE[sec];
|
||
document.getElementById('prog'+sec).style.width = '100%';
|
||
document.getElementById('sum'+sec).classList.add('show');
|
||
var okCnt = s.results.filter(function(r){ return r===true; }).length;
|
||
document.getElementById('sumScore'+sec).textContent = okCnt+' / '+pool.length;
|
||
var p = okCnt/pool.length;
|
||
document.getElementById('sumGrade'+sec).textContent =
|
||
p>=.9 ? 'Отлично — тема освоена!' :
|
||
p>=.75 ? 'Хорошо! Разбери пропущенные задачи.' :
|
||
p>=.5 ? 'Неплохо. Повтори формулы и попробуй ещё раз.' :
|
||
'Прочитай теорию и реши снова.';
|
||
}
|
||
|
||
|
||
|
||
// ═══════════════════════════════════════
|
||
// ПЕРЕКЛЮЧАТЕЛЬ ПАРАГРАФОВ
|
||
// ═══════════════════════════════════════
|
||
function setParaTab(para) {
|
||
['p32','p33','p34','p35','p36','p37','p38','p39','p40','hard'].forEach(function(p) {
|
||
var el = document.getElementById('ptab-'+p);
|
||
if (el) el.style.display = (p===para) ? 'block' : 'none';
|
||
document.querySelectorAll('.para-pill[data-para="'+p+'"]').forEach(function(b) {
|
||
b.classList.toggle('active', p===para);
|
||
});
|
||
});
|
||
}
|
||
|
||
// ═══════════════════════════════════════
|
||
// ЗАГЛУШКИ ИНТЕРАКТИВОВ
|
||
// ═══════════════════════════════════════
|
||
var anim32Id=null,anim33Id=null,anim34Id=null,anim35Id=null,anim36Id=null,anim37Id=null,anim38Id=null,anim39Id=null,anim40Id=null;
|
||
function upd32() {
|
||
var cv = document.getElementById('cv32');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 240;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var sel = document.getElementById('sel32src');
|
||
var isWide = sel && sel.value === 'wide';
|
||
var n = parseInt((document.getElementById('sl32n') || {}).value) || 12;
|
||
|
||
var sources = isWide ?
|
||
[{x: W*0.22, y: H/2-20}, {x: W*0.22, y: H/2}, {x: W*0.22, y: H/2+20}] :
|
||
[{x: W*0.22, y: H/2}];
|
||
|
||
var screenX = W * 0.55;
|
||
var holeY = H / 2, holeH = 8;
|
||
ctx.fillStyle = '#475569';
|
||
ctx.fillRect(screenX - 3, 10, 6, holeY - holeH - 10);
|
||
ctx.fillRect(screenX - 3, holeY + holeH, 6, H - holeY - holeH - 10);
|
||
|
||
var hues = ['rgba(251,191,36,', 'rgba(249,115,22,', 'rgba(239,68,68,'];
|
||
sources.forEach(function(src, si) {
|
||
var hue = hues[si] || hues[0];
|
||
for (var i = 0; i < n; i++) {
|
||
var angle = (i / n) * Math.PI * 2;
|
||
var dx = Math.cos(angle), dy = Math.sin(angle);
|
||
var len = Math.min(W, H) * 0.8;
|
||
var tScreen = (screenX - src.x) / (dx || 0.001);
|
||
var yAtScreen = src.y + dy * tScreen;
|
||
var throughHole = Math.abs(yAtScreen - holeY) < holeH && dx > 0;
|
||
var alpha = throughHole ? 0.9 : 0.15;
|
||
ctx.strokeStyle = hue + alpha + ')';
|
||
ctx.lineWidth = throughHole ? 1.8 : 0.8;
|
||
ctx.beginPath();
|
||
ctx.moveTo(src.x, src.y);
|
||
if (throughHole) {
|
||
ctx.lineTo(src.x + dx * len, src.y + dy * len);
|
||
} else {
|
||
if (dx > 0 && tScreen > 0 && tScreen < len) {
|
||
ctx.lineTo(screenX, yAtScreen);
|
||
} else {
|
||
ctx.lineTo(src.x + dx * len, src.y + dy * len);
|
||
}
|
||
}
|
||
ctx.stroke();
|
||
}
|
||
var grd = ctx.createRadialGradient(src.x, src.y, 0, src.x, src.y, 18);
|
||
grd.addColorStop(0, 'rgba(251,191,36,0.9)');
|
||
grd.addColorStop(1, 'rgba(251,191,36,0)');
|
||
ctx.fillStyle = grd;
|
||
ctx.beginPath(); ctx.arc(src.x, src.y, 18, 0, Math.PI * 2); ctx.fill();
|
||
ctx.fillStyle = '#fff'; ctx.font = 'bold 9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText(isWide ? 'S' + (si+1) : 'S', src.x, src.y + 4);
|
||
});
|
||
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('Источник', W * 0.22, H - 10);
|
||
ctx.fillText('Экран с отверстием', screenX, H - 10);
|
||
ctx.fillText('→ луч', W * 0.78, H/2 - 15);
|
||
}
|
||
function startAnim32() { upd32(); }
|
||
|
||
function upd33() {
|
||
var cv = document.getElementById('cv33');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 260;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var sel = document.getElementById('sel33src');
|
||
var isWide = sel && sel.value === 'wide';
|
||
var objH = parseInt((document.getElementById('sl33obj') || {}).value) || 30;
|
||
var lbl = document.getElementById('lbl33obj');
|
||
if (lbl) lbl.textContent = objH;
|
||
|
||
var srcX = W * 0.12, srcYC = H / 2;
|
||
var srcSize = isWide ? 30 : 3;
|
||
var objX = W * 0.45, objYC = H / 2;
|
||
var scrX = W * 0.82;
|
||
|
||
if (isWide) {
|
||
var grd = ctx.createLinearGradient(srcX-3, srcYC-srcSize, srcX+3, srcYC+srcSize);
|
||
grd.addColorStop(0, '#fbbf24'); grd.addColorStop(0.5, '#fff'); grd.addColorStop(1, '#fbbf24');
|
||
ctx.fillStyle = grd;
|
||
ctx.fillRect(srcX - 4, srcYC - srcSize, 8, srcSize * 2);
|
||
} else {
|
||
var sg = ctx.createRadialGradient(srcX, srcYC, 0, srcX, srcYC, 12);
|
||
sg.addColorStop(0, 'rgba(255,255,200,1)'); sg.addColorStop(1, 'rgba(251,191,36,0)');
|
||
ctx.fillStyle = sg;
|
||
ctx.beginPath(); ctx.arc(srcX, srcYC, 12, 0, Math.PI * 2); ctx.fill();
|
||
}
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = '9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('S', srcX, srcYC + 4);
|
||
|
||
ctx.fillStyle = '#64748b';
|
||
ctx.fillRect(objX - 5, objYC - objH/2, 10, objH);
|
||
|
||
var srcYTop = srcYC - srcSize, srcYBot = srcYC + srcSize;
|
||
var objYTop = objYC - objH/2, objYBot = objYC + objH/2;
|
||
var shadowTopY = srcYTop + (objYTop - srcYTop) * (scrX - srcX) / (objX - srcX);
|
||
var shadowBotY = srcYBot + (objYBot - srcYBot) * (scrX - srcX) / (objX - srcX);
|
||
var penumbraTopY = srcYBot + (objYTop - srcYBot) * (scrX - srcX) / (objX - srcX);
|
||
var penumbraBotY = srcYTop + (objYBot - srcYTop) * (scrX - srcX) / (objX - srcX);
|
||
|
||
ctx.fillStyle = '#1e293b'; ctx.fillRect(scrX - 3, 10, 6, H - 20);
|
||
ctx.strokeStyle = '#475569'; ctx.lineWidth = 1;
|
||
ctx.strokeRect(scrX - 3, 10, 6, H - 20);
|
||
|
||
if (isWide) {
|
||
ctx.fillStyle = 'rgba(251,191,36,0.2)';
|
||
ctx.fillRect(scrX + 3, Math.min(penumbraTopY, shadowTopY), 14, Math.abs(shadowTopY - penumbraTopY));
|
||
ctx.fillStyle = 'rgba(15,23,42,0.95)';
|
||
ctx.fillRect(scrX + 3, shadowTopY, 14, shadowBotY - shadowTopY);
|
||
ctx.fillStyle = 'rgba(251,191,36,0.2)';
|
||
ctx.fillRect(scrX + 3, shadowBotY, 14, Math.abs(penumbraBotY - shadowBotY));
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '7px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('полутень', scrX + 18, penumbraTopY + 6);
|
||
ctx.fillText('тень', scrX + 18, (shadowTopY + shadowBotY) / 2 + 3);
|
||
ctx.fillText('полутень', scrX + 18, penumbraBotY - 3);
|
||
} else {
|
||
ctx.fillStyle = 'rgba(15,23,42,0.95)';
|
||
ctx.fillRect(scrX + 3, shadowTopY, 14, shadowBotY - shadowTopY);
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '7px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('тень', scrX + 18, (shadowTopY + shadowBotY) / 2 + 3);
|
||
}
|
||
|
||
ctx.strokeStyle = 'rgba(251,191,36,0.5)'; ctx.lineWidth = 1; ctx.setLineDash([4,3]);
|
||
ctx.beginPath(); ctx.moveTo(srcX, srcYTop); ctx.lineTo(objX, objYTop); ctx.lineTo(scrX, shadowTopY); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(srcX, srcYBot); ctx.lineTo(objX, objYBot); ctx.lineTo(scrX, shadowBotY); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('Источник', srcX, H - 8);
|
||
ctx.fillText('Предмет', objX, H - 8);
|
||
ctx.fillText('Экран', scrX, H - 8);
|
||
}
|
||
function startAnim33() { upd33(); }
|
||
|
||
// ── cv34: Pro Max закон отражения (мышь-лазер) ──
|
||
var alpha34 = 35; // текущий угол падения (0..85), хранится глобально
|
||
function reset34() { alpha34 = 45; upd34(); }
|
||
function upd34() {
|
||
var cv = document.getElementById('cv34');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 280;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var sel = document.getElementById('sel34type');
|
||
var isDiffuse = sel && sel.value === 'diffuse';
|
||
var alpha = Math.max(0, Math.min(85, alpha34|0));
|
||
var alphaRad = alpha * Math.PI / 180;
|
||
|
||
var mirrorY = H * 0.72, mirrorX = W / 2;
|
||
var rayLen = Math.min(W * 0.42, mirrorY - 20);
|
||
|
||
// фоновая сетка-«стол»
|
||
ctx.strokeStyle = 'rgba(148,163,184,0.06)'; ctx.lineWidth = 1;
|
||
for (var gx = 0; gx < W; gx += 24) { ctx.beginPath(); ctx.moveTo(gx, 0); ctx.lineTo(gx, H); ctx.stroke(); }
|
||
for (var gy = 0; gy < H; gy += 24) { ctx.beginPath(); ctx.moveTo(0, gy); ctx.lineTo(W, gy); ctx.stroke(); }
|
||
|
||
// зеркало
|
||
if (!isDiffuse) {
|
||
var grd = ctx.createLinearGradient(40, mirrorY, W-40, mirrorY);
|
||
grd.addColorStop(0, 'rgba(167,139,250,0.05)');
|
||
grd.addColorStop(0.5, 'rgba(167,139,250,0.55)');
|
||
grd.addColorStop(1, 'rgba(167,139,250,0.05)');
|
||
ctx.fillStyle = grd; ctx.fillRect(40, mirrorY, W - 80, 5);
|
||
ctx.strokeStyle = '#a78bfa'; ctx.lineWidth = 2;
|
||
ctx.beginPath(); ctx.moveTo(40, mirrorY); ctx.lineTo(W - 40, mirrorY); ctx.stroke();
|
||
// штриховка снизу — обозначение «обратной стороны»
|
||
ctx.strokeStyle = 'rgba(167,139,250,0.45)'; ctx.lineWidth = 1.2;
|
||
for (var hx = 50; hx < W - 40; hx += 10) {
|
||
ctx.beginPath(); ctx.moveTo(hx, mirrorY + 5); ctx.lineTo(hx - 6, mirrorY + 13); ctx.stroke();
|
||
}
|
||
} else {
|
||
ctx.strokeStyle = '#a78bfa'; ctx.lineWidth = 2;
|
||
ctx.beginPath();
|
||
for (var sx = 40; sx < W - 40; sx += 10) {
|
||
ctx.moveTo(sx, mirrorY + (sx % 20 === 0 ? -3 : 3));
|
||
ctx.lineTo(sx + 10, mirrorY + (sx % 20 === 0 ? 3 : -3));
|
||
}
|
||
ctx.stroke();
|
||
}
|
||
|
||
// нормаль (пунктир)
|
||
ctx.strokeStyle = 'rgba(203,213,225,0.6)'; ctx.lineWidth = 1.5;
|
||
ctx.setLineDash([6, 5]);
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, 12); ctx.lineTo(mirrorX, mirrorY + 28); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
ctx.fillStyle = '#cbd5e1'; ctx.font = '10px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('нормаль', mirrorX + 6, 22);
|
||
|
||
// падающий луч с лазерным glow
|
||
var incStartX = mirrorX - Math.sin(alphaRad) * rayLen;
|
||
var incStartY = mirrorY - Math.cos(alphaRad) * rayLen;
|
||
ctx.strokeStyle = 'rgba(251,191,36,0.25)'; ctx.lineWidth = 7;
|
||
ctx.beginPath(); ctx.moveTo(incStartX, incStartY); ctx.lineTo(mirrorX, mirrorY); ctx.stroke();
|
||
ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath(); ctx.moveTo(incStartX, incStartY); ctx.lineTo(mirrorX, mirrorY); ctx.stroke();
|
||
|
||
// лазер-указка
|
||
var lpw = 14, lph = 9;
|
||
ctx.save();
|
||
ctx.translate(incStartX, incStartY);
|
||
ctx.rotate(Math.atan2(mirrorY - incStartY, mirrorX - incStartX));
|
||
ctx.fillStyle = '#1e293b'; ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 1.5;
|
||
ctx.fillRect(-lpw, -lph/2, lpw, lph); ctx.strokeRect(-lpw, -lph/2, lpw, lph);
|
||
ctx.fillStyle = '#ef4444';
|
||
ctx.beginPath(); ctx.arc(0, 0, 2.5, 0, Math.PI*2); ctx.fill();
|
||
ctx.restore();
|
||
|
||
ctx.fillStyle = '#fcd34d'; ctx.font = 'bold 10px sans-serif'; ctx.textAlign = 'right';
|
||
ctx.fillText('падающий', incStartX - 18, incStartY - 4);
|
||
|
||
if (!isDiffuse) {
|
||
var refEndX = mirrorX + Math.sin(alphaRad) * rayLen;
|
||
var refEndY = mirrorY - Math.cos(alphaRad) * rayLen;
|
||
ctx.strokeStyle = 'rgba(96,165,250,0.25)'; ctx.lineWidth = 7;
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, mirrorY); ctx.lineTo(refEndX, refEndY); ctx.stroke();
|
||
ctx.strokeStyle = '#60a5fa'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, mirrorY); ctx.lineTo(refEndX, refEndY); ctx.stroke();
|
||
// стрелка на конце
|
||
var aDx = refEndX - mirrorX, aDy = refEndY - mirrorY, aL = Math.sqrt(aDx*aDx + aDy*aDy) || 1;
|
||
var ux = aDx/aL, uy = aDy/aL;
|
||
ctx.fillStyle = '#60a5fa';
|
||
ctx.beginPath();
|
||
ctx.moveTo(refEndX, refEndY);
|
||
ctx.lineTo(refEndX - ux*10 + uy*6, refEndY - uy*10 - ux*6);
|
||
ctx.lineTo(refEndX - ux*10 - uy*6, refEndY - uy*10 + ux*6);
|
||
ctx.fill();
|
||
ctx.fillStyle = '#93c5fd'; ctx.font = 'bold 10px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('отражённый', refEndX + 6, refEndY - 4);
|
||
|
||
// дуги углов α и β
|
||
var arcR = Math.min(50, rayLen * 0.45);
|
||
ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 2;
|
||
ctx.beginPath();
|
||
ctx.arc(mirrorX, mirrorY, arcR, -Math.PI/2 - alphaRad, -Math.PI/2); ctx.stroke();
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = 'bold 13px sans-serif'; ctx.textAlign = 'center';
|
||
var alA = mirrorX - Math.sin(alphaRad/2)*(arcR+12);
|
||
var alB = mirrorY - Math.cos(alphaRad/2)*(arcR+12);
|
||
ctx.fillText('α=' + alpha + '°', alA, alB + 4);
|
||
|
||
ctx.strokeStyle = '#60a5fa'; ctx.lineWidth = 2;
|
||
ctx.beginPath();
|
||
ctx.arc(mirrorX, mirrorY, arcR, -Math.PI/2, -Math.PI/2 + alphaRad); ctx.stroke();
|
||
ctx.fillStyle = '#60a5fa'; ctx.font = 'bold 13px sans-serif'; ctx.textAlign = 'center';
|
||
var blA = mirrorX + Math.sin(alphaRad/2)*(arcR+12);
|
||
var blB = mirrorY - Math.cos(alphaRad/2)*(arcR+12);
|
||
ctx.fillText('β=' + alpha + '°', blA, blB + 4);
|
||
} else {
|
||
for (var di = 0; di < 11; di++) {
|
||
var dAngle = ((di / 10) * Math.PI - Math.PI/2) * 0.92;
|
||
var dX = mirrorX + Math.sin(dAngle) * rayLen * 0.85;
|
||
var dY = mirrorY - Math.cos(dAngle) * rayLen * 0.85;
|
||
var alpha2 = 0.25 + 0.55 * Math.abs(Math.cos(dAngle));
|
||
ctx.strokeStyle = 'rgba(96,165,250,' + alpha2 + ')';
|
||
ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, mirrorY); ctx.lineTo(dX, dY); ctx.stroke();
|
||
}
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('Лучи рассеиваются во все стороны', mirrorX, mirrorY + 45);
|
||
}
|
||
|
||
// точка падения — «искорка»
|
||
ctx.fillStyle = 'rgba(251,191,36,0.85)';
|
||
ctx.beginPath(); ctx.arc(mirrorX, mirrorY, 4, 0, Math.PI*2); ctx.fill();
|
||
ctx.fillStyle = 'rgba(251,191,36,0.25)';
|
||
ctx.beginPath(); ctx.arc(mirrorX, mirrorY, 9, 0, Math.PI*2); ctx.fill();
|
||
|
||
// chips
|
||
var cA = document.getElementById('chip34a');
|
||
var cB = document.getElementById('chip34b');
|
||
if (cA) cA.textContent = 'α = ' + alpha + '°';
|
||
if (cB) {
|
||
if (isDiffuse) {
|
||
cB.textContent = 'диффузное';
|
||
cB.style.background = 'rgba(148,163,184,.15)';
|
||
cB.style.color = '#64748b';
|
||
cB.style.borderColor = 'rgba(148,163,184,.3)';
|
||
} else {
|
||
cB.textContent = 'β = ' + alpha + '° ✓';
|
||
cB.style.background = 'rgba(34,197,94,.12)';
|
||
cB.style.color = '#16a34a';
|
||
cB.style.borderColor = 'rgba(34,197,94,.3)';
|
||
}
|
||
}
|
||
|
||
var res = document.getElementById('res34');
|
||
if (res) res.innerHTML = isDiffuse
|
||
? 'Диффузное отражение: лучи расходятся во все стороны'
|
||
: '$\\alpha = ' + alpha + '°$ → $\\beta = ' + alpha + '°$ (закон отражения)';
|
||
if (window.doRender && res) doRender(res);
|
||
}
|
||
|
||
// Mouse / touch drag для cv34: курсор задаёт точку — угол α определяется автоматически
|
||
(function() {
|
||
function setup34() {
|
||
var cv = document.getElementById('cv34');
|
||
if (!cv) return;
|
||
function update(e) {
|
||
var rect = cv.getBoundingClientRect();
|
||
var x = e.clientX - rect.left;
|
||
var y = e.clientY - rect.top;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 280;
|
||
var mirrorY = H * 0.72, mirrorX = W / 2;
|
||
// вектор от точки падения к курсору
|
||
var dx = x - mirrorX, dy = mirrorY - y; // dy > 0, если выше зеркала
|
||
if (dy < 4) dy = 4;
|
||
var a = Math.atan2(dx, dy) * 180 / Math.PI;
|
||
// ограничим |α| <= 85
|
||
a = Math.max(-85, Math.min(85, a));
|
||
alpha34 = Math.abs(Math.round(a));
|
||
upd34();
|
||
}
|
||
var down = false;
|
||
cv.addEventListener('mousemove', function(e) { update(e); });
|
||
cv.addEventListener('mousedown', function(e) { down = true; update(e); });
|
||
cv.addEventListener('mouseup', function() { down = false; });
|
||
cv.addEventListener('touchstart', function(e) {
|
||
if (e.touches.length) { update(e.touches[0]); e.preventDefault(); }
|
||
}, {passive:false});
|
||
cv.addEventListener('touchmove', function(e) {
|
||
if (e.touches.length) { update(e.touches[0]); e.preventDefault(); }
|
||
}, {passive:false});
|
||
cv.addEventListener('touchend', function() {});
|
||
}
|
||
if (document.readyState === 'complete') setup34();
|
||
else window.addEventListener('load', setup34);
|
||
})();
|
||
|
||
function upd35() {
|
||
var cv = document.getElementById('cv35');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 280;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var l1 = parseInt((document.getElementById('sl35d') || {}).value) || 100;
|
||
var showRays = document.getElementById('chk35rays') && document.getElementById('chk35rays').checked;
|
||
var mirrorX = W / 2;
|
||
var scale = (W * 0.35) / 200;
|
||
var objX = mirrorX - l1 * scale;
|
||
var imgX = mirrorX + l1 * scale;
|
||
var objH = 60, objYbase = H * 0.72, objYtop = objYbase - objH;
|
||
|
||
var mg = ctx.createLinearGradient(mirrorX-3, 20, mirrorX+3, H-20);
|
||
mg.addColorStop(0, 'rgba(167,139,250,0.1)');
|
||
mg.addColorStop(0.5, 'rgba(167,139,250,0.5)');
|
||
mg.addColorStop(1, 'rgba(167,139,250,0.1)');
|
||
ctx.fillStyle = mg; ctx.fillRect(mirrorX - 3, 20, 6, H - 40);
|
||
ctx.strokeStyle = '#a78bfa'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, 20); ctx.lineTo(mirrorX, H - 20); ctx.stroke();
|
||
ctx.fillStyle = '#a78bfa'; ctx.font = '9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('Зеркало', mirrorX, H - 8);
|
||
|
||
ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 3;
|
||
ctx.beginPath(); ctx.moveTo(objX, objYbase); ctx.lineTo(objX, objYtop); ctx.stroke();
|
||
ctx.fillStyle = '#fbbf24';
|
||
ctx.beginPath(); ctx.moveTo(objX, objYtop - 10); ctx.lineTo(objX - 6, objYtop + 2); ctx.lineTo(objX + 6, objYtop + 2); ctx.fill();
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = 'bold 9px sans-serif';
|
||
ctx.fillText('Предмет', objX, objYbase + 16);
|
||
ctx.fillText('S', objX, objYtop - 14);
|
||
|
||
ctx.strokeStyle = 'rgba(147,197,253,0.6)'; ctx.lineWidth = 2; ctx.setLineDash([5, 4]);
|
||
ctx.beginPath(); ctx.moveTo(imgX, objYbase); ctx.lineTo(imgX, objYtop); ctx.stroke();
|
||
ctx.fillStyle = 'rgba(147,197,253,0.5)';
|
||
ctx.beginPath(); ctx.moveTo(imgX, objYtop - 10); ctx.lineTo(imgX - 6, objYtop + 2); ctx.lineTo(imgX + 6, objYtop + 2); ctx.fill();
|
||
ctx.setLineDash([]);
|
||
ctx.fillStyle = '#93c5fd'; ctx.font = 'bold 9px sans-serif';
|
||
ctx.fillText("Изображение S'", imgX, objYbase + 16);
|
||
ctx.fillStyle = 'rgba(147,197,253,0.7)'; ctx.font = '8px sans-serif';
|
||
ctx.fillText("(мнимое)", imgX, objYbase + 28);
|
||
|
||
ctx.strokeStyle = '#475569'; ctx.lineWidth = 1; ctx.setLineDash([3, 3]);
|
||
ctx.beginPath(); ctx.moveTo(objX, H * 0.85); ctx.lineTo(mirrorX, H * 0.85); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
ctx.fillStyle = '#ef4444'; ctx.font = 'bold 10px sans-serif';
|
||
ctx.fillText('l₁ = ' + l1, (objX + mirrorX) / 2, H * 0.85 - 4);
|
||
ctx.strokeStyle = '#475569'; ctx.lineWidth = 1; ctx.setLineDash([3, 3]);
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, H * 0.85); ctx.lineTo(imgX, H * 0.85); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
ctx.fillStyle = '#3b82f6'; ctx.font = 'bold 10px sans-serif';
|
||
ctx.fillText('l₂ = ' + l1, (mirrorX + imgX) / 2, H * 0.85 - 4);
|
||
|
||
if (showRays) {
|
||
var eyeX = W * 0.88, eyeY = H * 0.35;
|
||
ctx.strokeStyle = 'rgba(251,191,36,0.7)'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(objX, objYtop); ctx.lineTo(mirrorX, objYtop); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, objYtop); ctx.lineTo(eyeX, eyeY); ctx.stroke();
|
||
ctx.setLineDash([4, 3]);
|
||
ctx.strokeStyle = 'rgba(147,197,253,0.5)';
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, objYtop); ctx.lineTo(imgX, objYtop); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
|
||
var r2mirY = objYtop + 20;
|
||
ctx.strokeStyle = 'rgba(251,191,36,0.7)'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(objX, objYtop); ctx.lineTo(mirrorX, r2mirY); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, r2mirY); ctx.lineTo(eyeX, eyeY); ctx.stroke();
|
||
ctx.setLineDash([4, 3]);
|
||
ctx.strokeStyle = 'rgba(147,197,253,0.5)';
|
||
ctx.beginPath(); ctx.moveTo(mirrorX, r2mirY); ctx.lineTo(imgX, r2mirY - (r2mirY - objYtop)); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
|
||
ctx.fillStyle = '#22c55e'; ctx.font = '16px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('👁', eyeX, eyeY + 6);
|
||
}
|
||
|
||
var res = document.getElementById('res35');
|
||
if (res) res.textContent = 'l₁ = l₂ = ' + l1 + ' усл.ед. | Изображение: мнимое, прямое, равных размеров.';
|
||
}
|
||
|
||
function upd36() {
|
||
var cv = document.getElementById('cv36');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 270;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var alpha = parseInt((document.getElementById('sl36a') || {}).value) || 40;
|
||
var sel = document.getElementById('sel36med');
|
||
var medStr = sel ? sel.value : 'water';
|
||
var nMap = {water:1.33, glass:1.5, diamond:2.42, rev_water:0.75};
|
||
var labMap = {water:'Воздух → Вода (n=1,33)', glass:'Воздух → Стекло (n=1,5)', diamond:'Воздух → Алмаз (n=2,42)', rev_water:'Вода → Воздух (n=0,75)'};
|
||
var colMap = {water:'rgba(14,165,233,0.3)', glass:'rgba(167,139,250,0.25)', diamond:'rgba(251,191,36,0.2)', rev_water:'rgba(14,165,233,0.15)'};
|
||
var n = nMap[medStr] || 1.33;
|
||
var alphaRad = alpha * Math.PI / 180;
|
||
var sinBeta = Math.sin(alphaRad) / n;
|
||
var beta = Math.asin(Math.min(1, sinBeta)) * 180 / Math.PI;
|
||
var betaRad = Math.asin(Math.min(1, sinBeta));
|
||
var totalInternalReflection = sinBeta > 1;
|
||
|
||
var boundY = H / 2;
|
||
var cx = W / 2;
|
||
|
||
// Media backgrounds
|
||
ctx.fillStyle = 'rgba(15,23,42,0.6)'; ctx.fillRect(0, 0, W, boundY);
|
||
ctx.fillStyle = colMap[medStr]; ctx.fillRect(0, boundY, W, H - boundY);
|
||
|
||
// Boundary line
|
||
ctx.strokeStyle = 'rgba(167,139,250,0.6)'; ctx.lineWidth = 2;
|
||
ctx.beginPath(); ctx.moveTo(0, boundY); ctx.lineTo(W, boundY); ctx.stroke();
|
||
|
||
// Labels
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '9px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText(medStr === 'rev_water' ? 'Вода' : 'Воздух', 8, boundY - 8);
|
||
ctx.fillText(medStr === 'rev_water' ? 'Воздух' : medStr === 'water' ? 'Вода' : medStr === 'glass' ? 'Стекло' : 'Алмаз', 8, boundY + 18);
|
||
|
||
// Normal
|
||
ctx.strokeStyle = 'rgba(148,163,184,0.4)'; ctx.lineWidth = 1.5; ctx.setLineDash([6, 4]);
|
||
ctx.beginPath(); ctx.moveTo(cx, 20); ctx.lineTo(cx, H - 20); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
ctx.fillStyle = '#64748b'; ctx.font = '9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('нормаль', cx + 40, 30);
|
||
|
||
var rayLen = Math.min(W, H) * 0.38;
|
||
|
||
// Incident ray
|
||
var incSX = cx - Math.sin(alphaRad) * rayLen;
|
||
var incSY = boundY - Math.cos(alphaRad) * rayLen;
|
||
ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath(); ctx.moveTo(incSX, incSY); ctx.lineTo(cx, boundY); ctx.stroke();
|
||
// Arrow
|
||
var dx = cx-incSX, dy = boundY-incSY, dl = Math.sqrt(dx*dx+dy*dy);
|
||
var mx = cx-dx/dl*12, my = boundY-dy/dl*12;
|
||
ctx.fillStyle='#ef4444'; ctx.beginPath();
|
||
ctx.moveTo(cx,boundY); ctx.lineTo(mx+dy/dl*5,my-dx/dl*5); ctx.lineTo(mx-dy/dl*5,my+dx/dl*5); ctx.fill();
|
||
|
||
// Reflected ray
|
||
var refEX = cx + Math.sin(alphaRad) * rayLen * 0.6;
|
||
var refEY = boundY - Math.cos(alphaRad) * rayLen * 0.6;
|
||
ctx.strokeStyle = 'rgba(239,68,68,0.5)'; ctx.lineWidth = 1.5; ctx.setLineDash([4,3]);
|
||
ctx.beginPath(); ctx.moveTo(cx, boundY); ctx.lineTo(refEX, refEY); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
|
||
// Refracted ray
|
||
if (!totalInternalReflection) {
|
||
var refRX = cx + Math.sin(betaRad) * rayLen;
|
||
var refRY = boundY + Math.cos(betaRad) * rayLen;
|
||
ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath(); ctx.moveTo(cx, boundY); ctx.lineTo(refRX, refRY); ctx.stroke();
|
||
ctx.fillStyle='#3b82f6'; ctx.beginPath();
|
||
var dx2=refRX-cx,dy2=refRY-boundY,dl2=Math.sqrt(dx2*dx2+dy2*dy2);
|
||
var rx=refRX-dx2/dl2*12,ry=refRY-dy2/dl2*12;
|
||
ctx.moveTo(refRX,refRY); ctx.lineTo(rx+dy2/dl2*5,ry-dx2/dl2*5); ctx.lineTo(rx-dy2/dl2*5,ry+dx2/dl2*5); ctx.fill();
|
||
} else {
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = 'bold 10px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('⚠️ Полное внутреннее отражение!', cx, boundY + 40);
|
||
}
|
||
|
||
// Angle arcs & labels
|
||
var arcR = 40;
|
||
if (alpha > 0) {
|
||
ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2;
|
||
ctx.beginPath(); ctx.arc(cx, boundY, arcR, -Math.PI/2-alphaRad, -Math.PI/2); ctx.stroke();
|
||
ctx.fillStyle = '#fca5a5'; ctx.font = 'bold 11px sans-serif'; ctx.textAlign = 'right';
|
||
ctx.fillText('α=' + alpha + '°', cx - Math.sin(alphaRad/2)*arcR - 4, boundY - Math.cos(alphaRad/2)*arcR);
|
||
|
||
if (!totalInternalReflection && beta > 0.5) {
|
||
ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2;
|
||
ctx.beginPath(); ctx.arc(cx, boundY, arcR, Math.PI/2, Math.PI/2+betaRad); ctx.stroke();
|
||
ctx.fillStyle = '#93c5fd'; ctx.font = 'bold 11px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('β=' + beta.toFixed(1) + '°', cx + Math.sin(betaRad/2)*arcR + 4, boundY + Math.cos(betaRad/2)*arcR);
|
||
}
|
||
}
|
||
|
||
var res = document.getElementById('res36');
|
||
if (res) {
|
||
if (totalInternalReflection) {
|
||
res.textContent = 'α=' + alpha + '° | Полное внутреннее отражение! (sin α > n²)';
|
||
} else {
|
||
res.innerHTML = '$\\alpha = ' + alpha + '°$; $n = ' + n + '$; $\\beta \\approx ' + beta.toFixed(1) + '°$ (' + (n>1?'β < α':'β > α') + ' — ' + (n>1?'более плотная среда':'менее плотная среда') + ')';
|
||
if (window.doRender) doRender(res);
|
||
}
|
||
}
|
||
}
|
||
|
||
function upd37() {
|
||
var cv = document.getElementById('cv37');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 240;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var F = parseInt((document.getElementById('sl37F') || {}).value) || 80;
|
||
if (F === 0) F = 1;
|
||
var lx = W / 2, ly = H / 2;
|
||
var scale = W * 0.3 / 200;
|
||
var Fpx = F * scale;
|
||
|
||
// Optical axis
|
||
ctx.strokeStyle = 'rgba(148,163,184,0.3)'; ctx.lineWidth = 1;
|
||
ctx.beginPath(); ctx.moveTo(0, ly); ctx.lineTo(W, ly); ctx.stroke();
|
||
|
||
// Lens
|
||
var lensH = H * 0.55;
|
||
var isConv = F > 0;
|
||
ctx.strokeStyle = isConv ? '#a78bfa' : '#f97316'; ctx.lineWidth = 3;
|
||
if (isConv) {
|
||
// Biconvex
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lensH/2);
|
||
ctx.quadraticCurveTo(lx + 18, ly, lx, ly + lensH/2);
|
||
ctx.stroke();
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lensH/2);
|
||
ctx.quadraticCurveTo(lx - 18, ly, lx, ly + lensH/2);
|
||
ctx.stroke();
|
||
} else {
|
||
// Biconcave
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lensH/2);
|
||
ctx.quadraticCurveTo(lx - 18, ly, lx, ly + lensH/2);
|
||
ctx.stroke();
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lensH/2);
|
||
ctx.quadraticCurveTo(lx + 18, ly, lx, ly + lensH/2);
|
||
ctx.stroke();
|
||
}
|
||
// Arrows on lens symbol
|
||
ctx.strokeStyle = isConv ? '#a78bfa' : '#f97316'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(lx, ly - lensH/2); ctx.lineTo(lx, ly + lensH/2); ctx.stroke();
|
||
ctx.fillStyle = isConv ? '#a78bfa' : '#f97316';
|
||
if (isConv) {
|
||
ctx.beginPath(); ctx.moveTo(lx, ly - lensH/2); ctx.lineTo(lx-5,ly-lensH/2+10); ctx.lineTo(lx+5,ly-lensH/2+10); ctx.fill();
|
||
ctx.beginPath(); ctx.moveTo(lx, ly + lensH/2); ctx.lineTo(lx-5,ly+lensH/2-10); ctx.lineTo(lx+5,ly+lensH/2-10); ctx.fill();
|
||
} else {
|
||
ctx.beginPath(); ctx.moveTo(lx, ly - lensH/2); ctx.lineTo(lx-5,ly-lensH/2-2); ctx.lineTo(lx-5,ly-lensH/2+12); ctx.fill();
|
||
ctx.beginPath(); ctx.moveTo(lx, ly + lensH/2); ctx.lineTo(lx-5,ly+lensH/2+2); ctx.lineTo(lx-5,ly+lensH/2-12); ctx.fill();
|
||
}
|
||
|
||
// Focal points
|
||
var f1x = lx - Math.abs(Fpx), f2x = lx + Math.abs(Fpx);
|
||
if (F < 0) { f1x = lx + Math.abs(Fpx); f2x = lx - Math.abs(Fpx); }
|
||
[f1x, f2x].forEach(function(fx) {
|
||
ctx.fillStyle = '#fbbf24';
|
||
ctx.beginPath(); ctx.arc(fx, ly, 5, 0, Math.PI*2); ctx.fill();
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = 'bold 11px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('F', fx, ly - 10);
|
||
});
|
||
|
||
// Parallel rays → converge/diverge at F
|
||
var nRays = 7;
|
||
for (var ri = 0; ri < nRays; ri++) {
|
||
var ry = ly - lensH/2 + lensH * ri / (nRays - 1);
|
||
var startX = 15;
|
||
// Incident ray
|
||
ctx.strokeStyle = 'rgba(251,191,36,0.8)'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(startX, ry); ctx.lineTo(lx, ry); ctx.stroke();
|
||
|
||
if (isConv) {
|
||
// Refracted ray converges to F
|
||
ctx.strokeStyle = 'rgba(59,130,246,0.8)'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(lx, ry); ctx.lineTo(f2x, ly); ctx.stroke();
|
||
// Continue past F
|
||
var extX = W - 10;
|
||
var extY = ly + (extX - f2x) * (ly - ry) / (f2x - lx);
|
||
ctx.strokeStyle = 'rgba(59,130,246,0.3)'; ctx.lineWidth = 1;
|
||
ctx.beginPath(); ctx.moveTo(f2x, ly); ctx.lineTo(Math.min(extX, W-5), extY); ctx.stroke();
|
||
} else {
|
||
// Refracted ray diverges; extension passes through F (on same side)
|
||
var fFarX = lx - Fpx; // мнимый фокус (ближе к источнику для рассеивающей)
|
||
var dirX = lx - fFarX, dirY = ry - ly; // direction from F to point on lens
|
||
var len = Math.sqrt(dirX*dirX + dirY*dirY);
|
||
ctx.strokeStyle = 'rgba(59,130,246,0.8)'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.moveTo(lx, ry); ctx.lineTo(lx + dirX/len*200, ry + dirY/len*200); ctx.stroke();
|
||
// Dashed continuation to мнимый фокус
|
||
ctx.strokeStyle = 'rgba(147,197,253,0.4)'; ctx.lineWidth = 1; ctx.setLineDash([4,3]);
|
||
ctx.beginPath(); ctx.moveTo(lx, ry); ctx.lineTo(fFarX, ly); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
}
|
||
}
|
||
|
||
// Labels
|
||
ctx.fillStyle = isConv ? '#a78bfa' : '#f97316'; ctx.font = 'bold 9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText(isConv ? 'Собирающая' : 'Рассеивающая', lx, ly - lensH/2 - 8);
|
||
|
||
var D = F !== 0 ? (1000 / F).toFixed(1) : '∞';
|
||
var res = document.getElementById('res37');
|
||
if (res) res.textContent = 'F = ' + F + ' усл.; D = 1000/' + F + ' = ' + D + ' дптр (' + (isConv ? 'собирающая' : 'рассеивающая') + ')';
|
||
}
|
||
|
||
// ── cv38: Pro Max тонкая линза (drag предмет + линза, формула, увеличение) ──
|
||
var obj38d = 160;
|
||
var lensPos38 = 0.55; // линза по центру (доля W); можно тянуть мышью
|
||
function reset38() {
|
||
lensPos38 = 0.55;
|
||
var slF = document.getElementById('sl38F'); if (slF) { slF.value = 70; var lf = document.getElementById('lbl38F'); if (lf) lf.textContent = '70 усл.'; }
|
||
var slD = document.getElementById('sl38d'); if (slD) { slD.value = 160; var ld = document.getElementById('lbl38d'); if (ld) ld.textContent = '160 усл.'; }
|
||
var sel = document.getElementById('sel38type'); if (sel) sel.value = 'conv';
|
||
var chk = document.getElementById('chk38r3'); if (chk) chk.checked = true;
|
||
upd38();
|
||
}
|
||
function upd38() {
|
||
var cv = document.getElementById('cv38');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 320;
|
||
cv.width = Math.round(W * dpr); cv.height = Math.round(H * dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0, 0, W, H);
|
||
|
||
var Fval = parseInt((document.getElementById('sl38F') || {}).value) || 70;
|
||
var dval = parseInt((document.getElementById('sl38d') || {}).value) || 160;
|
||
var selT = document.getElementById('sel38type');
|
||
var isDiv = selT && selT.value === 'div';
|
||
var showR3 = !!(document.getElementById('chk38r3') && document.getElementById('chk38r3').checked);
|
||
|
||
// Масштаб: scl пикселей на единицу
|
||
var scl = (W * 0.38) / 300;
|
||
var Fpx = Fval * scl;
|
||
var dpx = dval * scl;
|
||
|
||
// Геометрия
|
||
var lx = W * lensPos38, ly = H / 2;
|
||
// удержим линзу с зазорами под предмет
|
||
lx = Math.max(W * 0.32, Math.min(W * 0.78, lx));
|
||
var f1x = lx - Fpx; // передний фокус F (слева)
|
||
var f2x = lx + Fpx; // задний фокус F' (справа)
|
||
var objX = lx - dpx;
|
||
var objH = Math.min(72, H * 0.26);
|
||
var Ay = ly - objH; // кончик предмета (выше оси)
|
||
|
||
// Формула линзы: 1/F = 1/d + 1/f → f
|
||
var Feff = isDiv ? -Fval : Fval;
|
||
var fImg, isInf=false;
|
||
// 1/Feff = 1/d + 1/f → f = d*F/(d-F)
|
||
var denom = dval - Feff;
|
||
if (Math.abs(denom) < 0.01) { fImg = 1e9; isInf = true; }
|
||
else fImg = Feff * dval / denom;
|
||
var Gamma = -fImg / dval; // линейное увеличение (- = перевёрнутое)
|
||
var fpx = fImg * scl;
|
||
var imgX = lx + fpx;
|
||
var imgYtip = ly - Gamma * objH;
|
||
|
||
var isReal = fImg > 0.5 && isFinite(fImg);
|
||
var isVirt = fImg < -0.5 && isFinite(fImg);
|
||
|
||
// === Сетка-«стол» ===
|
||
ctx.strokeStyle = 'rgba(148,163,184,0.05)'; ctx.lineWidth = 1;
|
||
for (var gx = 0; gx < W; gx += 30) { ctx.beginPath(); ctx.moveTo(gx,0); ctx.lineTo(gx,H); ctx.stroke(); }
|
||
for (var gy = 0; gy < H; gy += 30) { ctx.beginPath(); ctx.moveTo(0,gy); ctx.lineTo(W,gy); ctx.stroke(); }
|
||
|
||
// === Фоновая зона: подсветка области (внутри F / между F и 2F / за 2F) ===
|
||
if (!isDiv) {
|
||
var zc = dpx < Fpx ? 'rgba(124,58,237,0.07)' : dpx < 2*Fpx ? 'rgba(249,115,22,0.05)' : 'rgba(34,197,94,0.05)';
|
||
ctx.fillStyle = zc; ctx.fillRect(0, 0, lx - 1, H);
|
||
ctx.fillStyle = '#475569'; ctx.font = '8.5px sans-serif'; ctx.textAlign = 'left';
|
||
var zoneL = dpx < Fpx ? 'd < F: мнимое, прямое, увелич.' :
|
||
dpx < 2*Fpx ? 'F < d < 2F: действ., перевёрн., увелич.' :
|
||
'd > 2F: действ., перевёрн., уменьш.';
|
||
ctx.fillText(zoneL, 8, 14);
|
||
}
|
||
|
||
// === Главная оптическая ось ===
|
||
ctx.strokeStyle = 'rgba(148,163,184,0.35)'; ctx.lineWidth = 1;
|
||
ctx.beginPath(); ctx.moveTo(0,ly); ctx.lineTo(W,ly); ctx.stroke();
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '9px sans-serif'; ctx.textAlign = 'right';
|
||
ctx.fillText('главная оптическая ось', W - 6, ly - 4);
|
||
// стрелка оси справа
|
||
ctx.fillStyle = 'rgba(148,163,184,0.6)';
|
||
ctx.beginPath(); ctx.moveTo(W - 2, ly); ctx.lineTo(W - 9, ly - 3); ctx.lineTo(W - 9, ly + 3); ctx.fill();
|
||
|
||
// === Фокусы F и F' и точки 2F ===
|
||
function fmark(fx, lbl, primary) {
|
||
var a = primary ? 0.95 : 0.7;
|
||
ctx.fillStyle = 'rgba(251,191,36,' + a + ')';
|
||
ctx.beginPath(); ctx.arc(fx, ly, 5, 0, Math.PI*2); ctx.fill();
|
||
ctx.strokeStyle = 'rgba(15,23,42,0.7)'; ctx.lineWidth = 1;
|
||
ctx.beginPath(); ctx.arc(fx, ly, 5, 0, Math.PI*2); ctx.stroke();
|
||
ctx.fillStyle = 'rgba(251,191,36,0.95)';
|
||
ctx.font = 'bold 11px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText(lbl, fx, ly - 12);
|
||
}
|
||
fmark(f1x, 'F', true);
|
||
fmark(f2x, "F'", true);
|
||
// точки 2F
|
||
[lx - 2*Fpx, lx + 2*Fpx].forEach(function(tf) {
|
||
ctx.fillStyle = 'rgba(251,191,36,0.35)';
|
||
ctx.beginPath(); ctx.arc(tf, ly, 3, 0, Math.PI*2); ctx.fill();
|
||
ctx.fillStyle = 'rgba(251,191,36,0.55)'; ctx.font = '8px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('2F', tf, ly - 8);
|
||
});
|
||
|
||
// === Линза (двояковыпуклая для собирающей, двояковогнутая для рассеивающей) ===
|
||
var lc = isDiv ? '#f97316' : '#a78bfa';
|
||
var lH = H * 0.42;
|
||
// тело линзы (овал/линза-фигура)
|
||
ctx.save();
|
||
if (!isDiv) {
|
||
// двояковыпуклая
|
||
var grdL = ctx.createLinearGradient(lx-12, 0, lx+12, 0);
|
||
grdL.addColorStop(0, 'rgba(167,139,250,0.06)');
|
||
grdL.addColorStop(0.5, 'rgba(167,139,250,0.28)');
|
||
grdL.addColorStop(1, 'rgba(167,139,250,0.06)');
|
||
ctx.fillStyle = grdL;
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lH/2);
|
||
ctx.quadraticCurveTo(lx + 18, ly, lx, ly + lH/2);
|
||
ctx.quadraticCurveTo(lx - 18, ly, lx, ly - lH/2);
|
||
ctx.fill();
|
||
ctx.strokeStyle = lc; ctx.lineWidth = 2;
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lH/2);
|
||
ctx.quadraticCurveTo(lx + 18, ly, lx, ly + lH/2);
|
||
ctx.stroke();
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ly - lH/2);
|
||
ctx.quadraticCurveTo(lx - 18, ly, lx, ly + lH/2);
|
||
ctx.stroke();
|
||
// стрелки-указатели «собирающая» (двусторонние)
|
||
ctx.fillStyle = lc;
|
||
ctx.beginPath(); ctx.moveTo(lx, ly-lH/2-3); ctx.lineTo(lx-5,ly-lH/2+7); ctx.lineTo(lx+5,ly-lH/2+7); ctx.fill();
|
||
ctx.beginPath(); ctx.moveTo(lx, ly+lH/2+3); ctx.lineTo(lx-5,ly+lH/2-7); ctx.lineTo(lx+5,ly+lH/2-7); ctx.fill();
|
||
} else {
|
||
// двояковогнутая
|
||
ctx.fillStyle = 'rgba(249,115,22,0.18)';
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx - 10, ly - lH/2);
|
||
ctx.lineTo(lx + 10, ly - lH/2);
|
||
ctx.quadraticCurveTo(lx, ly, lx + 10, ly + lH/2);
|
||
ctx.lineTo(lx - 10, ly + lH/2);
|
||
ctx.quadraticCurveTo(lx, ly, lx - 10, ly - lH/2);
|
||
ctx.fill();
|
||
ctx.strokeStyle = lc; ctx.lineWidth = 2;
|
||
ctx.beginPath(); ctx.moveTo(lx-10,ly-lH/2); ctx.lineTo(lx+10,ly-lH/2); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(lx-10,ly+lH/2); ctx.lineTo(lx+10,ly+lH/2); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(lx-10,ly-lH/2); ctx.quadraticCurveTo(lx, ly, lx-10, ly+lH/2); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(lx+10,ly-lH/2); ctx.quadraticCurveTo(lx, ly, lx+10, ly+lH/2); ctx.stroke();
|
||
// стрелки-указатели «рассеивающая»
|
||
ctx.fillStyle = lc;
|
||
ctx.beginPath(); ctx.moveTo(lx-10,ly-lH/2); ctx.lineTo(lx-14,ly-lH/2+8); ctx.lineTo(lx-6,ly-lH/2+8); ctx.fill();
|
||
ctx.beginPath(); ctx.moveTo(lx+10,ly-lH/2); ctx.lineTo(lx+14,ly-lH/2+8); ctx.lineTo(lx+6,ly-lH/2+8); ctx.fill();
|
||
}
|
||
ctx.restore();
|
||
// оптический центр O
|
||
ctx.fillStyle = '#fff';
|
||
ctx.beginPath(); ctx.arc(lx, ly, 3, 0, Math.PI*2); ctx.fill();
|
||
ctx.strokeStyle = lc; ctx.lineWidth = 1;
|
||
ctx.beginPath(); ctx.arc(lx, ly, 3, 0, Math.PI*2); ctx.stroke();
|
||
ctx.fillStyle = lc; ctx.font = 'bold 9px sans-serif'; ctx.textAlign = 'left';
|
||
ctx.fillText('O', lx + 6, ly + 12);
|
||
ctx.fillStyle = lc; ctx.font = 'bold 9px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText(isDiv ? 'Рассеивающая' : 'Собирающая', lx, ly - lH/2 - 12);
|
||
// hint «drag»
|
||
ctx.fillStyle = 'rgba(255,255,255,0.35)'; ctx.font = '8px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('⇔ drag', lx, ly + lH/2 + 12);
|
||
|
||
// === Предмет AB (стрелка ↑) ===
|
||
ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 3;
|
||
ctx.beginPath(); ctx.moveTo(objX, ly); ctx.lineTo(objX, Ay); ctx.stroke();
|
||
ctx.fillStyle = '#fbbf24';
|
||
ctx.beginPath(); ctx.moveTo(objX, Ay - 10); ctx.lineTo(objX - 6, Ay + 2); ctx.lineTo(objX + 6, Ay + 2); ctx.fill();
|
||
// drag-«ручка» — кружок на кончике
|
||
ctx.fillStyle = 'rgba(251,191,36,0.85)';
|
||
ctx.beginPath(); ctx.arc(objX, Ay - 4, 6, 0, Math.PI*2); ctx.fill();
|
||
ctx.strokeStyle = '#fff'; ctx.lineWidth = 1.5;
|
||
ctx.beginPath(); ctx.arc(objX, Ay - 4, 6, 0, Math.PI*2); ctx.stroke();
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = 'bold 10px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('B', objX, Ay - 14);
|
||
ctx.fillStyle = '#fbbf24'; ctx.font = 'bold 10px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText('A', objX, ly + 14);
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '8.5px sans-serif';
|
||
ctx.fillText('d=' + dval, objX, ly + 26);
|
||
|
||
// === ТРАССИРОВКА ЛУЧЕЙ ===
|
||
var EDGE = W + 40;
|
||
function yAt(x1,y1,x2,y2,toX) {
|
||
if (Math.abs(x2-x1) < 0.001) return y1;
|
||
return y1 + (y2-y1)*(toX-x1)/(x2-x1);
|
||
}
|
||
function seg(x1,y1,x2,y2,col,dsh,lw) {
|
||
if (isNaN(y1)||isNaN(y2)) return;
|
||
ctx.strokeStyle = col; ctx.lineWidth = lw||1.8;
|
||
ctx.setLineDash(dsh ? [5,4] : []);
|
||
ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
}
|
||
var Ax = objX;
|
||
|
||
// ── ЛУЧ 1 (красный): || оси → через F' ──
|
||
seg(Ax, Ay, lx, Ay, '#ef4444');
|
||
if (!isDiv) {
|
||
if (isReal) {
|
||
var r1iy = yAt(lx,Ay,f2x,ly,imgX);
|
||
seg(lx, Ay, imgX, r1iy, '#ef4444');
|
||
seg(imgX, r1iy, EDGE, yAt(lx,Ay,f2x,ly,EDGE), 'rgba(239,68,68,0.18)', false, 1);
|
||
} else if (isVirt) {
|
||
seg(lx, Ay, EDGE, yAt(lx,Ay,f2x,ly,EDGE), '#ef4444');
|
||
seg(lx, Ay, imgX, yAt(lx,Ay,f2x,ly,imgX), 'rgba(239,68,68,0.45)', true, 1.5);
|
||
} else {
|
||
seg(lx, Ay, EDGE, yAt(lx,Ay,f2x,ly,EDGE), '#ef4444');
|
||
}
|
||
} else {
|
||
// рассеивающая: после линзы луч расходится, как из F (того, что слева)
|
||
var r1slope = (Ay - ly) / (lx - f1x + 0.001);
|
||
var r1ey = Ay + r1slope * (EDGE - lx);
|
||
seg(lx, Ay, EDGE, r1ey, '#ef4444');
|
||
if (isVirt) seg(lx, Ay, imgX, yAt(f1x,ly,lx,Ay,imgX), 'rgba(239,68,68,0.45)', true, 1.5);
|
||
}
|
||
|
||
// ── ЛУЧ 2 (зелёный): через оптический центр O — без преломления ──
|
||
seg(Ax, Ay, lx, ly, '#22c55e');
|
||
if (isReal) {
|
||
var r2iy = yAt(Ax,Ay,lx,ly,imgX);
|
||
seg(lx, ly, imgX, r2iy, '#22c55e');
|
||
seg(imgX, r2iy, EDGE, yAt(Ax,Ay,lx,ly,EDGE), 'rgba(34,197,94,0.18)', false, 1);
|
||
} else if (isVirt) {
|
||
seg(lx, ly, EDGE, yAt(Ax,Ay,lx,ly,EDGE), '#22c55e');
|
||
seg(lx, ly, imgX, yAt(Ax,Ay,lx,ly,imgX), 'rgba(34,197,94,0.45)', true, 1.5);
|
||
} else {
|
||
seg(lx, ly, EDGE, yAt(Ax,Ay,lx,ly,EDGE), '#22c55e');
|
||
}
|
||
|
||
// ── ЛУЧ 3 (оранжевый): через F → после линзы || оси ──
|
||
if (showR3 && !isDiv && dpx > Fpx * 0.05) {
|
||
var r3yL = yAt(Ax, Ay, f1x, ly, lx);
|
||
seg(Ax, Ay, lx, r3yL, '#f97316');
|
||
if (isReal) {
|
||
seg(lx, r3yL, imgX, r3yL, '#f97316');
|
||
seg(imgX, r3yL, EDGE, r3yL, 'rgba(249,115,22,0.18)', false, 1);
|
||
} else if (isVirt) {
|
||
seg(lx, r3yL, EDGE, r3yL, '#f97316');
|
||
seg(lx, r3yL, imgX, r3yL, 'rgba(249,115,22,0.45)', true, 1.5);
|
||
} else {
|
||
seg(lx, r3yL, EDGE, r3yL, '#f97316');
|
||
}
|
||
}
|
||
|
||
// === Изображение A'B' (сплошное действ. / пунктир мнимое) ===
|
||
if (!isInf && Math.abs(fpx) < W*1.2 && Math.abs(imgYtip-ly) < H*0.98) {
|
||
var ic = isReal ? '#3b82f6' : 'rgba(147,197,253,0.85)';
|
||
ctx.strokeStyle = ic; ctx.lineWidth = isReal ? 3 : 2;
|
||
if (isVirt) ctx.setLineDash([5,4]);
|
||
ctx.beginPath(); ctx.moveTo(imgX, ly); ctx.lineTo(imgX, imgYtip); ctx.stroke();
|
||
ctx.fillStyle = ic;
|
||
var ad = (imgYtip < ly) ? -1 : 1;
|
||
ctx.beginPath();
|
||
ctx.moveTo(imgX, imgYtip + ad*10);
|
||
ctx.lineTo(imgX - 6, imgYtip - ad*2);
|
||
ctx.lineTo(imgX + 6, imgYtip - ad*2);
|
||
ctx.fill();
|
||
ctx.setLineDash([]);
|
||
ctx.fillStyle = ic; ctx.font = 'bold 10px sans-serif'; ctx.textAlign = 'center';
|
||
ctx.fillText("B'", imgX, imgYtip + (ad < 0 ? -8 : 18));
|
||
ctx.fillText("A'", imgX, ly + (ad < 0 ? 14 : -6));
|
||
ctx.fillStyle = '#94a3b8'; ctx.font = '8.5px sans-serif';
|
||
ctx.fillText("f=" + Math.round(fImg), imgX, ly + (ad < 0 ? 26 : -18));
|
||
}
|
||
|
||
// === Подписи d, f под осью (от линзы) ===
|
||
ctx.strokeStyle = 'rgba(251,191,36,0.5)'; ctx.lineWidth = 1; ctx.setLineDash([3,3]);
|
||
ctx.beginPath(); ctx.moveTo(objX, ly + 30); ctx.lineTo(lx, ly + 30); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
|
||
// === Чипы: формула линзы, увеличение, тип ===
|
||
var cLens = document.getElementById('chip38lens');
|
||
var cMag = document.getElementById('chip38mag');
|
||
var cType = document.getElementById('chip38type');
|
||
if (cLens) {
|
||
if (isInf) cLens.textContent = 'd = F → 1/F = 1/d + 0 → f = ∞';
|
||
else {
|
||
// 1/F = 1/d + 1/f → подставим числа
|
||
var fR = Math.round(fImg);
|
||
cLens.textContent = '1/' + Feff + ' = 1/' + dval + ' + 1/' + fR;
|
||
}
|
||
}
|
||
if (cMag) {
|
||
if (isInf) {
|
||
cMag.textContent = "Γ → ∞";
|
||
} else {
|
||
var absG = Math.abs(Gamma);
|
||
cMag.textContent = "Γ = f/d = " + absG.toFixed(2);
|
||
// зелёный/синий/серый — увеличение/уменьшение/равное
|
||
if (absG > 1.05) { cMag.style.background='rgba(34,197,94,.12)'; cMag.style.color='#16a34a'; cMag.style.borderColor='rgba(34,197,94,.3)'; }
|
||
else if (absG < 0.95) { cMag.style.background='rgba(59,130,246,.12)'; cMag.style.color='#1d4ed8'; cMag.style.borderColor='rgba(59,130,246,.3)'; }
|
||
else { cMag.style.background='rgba(148,163,184,.15)'; cMag.style.color='#475569'; cMag.style.borderColor='rgba(148,163,184,.3)'; }
|
||
}
|
||
}
|
||
if (cType) {
|
||
var t1 = isReal ? 'действ.' : (isVirt ? 'мнимое' : '∞');
|
||
var t2 = Gamma < 0 ? 'перевёрн.' : 'прямое';
|
||
cType.textContent = t1 + ', ' + t2;
|
||
}
|
||
|
||
// === Текстовый результат ===
|
||
var res = document.getElementById('res38');
|
||
if (res) {
|
||
if (isInf) {
|
||
res.textContent = 'd = F = ' + Fval + ' → лучи параллельны, изображение на ∞';
|
||
} else {
|
||
var t1r = isReal ? 'действительное' : 'мнимое';
|
||
var t2r = Gamma < 0 ? 'перевёрнутое' : 'прямое';
|
||
var absG2 = Math.abs(Gamma);
|
||
var t3r = absG2 > 1.05 ? 'увеличенное' : absG2 < 0.95 ? 'уменьшенное' : 'равное';
|
||
res.textContent = 'd=' + dval + ', F=' + Feff + ' → f=' + Math.round(fImg) + ' | ' + t1r + ', ' + t2r + ', ' + t3r + ' (Γ=' + absG2.toFixed(2) + ')';
|
||
}
|
||
}
|
||
}
|
||
|
||
// Mouse / touch drag для cv38: за стрелку-предмет или за линзу
|
||
(function() {
|
||
var dragging38 = null; // 'obj' | 'lens' | null
|
||
function setup38() {
|
||
var cv = document.getElementById('cv38');
|
||
if (!cv) return;
|
||
function pick(e) {
|
||
var rect = cv.getBoundingClientRect();
|
||
var x = e.clientX - rect.left, y = e.clientY - rect.top;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 320;
|
||
var ly = H / 2;
|
||
var lx = Math.max(W*0.32, Math.min(W*0.78, W * lensPos38));
|
||
var scl = (W * 0.38) / 300;
|
||
var dval = parseInt((document.getElementById('sl38d')||{}).value) || 160;
|
||
var objX = lx - dval * scl;
|
||
// приоритет — предмет (если рядом по x), иначе линза
|
||
if (Math.abs(x - objX) < 22) return {mode: 'obj', x: x, y: y, W: W, lx: lx, scl: scl};
|
||
if (Math.abs(x - lx) < 18) return {mode: 'lens', x: x, y: y, W: W, lx: lx, scl: scl};
|
||
return null;
|
||
}
|
||
function move(e) {
|
||
if (!dragging38) return;
|
||
var rect = cv.getBoundingClientRect();
|
||
var x = e.clientX - rect.left;
|
||
var W = cv.offsetWidth;
|
||
if (dragging38 === 'lens') {
|
||
lensPos38 = Math.max(0.32, Math.min(0.78, x / W));
|
||
} else if (dragging38 === 'obj') {
|
||
var lx = Math.max(W*0.32, Math.min(W*0.78, W * lensPos38));
|
||
var scl = (W * 0.38) / 300;
|
||
var d = Math.round(Math.max(10, Math.min(300, (lx - x) / scl)));
|
||
var sl = document.getElementById('sl38d');
|
||
if (sl) {
|
||
sl.value = d;
|
||
var lb = document.getElementById('lbl38d');
|
||
if (lb) lb.textContent = d + ' усл.';
|
||
}
|
||
}
|
||
upd38();
|
||
}
|
||
cv.addEventListener('mousedown', function(e) {
|
||
var p = pick(e);
|
||
if (p) { dragging38 = p.mode; cv.style.cursor = 'grabbing'; move(e); }
|
||
});
|
||
cv.addEventListener('mousemove', function(e) {
|
||
if (dragging38) { move(e); return; }
|
||
var p = pick(e);
|
||
cv.style.cursor = p ? 'grab' : 'crosshair';
|
||
});
|
||
cv.addEventListener('mouseup', function() { dragging38 = null; cv.style.cursor = 'grab'; });
|
||
cv.addEventListener('mouseleave', function() { dragging38 = null; cv.style.cursor = 'grab'; });
|
||
cv.addEventListener('touchstart', function(e) {
|
||
if (!e.touches.length) return;
|
||
var p = pick(e.touches[0]);
|
||
if (p) { dragging38 = p.mode; move(e.touches[0]); e.preventDefault(); }
|
||
}, {passive:false});
|
||
cv.addEventListener('touchmove', function(e) {
|
||
if (dragging38 && e.touches.length) { move(e.touches[0]); e.preventDefault(); }
|
||
}, {passive:false});
|
||
cv.addEventListener('touchend', function() { dragging38 = null; });
|
||
}
|
||
if (document.readyState === 'complete') setup38();
|
||
else window.addEventListener('load', setup38);
|
||
})();
|
||
function upd39() {
|
||
var cv = document.getElementById('cv39');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 240;
|
||
cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr,0,0,dpr,0,0);
|
||
ctx.fillStyle = '#0f172a'; ctx.fillRect(0,0,W,H);
|
||
|
||
var d = parseInt((document.getElementById('sl39d')||{}).value)||50;
|
||
// Normalize: 15cm → max bulge; 200cm → flat
|
||
var bulge = Math.max(3, 22 - (d - 15) * 19 / 185);
|
||
var lensAccom = bulge; // more bulge = shorter F
|
||
var ey = H/2, ex = W * 0.55;
|
||
var eyeRx = W * 0.18, eyeRy = H * 0.38;
|
||
|
||
// Eye outline
|
||
ctx.strokeStyle = '#a78bfa'; ctx.lineWidth = 2;
|
||
ctx.beginPath(); ctx.ellipse(ex, ey, eyeRx, eyeRy, 0, 0, Math.PI*2); ctx.stroke();
|
||
ctx.fillStyle = 'rgba(124,58,237,0.05)'; ctx.fill();
|
||
|
||
// Cornea (left side, fixed)
|
||
ctx.strokeStyle = '#38bdf8'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath();
|
||
ctx.moveTo(ex - eyeRx, ey - 22);
|
||
ctx.quadraticCurveTo(ex - eyeRx - 12, ey, ex - eyeRx, ey + 22);
|
||
ctx.stroke();
|
||
|
||
// Lens (variable bulge for accommodation)
|
||
var lx = ex - eyeRx + 28;
|
||
ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ey - 20);
|
||
ctx.quadraticCurveTo(lx + lensAccom, ey, lx, ey + 20);
|
||
ctx.stroke();
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx + 8, ey - 20);
|
||
ctx.quadraticCurveTo(lx + 8 - lensAccom, ey, lx + 8, ey + 20);
|
||
ctx.stroke();
|
||
ctx.fillStyle = 'rgba(251,191,36,0.12)';
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx, ey-20); ctx.quadraticCurveTo(lx+lensAccom, ey, lx, ey+20);
|
||
ctx.lineTo(lx+8, ey+20); ctx.quadraticCurveTo(lx+8-lensAccom, ey, lx+8, ey-20); ctx.fill();
|
||
|
||
// Retina (right side)
|
||
ctx.strokeStyle = '#22c55e'; ctx.lineWidth = 2.5;
|
||
ctx.beginPath();
|
||
ctx.moveTo(ex + eyeRx - 5, ey - 30);
|
||
ctx.quadraticCurveTo(ex + eyeRx + 8, ey, ex + eyeRx - 5, ey + 30);
|
||
ctx.stroke();
|
||
|
||
// Optical axis
|
||
ctx.strokeStyle = 'rgba(148,163,184,0.2)'; ctx.lineWidth=1;
|
||
ctx.beginPath(); ctx.moveTo(0,ey); ctx.lineTo(W,ey); ctx.stroke();
|
||
|
||
// Object (left)
|
||
var objX = ex - eyeRx - Math.min(W*0.35, d*2.2);
|
||
if (objX < 10) objX = 10;
|
||
ctx.strokeStyle = '#fbbf24'; ctx.lineWidth=2.5;
|
||
ctx.beginPath(); ctx.moveTo(objX, ey); ctx.lineTo(objX, ey-30); ctx.stroke();
|
||
ctx.fillStyle='#fbbf24';
|
||
ctx.beginPath(); ctx.moveTo(objX,ey-36); ctx.lineTo(objX-4,ey-26); ctx.lineTo(objX+4,ey-26); ctx.fill();
|
||
ctx.font='8px sans-serif'; ctx.textAlign='center'; ctx.fillStyle='#fbbf24';
|
||
ctx.fillText(d + ' см', objX, ey+16);
|
||
|
||
// Rays converge on retina
|
||
var retinaX = ex + eyeRx - 5;
|
||
ctx.strokeStyle = 'rgba(59,130,246,0.7)'; ctx.lineWidth=1.5;
|
||
ctx.beginPath(); ctx.moveTo(objX, ey-28); ctx.lineTo(lx+4, ey-15); ctx.lineTo(retinaX, ey + (d<50?12:d<100?5:0)); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(objX, ey+2); ctx.lineTo(lx+4, ey+10); ctx.lineTo(retinaX, ey - (d<50?12:d<100?5:0)); ctx.stroke();
|
||
|
||
// Labels
|
||
ctx.fillStyle='#38bdf8'; ctx.font='8px sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText('роговица', ex-eyeRx-3, ey-eyeRy+14);
|
||
ctx.fillStyle='#fbbf24';
|
||
ctx.fillText('хрусталик', lx+4, ey-22);
|
||
ctx.fillStyle='#22c55e';
|
||
ctx.fillText('сетчатка', retinaX+22, ey);
|
||
ctx.fillStyle = d<25 ? '#ef4444' : d>150 ? '#22c55e' : '#fbbf24';
|
||
ctx.font='bold 9px sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText(d<25 ? '⚠️ Очень близко — напряжение!' : d<50 ? 'Хрусталик выпуклый (F мал)' : d<120 ? 'Хрусталик средний' : 'Хрусталик плоский (F велик)', W/2, H-10);
|
||
|
||
var res=document.getElementById('res39');
|
||
if(res) res.textContent = 'Расстояние: ' + d + ' см | хрусталик ' + (d<40?'сильно выпуклый, D↑':d<80?'нормальный':'плоский, D↓');
|
||
}
|
||
function startAnim39() { upd39(); }
|
||
|
||
function upd40() {
|
||
var cv = document.getElementById('cv40');
|
||
if (!cv || cv.offsetWidth === 0) return;
|
||
var dpr = window.devicePixelRatio || 1;
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || 260;
|
||
cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr,0,0,dpr,0,0);
|
||
ctx.fillStyle='#0f172a'; ctx.fillRect(0,0,W,H);
|
||
|
||
var sel=document.getElementById('sel40def');
|
||
var defect=sel?sel.value:'normal';
|
||
var glasses=document.getElementById('chk40glasses')&&document.getElementById('chk40glasses').checked;
|
||
var Dgl=parseFloat((document.getElementById('sl40D')||{}).value)||-2;
|
||
|
||
var ey=H/2, ex=W*0.62, eyeRx=W*0.16, eyeRy=H*0.32;
|
||
|
||
// Defect offsets: where focus actually lands
|
||
var focusOffset = defect==='myopia' ? -eyeRx*0.25 : defect==='hyperopia' ? eyeRx*0.25 : 0;
|
||
if (glasses) {
|
||
// Glasses correct the focus
|
||
var correction = -Dgl * eyeRx * 0.06;
|
||
focusOffset = Math.max(-eyeRx*0.3, Math.min(eyeRx*0.3, focusOffset + correction));
|
||
}
|
||
var retinaX = ex + eyeRx - 8;
|
||
var focusX = retinaX + focusOffset;
|
||
|
||
// Eye outline
|
||
ctx.strokeStyle='#a78bfa'; ctx.lineWidth=2;
|
||
ctx.beginPath(); ctx.ellipse(ex,ey,eyeRx,eyeRy,0,0,Math.PI*2); ctx.stroke();
|
||
|
||
// Shape of eye (myopia = elongated)
|
||
if (defect==='myopia') {
|
||
ctx.strokeStyle='rgba(239,68,68,0.4)'; ctx.lineWidth=1.5; ctx.setLineDash([4,3]);
|
||
ctx.beginPath(); ctx.ellipse(ex+4,ey,eyeRx+6,eyeRy,0,0,Math.PI*2); ctx.stroke();
|
||
ctx.setLineDash([]);
|
||
}
|
||
|
||
// Glasses (if worn)
|
||
if (glasses) {
|
||
var glassX = ex - eyeRx - 25;
|
||
var gColor = Dgl<0 ? '#f97316' : '#22c55e';
|
||
ctx.strokeStyle=gColor; ctx.lineWidth=2.5;
|
||
// Simple lens representation
|
||
if (Dgl < 0) {
|
||
ctx.beginPath(); ctx.moveTo(glassX, ey-18); ctx.quadraticCurveTo(glassX-8,ey,glassX,ey+18); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(glassX+6, ey-18); ctx.quadraticCurveTo(glassX+14,ey,glassX+6,ey+18); ctx.stroke();
|
||
} else {
|
||
ctx.beginPath(); ctx.moveTo(glassX, ey-18); ctx.quadraticCurveTo(glassX+10,ey,glassX,ey+18); ctx.stroke();
|
||
ctx.beginPath(); ctx.moveTo(glassX+6, ey-18); ctx.quadraticCurveTo(glassX-4,ey,glassX+6,ey+18); ctx.stroke();
|
||
}
|
||
ctx.fillStyle=gColor; ctx.font='8px sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText((Dgl>0?'+':'')+Dgl+' дптр', glassX+3, ey+28);
|
||
}
|
||
|
||
// Cornea/lens (simplified)
|
||
var lx = ex - eyeRx + 12;
|
||
ctx.strokeStyle='#fbbf24'; ctx.lineWidth=2.5;
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx,ey-18); ctx.quadraticCurveTo(lx+10,ey,lx,ey+18); ctx.stroke();
|
||
ctx.beginPath();
|
||
ctx.moveTo(lx+8,ey-18); ctx.quadraticCurveTo(lx-2,ey,lx+8,ey+18); ctx.stroke();
|
||
|
||
// Retina
|
||
ctx.strokeStyle='#22c55e'; ctx.lineWidth=2.5;
|
||
ctx.beginPath();
|
||
ctx.moveTo(retinaX, ey-eyeRy+8);
|
||
ctx.quadraticCurveTo(retinaX+6,ey,retinaX,ey+eyeRy-8);
|
||
ctx.stroke();
|
||
|
||
// Rays converging to focusX
|
||
var nR=5;
|
||
for(var ri=0;ri<nR;ri++) {
|
||
var ry = ey-20 + ri*10;
|
||
var atFocus = focusX;
|
||
// Color: green=on retina, red=not
|
||
var onRetina = Math.abs(focusX - retinaX) < 8;
|
||
ctx.strokeStyle = onRetina ? 'rgba(34,197,94,0.8)' : ri%2===0?'rgba(59,130,246,0.7)':'rgba(239,68,68,0.6)';
|
||
ctx.lineWidth=1.5;
|
||
ctx.beginPath(); ctx.moveTo(ex-eyeRx-40, ry); ctx.lineTo(lx+4,ry);
|
||
// After lens → converge to focus
|
||
ctx.lineTo(atFocus, ey);
|
||
// If focus behind retina — continue
|
||
if (atFocus > retinaX+2) {
|
||
ctx.setLineDash([3,3]);
|
||
ctx.lineTo(atFocus+40, ey + (ey-ry));
|
||
ctx.setLineDash([]);
|
||
}
|
||
ctx.stroke();
|
||
}
|
||
|
||
// Focus dot
|
||
var focusColor = Math.abs(focusX - retinaX) < 8 ? '#22c55e' : '#ef4444';
|
||
ctx.fillStyle=focusColor;
|
||
ctx.beginPath(); ctx.arc(focusX,ey,6,0,Math.PI*2); ctx.fill();
|
||
ctx.fillStyle='#fff'; ctx.font='8px sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText('F', focusX, ey+4);
|
||
|
||
// Status text
|
||
var onR = Math.abs(focusX - retinaX) < 10;
|
||
var statusColor = onR ? '#22c55e' : '#ef4444';
|
||
ctx.fillStyle=statusColor; ctx.font='bold 10px sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText(onR ? '✓ Фокус на сетчатке — чёткое зрение' :
|
||
focusX < retinaX ? '✗ Фокус перед сетчаткой — размыто (близорукость)' :
|
||
'✗ Фокус за сетчаткой — размыто (дальнозоркость)', W/2, H-12);
|
||
|
||
// Labels
|
||
ctx.fillStyle='#fbbf24'; ctx.font='8px sans-serif'; ctx.textAlign='center';
|
||
ctx.fillText('линза', lx+4, ey+30);
|
||
ctx.fillStyle='#22c55e'; ctx.fillText('сетчатка', retinaX+22, ey-eyeRy+5);
|
||
|
||
var res=document.getElementById('res40');
|
||
if(res) res.textContent = (defect==='normal'?'Норма':(defect==='myopia'?'Близорукость':'Дальнозоркость')) +
|
||
(glasses?' + очки '+Dgl+' дптр':'') + (onR?' → фокус на сетчатке ✓':' → фокус не на сетчатке ✗');
|
||
}
|
||
function startAnim40() { upd40(); }
|
||
|
||
// ═══════════════════════════════════════
|
||
// ИНИЦИАЛИЗАЦИЯ
|
||
// ═══════════════════════════════════════
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// тема
|
||
if (localStorage.getItem('phys8_o_theme')==='dark') document.documentElement.classList.add('dark');
|
||
document.getElementById('themeBtn').onclick = function() {
|
||
document.documentElement.classList.toggle('dark');
|
||
var isDark = document.documentElement.classList.contains('dark');
|
||
localStorage.setItem('phys8_o_theme', isDark?'dark':'light');
|
||
this.querySelector('i').className = isDark ? 'fas fa-sun' : 'fas fa-moon';
|
||
};
|
||
// Установить начальную иконку темы
|
||
(function(){
|
||
var isDark = document.documentElement.classList.contains('dark');
|
||
var ic = document.querySelector('#themeBtn i');
|
||
if(ic) ic.className = isDark ? 'fas fa-sun' : 'fas fa-moon';
|
||
})();
|
||
|
||
// sidebar навигация
|
||
var tabFnsO = {
|
||
'ref32': function(){ setTimeout(function(){ if(typeof startAnim32==='function' && !anim32Id) startAnim32(); }, 60); },
|
||
'ref33': function(){ setTimeout(function(){ if(typeof startAnim33==='function' && !anim33Id) startAnim33(); }, 60); },
|
||
'ref34': function(){ setTimeout(function(){ if(typeof upd34==='function') upd34(); }, 60); },
|
||
'ref35': function(){ setTimeout(function(){ if(typeof upd35==='function') upd35(); }, 60); },
|
||
'ref36': function(){ setTimeout(function(){ if(typeof upd36==='function') upd36(); }, 60); },
|
||
'ref37': function(){ setTimeout(function(){ if(typeof upd37==='function') upd37(); }, 60); },
|
||
'ref38': function(){ setTimeout(function(){ if(typeof upd38==='function') upd38(); }, 60); },
|
||
'ref39': function(){ setTimeout(function(){ if(typeof startAnim39==='function' && !anim39Id) startAnim39(); }, 60); },
|
||
'ref40': function(){ setTimeout(function(){ if(typeof startAnim40==='function' && !anim40Id) startAnim40(); }, 60); }
|
||
};
|
||
|
||
function activateSection(target) {
|
||
document.querySelectorAll('.sb-item').forEach(function(b){ b.classList.remove('active'); });
|
||
document.querySelectorAll('.content').forEach(function(c){ c.classList.remove('active'); });
|
||
var btn = document.querySelector('.sb-item[data-target="'+target+'"]');
|
||
if(btn) btn.classList.add('active');
|
||
var cont = document.getElementById('tab-'+target);
|
||
if(cont) cont.classList.add('active');
|
||
if(tabFnsO[target]) tabFnsO[target]();
|
||
// Прокрутить main-col вверх
|
||
var mc = document.querySelector('.main-col');
|
||
if(mc) mc.scrollTop = 0;
|
||
else window.scrollTo({top:0,behavior:'smooth'});
|
||
}
|
||
|
||
document.querySelectorAll('.sb-item').forEach(function(btn) {
|
||
btn.onclick = function() {
|
||
activateSection(this.dataset.target);
|
||
};
|
||
});
|
||
|
||
// переключение вкладок ref-panel
|
||
window.switchRefTab = function(name) {
|
||
document.querySelectorAll('.ref-tab-btn').forEach(function(b){ b.classList.remove('active'); });
|
||
document.querySelectorAll('.ref-tab-content').forEach(function(c){ c.classList.remove('active'); });
|
||
var btn = document.querySelector('.ref-tab-btn[onclick*="\''+name+'\'"]');
|
||
if (btn) btn.classList.add('active');
|
||
var cont = document.getElementById('reftab-'+name);
|
||
if (cont) cont.classList.add('active');
|
||
// render KaTeX в шпаргалке при первом открытии
|
||
if (name === 'cheat' && cont && !cont.dataset.katexDone) {
|
||
cont.dataset.katexDone = '1';
|
||
if (window.renderMathInElement) renderMathInElement(cont, {
|
||
delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
|
||
throwOnError:false
|
||
});
|
||
}
|
||
};
|
||
|
||
// refPanel (popup)
|
||
var refRendered = false;
|
||
document.getElementById('refToggle').onclick = function(e) {
|
||
e.stopPropagation();
|
||
var panel = document.getElementById('refPanel');
|
||
panel.classList.toggle('show');
|
||
if (!refRendered && panel.classList.contains('show')) {
|
||
refRendered = true;
|
||
if (window.renderMathInElement) renderMathInElement(panel, {
|
||
delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
|
||
throwOnError:false
|
||
});
|
||
}
|
||
};
|
||
// Закрытие при клике вне панели
|
||
document.addEventListener('click', function(e) {
|
||
var panel = document.getElementById('refPanel');
|
||
var toggle = document.getElementById('refToggle');
|
||
if(panel && panel.classList.contains('show') && !panel.contains(e.target) && e.target !== toggle) {
|
||
panel.classList.remove('show');
|
||
}
|
||
});
|
||
|
||
// задачи — инит
|
||
['p32','p33','p34','p35','p36','p37','p38','p39','p40','hard'].forEach(function(sec) {
|
||
renderTask(sec);
|
||
});
|
||
setParaTab('p32');
|
||
|
||
// KaTeX
|
||
if (window.renderMathInElement) {
|
||
renderMathInElement(document.body, {
|
||
delimiters:[{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
|
||
throwOnError:false
|
||
});
|
||
}
|
||
|
||
// первоначальный запуск
|
||
setTimeout(function(){ startAnim32(); }, 200);
|
||
|
||
// ═══════════ PRO MAX UPGRADE ИНИЦИАЛИЗАЦИЯ ═══════════
|
||
initProMaxUpgrade();
|
||
});
|
||
|
||
// ═══════════════════════════════════════
|
||
// PRO MAX UPGRADE: инфра motion + UX
|
||
// ═══════════════════════════════════════
|
||
function initProMaxUpgrade(){
|
||
// 0. Авто-инжекция ph-glow и ph-badge в каждый hero
|
||
document.querySelectorAll('.para-hero').forEach(function(hero, i){
|
||
if(!hero.querySelector('.ph-glow')){
|
||
var g = document.createElement('span');
|
||
g.className = 'ph-glow';
|
||
hero.appendChild(g);
|
||
}
|
||
if(!hero.querySelector('.ph-badge')){
|
||
// определить номер § из class ph-N
|
||
var n = '';
|
||
hero.classList.forEach(function(c){ var m=/^ph-(\d+)$/.exec(c); if(m) n='§'+m[1]; });
|
||
if(!n) n='§'+(i+1);
|
||
var b = document.createElement('div');
|
||
b.className = 'ph-badge';
|
||
b.innerHTML = '<i class="fas fa-bookmark" style="font-size:.6rem;margin-right:4px"></i>'+n;
|
||
hero.appendChild(b);
|
||
}
|
||
});
|
||
|
||
// 1. IntersectionObserver — fade-up для секций при скролле
|
||
try{
|
||
var io = new IntersectionObserver(function(entries){
|
||
entries.forEach(function(e){
|
||
if(e.isIntersecting){ e.target.classList.add('is-in'); io.unobserve(e.target); }
|
||
});
|
||
},{threshold:.12,rootMargin:'0px 0px -40px 0px'});
|
||
document.querySelectorAll('.content > *').forEach(function(el){
|
||
// не трогаем para-hero — у него своя анимация
|
||
if(el.classList.contains('para-hero')) return;
|
||
el.classList.add('fx-rise');
|
||
io.observe(el);
|
||
});
|
||
document.querySelectorAll('.formula-grid, .life-grid, .idiag-2col').forEach(function(el){
|
||
el.classList.add('fx-stagger');
|
||
io.observe(el);
|
||
});
|
||
}catch(_){/* no-op */}
|
||
|
||
// 2. Mousemove параллакс на ::after шар у hero
|
||
document.querySelectorAll('.para-hero').forEach(function(hero){
|
||
hero.addEventListener('mousemove', function(e){
|
||
var r = hero.getBoundingClientRect();
|
||
var dx = (e.clientX - r.left - r.width/2) / r.width;
|
||
var dy = (e.clientY - r.top - r.height/2) / r.height;
|
||
hero.style.setProperty('--phx', (dx*12).toFixed(2)+'px');
|
||
hero.style.setProperty('--phy', (dy*8).toFixed(2)+'px');
|
||
});
|
||
});
|
||
|
||
// 3. Карточки формул: glow-курсор
|
||
document.querySelectorAll('.fcard').forEach(function(card){
|
||
card.addEventListener('mousemove', function(e){
|
||
var r = card.getBoundingClientRect();
|
||
card.style.setProperty('--mx', ((e.clientX-r.left)/r.width*100)+'%');
|
||
card.style.setProperty('--my', ((e.clientY-r.top)/r.height*100)+'%');
|
||
});
|
||
});
|
||
|
||
// 4. Ripple на всех кнопках
|
||
document.addEventListener('click', function(e){
|
||
var btn = e.target.closest('.btn, .para-pill, .opt-btn, .sb-item');
|
||
if(!btn) return;
|
||
var r = btn.getBoundingClientRect();
|
||
btn.style.setProperty('--rx', ((e.clientX-r.left)/r.width*100)+'%');
|
||
btn.style.setProperty('--ry', ((e.clientY-r.top)/r.height*100)+'%');
|
||
btn.classList.remove('is-ripple');
|
||
// reflow
|
||
void btn.offsetWidth;
|
||
btn.classList.add('is-ripple');
|
||
setTimeout(function(){ btn.classList.remove('is-ripple'); }, 600);
|
||
});
|
||
|
||
// 5. Mini-TOC: нет (заменено sidebar)
|
||
// buildMiniToc() — no-op
|
||
|
||
// 6. Chapter progress — нет (заменено sidebar)
|
||
}
|
||
|
||
// buildMiniToc, markMiniTocActive, updateChapterProgress — заменены sidebar, no-op
|
||
function buildMiniToc(){ /* no-op */ }
|
||
function markMiniTocActive(t){ /* no-op */ }
|
||
function updateChapterProgress(){ /* no-op */ }
|
||
|
||
// ═══ B1. setupCanvas — утилита для новых интерактивов ═══
|
||
function setupCanvas(id, opts){
|
||
opts = opts || {};
|
||
var cv = document.getElementById(id);
|
||
if(!cv) return null;
|
||
var dpr = Math.min(window.devicePixelRatio||1, 2);
|
||
function resize(){
|
||
var W = cv.offsetWidth, H = cv.offsetHeight || (opts.height||220);
|
||
cv.width = Math.round(W*dpr); cv.height = Math.round(H*dpr);
|
||
var ctx = cv.getContext('2d');
|
||
ctx.setTransform(dpr,0,0,dpr,0,0);
|
||
return {ctx:ctx, W:W, H:H};
|
||
}
|
||
var rid = null, paused = false, lastFrame = 0;
|
||
var io = null;
|
||
if(opts.draw){
|
||
var loop = function(now){
|
||
if(paused){ rid=null; return; }
|
||
var dt = lastFrame ? (now-lastFrame)/1000 : 0.016;
|
||
lastFrame = now;
|
||
var dims = resize();
|
||
opts.draw(dims.ctx, dims.W, dims.H, dt, now);
|
||
rid = requestAnimationFrame(loop);
|
||
};
|
||
// auto-pause when off-screen
|
||
try{
|
||
io = new IntersectionObserver(function(entries){
|
||
entries.forEach(function(e){
|
||
if(e.isIntersecting){
|
||
if(!rid){ paused=false; lastFrame=0; rid=requestAnimationFrame(loop); }
|
||
} else {
|
||
paused=true; if(rid){cancelAnimationFrame(rid); rid=null;}
|
||
}
|
||
});
|
||
},{threshold:.05});
|
||
io.observe(cv);
|
||
}catch(_){}
|
||
// initial
|
||
paused=false; lastFrame=0; rid=requestAnimationFrame(loop);
|
||
} else if(opts.onResize){
|
||
var dims = resize();
|
||
opts.onResize(dims.ctx, dims.W, dims.H);
|
||
}
|
||
window.addEventListener('resize', function(){ if(opts.onResize){ var d=resize(); opts.onResize(d.ctx,d.W,d.H);} });
|
||
return {
|
||
canvas:cv,
|
||
stop:function(){ paused=true; if(rid){cancelAnimationFrame(rid); rid=null;} if(io)io.disconnect(); }
|
||
};
|
||
}
|
||
</script>
|
||
</body>
|
||
</html>
|