diff --git a/frontend/js/phys9_legacy.js b/frontend/js/phys9_legacy.js index a2f5479..8c3f120 100644 --- a/frontend/js/phys9_legacy.js +++ b/frontend/js/phys9_legacy.js @@ -2930,7 +2930,7 @@ function startAnim1() { ctx.strokeStyle = dark ? '#334155' : '#e2e8f0'; ctx.lineWidth = 1; ctx.beginPath(); ctx.moveTo(0, y1); ctx.lineTo(W, y1); ctx.stroke(); var x1 = ((t * 65) % (W + 22)) - 11; - ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.beginPath(); ctx.arc(x1, y1 - 11, 9, 0, 2*Math.PI); ctx.fill(); // Row 2: accelerated var y2 = H * 0.57; @@ -2940,7 +2940,7 @@ function startAnim1() { ctx.beginPath(); ctx.moveTo(0, y2); ctx.lineTo(W, y2); ctx.stroke(); var ph2 = (t * 0.55) % 2.2; var x2 = ph2 * ph2 * W * 0.21; - ctx.fillStyle = '#10b981'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.beginPath(); ctx.arc(Math.min(x2, W+9), y2 - 11, 9, 0, 2*Math.PI); ctx.fill(); // Row 3: decelerated var y3 = H * 0.91; @@ -2950,7 +2950,7 @@ function startAnim1() { ctx.beginPath(); ctx.moveTo(0, y3); ctx.lineTo(W, y3); ctx.stroke(); var ph3 = (t * 0.55) % 2.2; var x3 = W * (2*ph3 - 0.45*ph3*ph3) * 0.22; - ctx.fillStyle = '#f97316'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.beginPath(); ctx.arc(Math.min(x3, W+9), y3 - 11, 9, 0, 2*Math.PI); ctx.fill(); anim1Id = requestAnimationFrame(frame); } @@ -2996,7 +2996,7 @@ function upd2() { ctx.fillText('Поезд: v₁ = '+vt+' м/с', tx+8, ty+16); // Passenger dot var px = tx + tw*0.5; - ctx.fillStyle = '#ef4444'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.beginPath(); ctx.arc(px, ty+th*0.5+2, 11, 0, 2*Math.PI); ctx.fill(); ctx.font = 'bold 9px Inter,sans-serif'; ctx.fillStyle = '#fff'; ctx.textAlign = 'center'; @@ -3004,9 +3004,9 @@ function upd2() { // Arrow: absolute speed var ay = ty - 12, scale = (W*0.7) / (vt + 10); var aLen = (vt + vp) * scale; - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(tx, ay); ctx.lineTo(tx + aLen, ay); ctx.stroke(); - ctx.fillStyle = '#10b981'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.beginPath(); ctx.moveTo(tx+aLen,ay); ctx.lineTo(tx+aLen-8,ay-5); ctx.lineTo(tx+aLen-8,ay+5); ctx.fill(); ctx.font = '11px Inter,sans-serif'; ctx.fillText('v_пас = '+vt+'+'+vp+' = '+(vt+vp)+' м/с', tx, ay - 5); @@ -3042,14 +3042,14 @@ function upd3() { var ox = W*0.18, oy = H*0.65, sc = (W*0.55) / 120; // Vector a (horizontal) var ax = a * sc, ay = 0; - drawArrow3(ctx, ox, oy, ox+ax, oy+ay, '#3b82f6', 'a='+a, true, dark); + drawArrow3(ctx,ox,oy,ox+ax,oy+ay,(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'), 'a='+a, true, dark); // Vector b (at angle) var bx = b*sc*Math.cos(angR), by = -b*sc*Math.sin(angR); - drawArrow3(ctx, ox, oy, ox+bx, oy+by, '#ef4444', 'b='+b, true, dark); + drawArrow3(ctx,ox,oy,ox+bx,oy+by,(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'), 'b='+b, true, dark); // Result vector (parallelogram diagonal) var rx = ax+bx, ry = ay+by; var cLen = Math.sqrt(rx*rx+ry*ry)/sc; - drawArrow3(ctx, ox, oy, ox+rx, oy+ry, '#10b981', 'c='+cLen.toFixed(1), false, dark); + drawArrow3(ctx,ox,oy,ox+rx,oy+ry,(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'), 'c='+cLen.toFixed(1), false, dark); // Dashed parallelogram lines ctx.strokeStyle = dark ? '#475569' : '#cbd5e1'; ctx.lineWidth = 1; ctx.setLineDash([4,3]); @@ -3101,9 +3101,9 @@ function upd4() { ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif'; ctx.fillText('x', ox+W*0.72-6, oy+14); ctx.fillText('y', ox+4, oy-H*0.7+12); // Vector - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(ox,oy); ctx.lineTo(ox+vx,oy+vy); ctx.stroke(); - ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); var ang = Math.atan2(vy,vx); ctx.beginPath(); ctx.moveTo(ox+vx,oy+vy); ctx.lineTo(ox+vx-9*Math.cos(ang-0.4),oy+vy-9*Math.sin(ang-0.4)); @@ -3115,14 +3115,14 @@ function upd4() { ctx.beginPath(); ctx.moveTo(ox+vx,oy+vy); ctx.lineTo(ox,oy+vy); ctx.stroke(); ctx.setLineDash([]); // Projection arrows - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(ox,oy); ctx.lineTo(ox+vx,oy); ctx.stroke(); - ctx.fillStyle = '#ef4444'; ctx.font = 'bold 11px Inter,sans-serif'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font = 'bold 11px Inter,sans-serif'; var axVal = (am*Math.cos(phiR)).toFixed(1); ctx.fillText('ax='+axVal, ox+vx/2-10, oy+16); - ctx.strokeStyle = '#f59e0b'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(ox,oy); ctx.lineTo(ox,oy+vy); ctx.stroke(); - ctx.fillStyle = '#f59e0b'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); var ayVal = (am*Math.sin(phiR)).toFixed(1); ctx.fillText('ay='+ayVal, ox+6, oy+vy/2); // Angle arc @@ -3155,22 +3155,22 @@ function upd5() { // Start point A var xa = pad, xb = pad + s1*sc, xc = pad + (s1-s2)*sc; // Draw detour arc (path above) - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(xa,y); ctx.quadraticCurveTo((xa+xb)/2, y-38, xb, y); ctx.stroke(); - ctx.fillStyle = '#ef4444'; ctx.font = '11px Inter,sans-serif'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font = '11px Inter,sans-serif'; ctx.fillText('Путь s₁='+s1+' м', (xa+xb)/2-24, y-42); // Return path (dashed below) - ctx.strokeStyle = '#f97316'; ctx.lineWidth = 2; ctx.setLineDash([5,3]); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.lineWidth = 2; ctx.setLineDash([5,3]); ctx.beginPath(); ctx.moveTo(xb,y); ctx.lineTo(xc,y); ctx.stroke(); ctx.setLineDash([]); - ctx.fillStyle = '#f97316'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fillText('s₂='+s2, (xb+xc)/2-10, y+18); // Displacement arrow - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(xa, y+30); ctx.lineTo(xc-4, y+30); ctx.stroke(); - ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); var disp = s1-s2; ctx.beginPath(); ctx.moveTo(xc,y+30); ctx.lineTo(xc-10,y+25); ctx.lineTo(xc-10,y+35); ctx.fill(); ctx.fillText('Перемещение |Δr| = '+(disp)+' м', xa, y+46); @@ -3229,7 +3229,7 @@ function upd6() { ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif'; ctx.fillText('t, с', ox+gw-4, oy+14); ctx.fillText('x, м', ox+4, tpad-6); // Line x(t) - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.beginPath(); for (var tc = 0; tc <= tmax; tc++) { var xc2 = x0 + v * tc; @@ -3238,7 +3238,7 @@ function upd6() { if (tc === 0) ctx.moveTo(gxc, gyc); else ctx.lineTo(gxc, gyc); } ctx.stroke(); - ctx.fillStyle = '#3b82f6'; ctx.font = 'bold 11px Inter,sans-serif'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 11px Inter,sans-serif'; ctx.fillText('x = '+x0+(v>=0?'+':'')+v+'·t', ox+gw*0.4, tpad+12); [['v6v',v+' м/с'],['v6x0',x0+' м']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; @@ -3290,7 +3290,7 @@ function upd7() { ctx.fillStyle = dark ? '#94a3b8' : '#475569'; ctx.font = '11px Inter,sans-serif'; ctx.fillText('t, с', ox+gw-4, oy+14); ctx.fillText('x, м', ox+4, tpad-6); // Line 1 - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.beginPath(); for (var tc = 0; tc <= tmax; tc++) { var xv = x01 + v1*tc; @@ -3298,10 +3298,10 @@ function upd7() { if (tc===0) ctx.moveTo(ox, oy-(x01-xmin)/(xmax-xmin)*gh); } ctx.stroke(); - ctx.fillStyle = '#3b82f6'; ctx.font = 'bold 10px Inter,sans-serif'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 10px Inter,sans-serif'; ctx.fillText('Тело 1 (v='+v1+')', ox+4, oy-(x01-xmin)/(xmax-xmin)*gh - 5); // Line 2 - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(ox, oy-(x02-xmin)/(xmax-xmin)*gh); for (var tc2 = 0; tc2 <= tmax; tc2++) { @@ -3309,7 +3309,7 @@ function upd7() { ctx.lineTo(ox+tc2*(gw/tmax), oy-(xv2-xmin)/(xmax-xmin)*gh); } ctx.stroke(); - ctx.fillStyle = '#ef4444'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fillText('Тело 2 (v='+v2+')', ox+gw*0.55, oy-(x02-xmin)/(xmax-xmin)*gh + 14); // Meeting point var dv = v1 + v2, dx = x02 - x01; @@ -3319,11 +3319,11 @@ function upd7() { if (tmeet > 0 && tmeet < tmax && xmeet >= xmin && xmeet <= xmax) { var gxm = ox+tmeet*(gw/tmax); var gym = oy-(xmeet-xmin)/(xmax-xmin)*gh; - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 1; ctx.setLineDash([4,3]); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 1; ctx.setLineDash([4,3]); ctx.beginPath(); ctx.moveTo(gxm,gym); ctx.lineTo(gxm,oy); ctx.stroke(); ctx.beginPath(); ctx.moveTo(ox,gym); ctx.lineTo(gxm,gym); ctx.stroke(); ctx.setLineDash([]); - ctx.fillStyle = '#10b981'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.beginPath(); ctx.arc(gxm,gym,5,0,2*Math.PI); ctx.fill(); ctx.font = '10px Inter,sans-serif'; ctx.fillText('t='+tmeet.toFixed(1)+' с', gxm+3, gym-5); @@ -3355,14 +3355,14 @@ function upd8() { var pad = W*0.08, segW = W*0.38, y = H*0.42, h = 22; // Segment 1 ctx.fillStyle = dark ? '#1e3a5f' : '#dbeafe'; - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2; ctx.fillRect(pad, y, segW, h); ctx.strokeRect(pad, y, segW, h); ctx.fillStyle = dark ? '#93c5fd' : '#1d4ed8'; ctx.font = 'bold 11px Inter,sans-serif'; ctx.textAlign = 'center'; ctx.fillText('v₁ = '+v1+' км/ч', pad+segW/2, y+15); // Segment 2 ctx.fillStyle = dark ? '#1c2d0f' : '#d1fae5'; - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.fillRect(pad+segW, y, segW, h); ctx.strokeRect(pad+segW, y, segW, h); ctx.fillStyle = dark ? '#6ee7b7' : '#065f46'; ctx.fillText('v₂ = '+v2+' км/ч', pad+segW+segW/2, y+15); @@ -3435,7 +3435,7 @@ function upd9() { var scY = riverH; var bx = W*0.12 + ph*drift*scX; var by = bank1 + ph*scY; - ctx.fillStyle = '#f59e0b'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); ctx.beginPath(); ctx.arc(bx, by, 8, 0, 2*Math.PI); ctx.fill(); ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter,sans-serif'; ctx.textAlign = 'center'; ctx.fillText('', bx, by+4); ctx.textAlign = 'left'; @@ -3487,7 +3487,7 @@ function upd10() { ctx.fillStyle = dark?'#94a3b8':'#475569'; ctx.font='11px Inter,sans-serif'; ctx.fillText('t,с', ox+gw-4, oy+14); ctx.fillText('v,м/с', ox+4, tpad-6); // v(t) line - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth=2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth=2.5; ctx.beginPath(); ctx.moveTo(ox, oy-v0/vmax*gh); for (var tc=0; tc<=tmax; tc++) { @@ -3496,15 +3496,15 @@ function upd10() { ctx.lineTo(ox+tc*(gw/tmax), oy-Math.min(vc,vmax)/vmax*gh); } ctx.stroke(); - ctx.fillStyle='#3b82f6'; ctx.font='bold 11px Inter,sans-serif'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font='bold 11px Inter,sans-serif'; ctx.fillText('v = '+v0+(a>=0?'+':'')+a+'·t', ox+gw*0.3, tpad+14); // a annotation - ctx.strokeStyle='#ef4444'; ctx.lineWidth=1.5; ctx.setLineDash([4,3]); + ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth=1.5; ctx.setLineDash([4,3]); var gx1=ox+(gw/tmax), gx2=ox+2*(gw/tmax); var vy1=oy-(v0+a)/vmax*gh, vy2=oy-(v0+2*a)/vmax*gh; ctx.beginPath(); ctx.moveTo(gx1,vy1); ctx.lineTo(gx2,vy1); ctx.lineTo(gx2,vy2); ctx.stroke(); ctx.setLineDash([]); - ctx.fillStyle='#ef4444'; ctx.font='10px Inter,sans-serif'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font='10px Inter,sans-serif'; ctx.fillText('a='+a, gx2+3, (vy1+vy2)/2+4); [['v10v0',v0+' м/с'],['v10a',a+' м/с²']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; }); var vFinal = v0+a*tmax; @@ -3559,7 +3559,7 @@ function upd11() { ctx.lineTo(ox+tc*(gw/tmax), oy-Math.min(vc,vmax)/vmax*gh); } ctx.lineTo(ox+gw,oy); ctx.closePath(); ctx.fill(); - ctx.strokeStyle='#3b82f6'; ctx.lineWidth=2.5; + ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth=2.5; ctx.beginPath(); ctx.moveTo(ox, oy-Math.min(v0,vmax)/vmax*gh); for (var tc2=0; tc2<=tmax; tc2++) { var vc2=v0+a*tc2; if(vc2<0) vc2=0; @@ -3567,7 +3567,7 @@ function upd11() { } ctx.stroke(); // Slope annotation - ctx.fillStyle='#3b82f6'; ctx.font='bold 11px Inter,sans-serif'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font='bold 11px Inter,sans-serif'; ctx.fillText('v = '+v0+(a>=0?'+':'')+a+'·t', ox+gw*0.45, tpad+14); ctx.fillStyle=dark?'#94a3b8':'#64748b'; ctx.font='10px Inter,sans-serif'; ctx.fillText('Площадь = путь s', ox+gw*0.22, oy-gh*0.28); @@ -3619,7 +3619,7 @@ function upd12() { ctx.fillStyle=dark?'#94a3b8':'#475569'; ctx.font='11px Inter,sans-serif'; ctx.fillText('t,с',ox+gw-4,oy+14); ctx.fillText('x,м',ox+4,tpad-6); // x(t) curve (parabola) - ctx.strokeStyle='#10b981'; ctx.lineWidth=2.5; + ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth=2.5; ctx.beginPath(); for (var tc=0; tc<=tmax*20; tc++) { var t2=tc/(tmax*20)*tmax; @@ -3629,7 +3629,7 @@ function upd12() { if (tc===0) ctx.moveTo(gxc,gyc); else ctx.lineTo(gxc,gyc); } ctx.stroke(); - ctx.fillStyle='#10b981'; ctx.font='bold 11px Inter,sans-serif'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.font='bold 11px Inter,sans-serif'; ctx.fillText('x = '+v0+'t + '+a+'/2·t²', ox+gw*0.3, tpad+14); [['v12v0',v0+' м/с'],['v12a',a+' м/с²']].forEach(function(p){ var el=document.getElementById(p[0]); if(el) el.textContent=p[1]; }); var el=document.getElementById('res12'); @@ -3670,14 +3670,14 @@ function upd13() { ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '10px Inter,sans-serif'; ctx.fillText('r='+r+' м', cx+3, cy-4); // Point - ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.beginPath(); ctx.arc(px,py,7,0,2*Math.PI); ctx.fill(); // Velocity vector (tangential) var tangX = -Math.sin(angle)*v*0.5*sc*0.8; var tangY = Math.cos(angle)*v*0.5*sc*0.8; - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(px+tangX,py+tangY); ctx.stroke(); - ctx.fillStyle = '#10b981'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.beginPath(); ctx.moveTo(px+tangX,py+tangY); ctx.lineTo(px+tangX-7*Math.cos(Math.atan2(tangY,tangX)-0.4),py+tangY-7*Math.sin(Math.atan2(tangY,tangX)-0.4)); ctx.lineTo(px+tangX-7*Math.cos(Math.atan2(tangY,tangX)+0.4),py+tangY-7*Math.sin(Math.atan2(tangY,tangX)+0.4)); @@ -3741,14 +3741,14 @@ function upd14() { ctx.fillStyle=dark?'#94a3b8':'#64748b'; ctx.font='10px Inter,sans-serif'; ctx.fillText('r='+r, cx+4, cy-4); // Point - ctx.fillStyle='#f97316'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.beginPath(); ctx.arc(px,py,7,0,2*Math.PI); ctx.fill(); // Velocity arrow (tangent) — green var scV = 0.45*sc; var tvx = -Math.sin(angle)*vms*scV, tvy = Math.cos(angle)*vms*scV; - ctx.strokeStyle='#10b981'; ctx.lineWidth=2; + ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth=2; ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(px+tvx,py+tvy); ctx.stroke(); - ctx.fillStyle='#10b981'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); var va=Math.atan2(tvy,tvx); ctx.beginPath(); ctx.moveTo(px+tvx,py+tvy); ctx.lineTo(px+tvx-7*Math.cos(va-0.4),py+tvy-7*Math.sin(va-0.4)); @@ -3760,9 +3760,9 @@ function upd14() { var aLen = Math.min(Math.sqrt(avx*avx+avy*avy), R*0.7); var aang = Math.atan2(cy-py, cx-px); var eax = px + Math.cos(aang)*aLen, eay = py + Math.sin(aang)*aLen; - ctx.strokeStyle='#ef4444'; ctx.lineWidth=2.5; + ctx.strokeStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth=2.5; ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(eax,eay); ctx.stroke(); - ctx.fillStyle='#ef4444'; + ctx.fillStyle=(window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.beginPath(); ctx.moveTo(eax,eay); ctx.lineTo(eax-8*Math.cos(aang-0.4),eay-8*Math.sin(aang-0.4)); ctx.lineTo(eax-8*Math.cos(aang+0.4),eay-8*Math.sin(aang+0.4)); ctx.fill(); @@ -3901,7 +3901,7 @@ function drawAngularThrow22(deg, v0) { var bx = pad + v0 * Math.cos(rad) * tMid * scX; var by = bH - (v0 * Math.sin(rad) * tMid - 0.5 * g * tMid * tMid) * scY; ctx.beginPath(); ctx.arc(bx, by, 7, 0, Math.PI * 2); - ctx.fillStyle = '#f97316'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill(); // Angle arc ctx.strokeStyle = '#0369a1'; ctx.lineWidth = 1.5; ctx.beginPath(); ctx.arc(pad, bH, 28, -rad, 0, true); ctx.stroke(); @@ -3912,7 +3912,7 @@ function drawAngularThrow22(deg, v0) { ctx.fillText('L = ' + L.toFixed(1) + ' м', pad + 5, bH + 18); ctx.fillText('H = ' + Hmax.toFixed(1) + ' м', bx - 20, by - 10); // Launch arrow - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; var arLen = 40; ctx.beginPath(); ctx.moveTo(pad, bH); @@ -3954,7 +3954,7 @@ function drawGravity23(m1, m2, r, F) { if (x2 > W - 30) x2 = W - 30; // Body 1 ctx.beginPath(); ctx.arc(x1 + r1, cy, r1, 0, Math.PI * 2); - ctx.fillStyle = '#1d4ed8'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceGravity:'#1d4ed8'); ctx.fill(); ctx.fillStyle = '#fff'; ctx.font = 'bold 11px Inter'; ctx.textAlign = 'center'; ctx.fillText(m1 + ' кг', x1 + r1, cy + 4); // Body 2 @@ -3965,10 +3965,10 @@ function drawGravity23(m1, m2, r, F) { // Arrows var maxArr = 60, normF = Math.log10(F + 1e-11) + 11; var arrLen = Math.max(8, Math.min(maxArr, normF * 8)); - ctx.strokeStyle = '#f97316'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.lineWidth = 2.5; // Left arrow (toward right) ctx.beginPath(); ctx.moveTo(x1 + r1, cy); ctx.lineTo(x1 + r1 + arrLen, cy); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(x1 + r1 + arrLen, cy - 5); ctx.lineTo(x1 + r1 + arrLen + 8, cy); ctx.lineTo(x1 + r1 + arrLen, cy + 5); ctx.fillStyle = '#f97316'; ctx.fill(); + ctx.beginPath(); ctx.moveTo(x1 + r1 + arrLen, cy - 5); ctx.lineTo(x1 + r1 + arrLen + 8, cy); ctx.lineTo(x1 + r1 + arrLen, cy + 5); ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill(); // Right arrow (toward left) ctx.beginPath(); ctx.moveTo(x2 - r2, cy); ctx.lineTo(x2 - r2 - arrLen, cy); ctx.stroke(); ctx.beginPath(); ctx.moveTo(x2 - r2 - arrLen, cy - 5); ctx.lineTo(x2 - r2 - arrLen - 8, cy); ctx.lineTo(x2 - r2 - arrLen, cy + 5); ctx.fill(); @@ -3976,7 +3976,7 @@ function drawGravity23(m1, m2, r, F) { ctx.fillStyle = dark ? '#94a3b8' : '#64748b'; ctx.font = '11px Inter'; ctx.textAlign = 'center'; ctx.fillText('r = ' + r + ' м', (x1 + r1 + x2 - r2) / 2, cy + 30); // F label - ctx.fillStyle = '#f97316'; ctx.font = 'bold 12px Inter'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = 'bold 12px Inter'; ctx.fillText('F = ' + F.toExponential(2) + ' Н', (x1 + r1 + x2 - r2) / 2, cy - 20); ctx.textAlign = 'left'; } @@ -4027,31 +4027,31 @@ function drawElevator24(m, a, P, Ft) { ctx.beginPath(); ctx.moveTo(px - 10, pBase - 10); ctx.lineTo(px + 10, pBase - 10); ctx.stroke(); // Weight arrow (F_t - downward, red) var g = 10, sc = Math.max(15, Math.min(60, Ft / (m * g) * 35)); - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(px + 25, pBase - 20); ctx.lineTo(px + 25, pBase - 20 + sc); ctx.stroke(); - ctx.beginPath(); ctx.moveTo(px + 22, pBase - 20 + sc - 6); ctx.lineTo(px + 25, pBase - 20 + sc + 4); ctx.lineTo(px + 28, pBase - 20 + sc - 6); ctx.fillStyle = '#ef4444'; ctx.fill(); - ctx.fillStyle = '#ef4444'; ctx.font = '10px Inter'; ctx.textAlign = 'left'; + ctx.beginPath(); ctx.moveTo(px + 22, pBase - 20 + sc - 6); ctx.lineTo(px + 25, pBase - 20 + sc + 4); ctx.lineTo(px + 28, pBase - 20 + sc - 6); ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.font = '10px Inter'; ctx.textAlign = 'left'; ctx.fillText('F_т=' + Ft.toFixed(0) + 'Н', px + 30, pBase - 20 + sc / 2); // Reaction (P - upward, green), clamped to 0 if weightless var Pdisp = Math.max(0, P); var scP = Math.max(0, Math.min(60, Pdisp / (m * g) * 35)); - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(px - 25, pBase); ctx.lineTo(px - 25, pBase - scP); ctx.stroke(); if (scP > 3) { - ctx.beginPath(); ctx.moveTo(px - 28, pBase - scP + 6); ctx.lineTo(px - 25, pBase - scP - 4); ctx.lineTo(px - 22, pBase - scP + 6); ctx.fillStyle = '#10b981'; ctx.fill(); + ctx.beginPath(); ctx.moveTo(px - 28, pBase - scP + 6); ctx.lineTo(px - 25, pBase - scP - 4); ctx.lineTo(px - 22, pBase - scP + 6); ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fill(); } - ctx.fillStyle = '#10b981'; ctx.font = '10px Inter'; ctx.textAlign = 'right'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.font = '10px Inter'; ctx.textAlign = 'right'; ctx.fillText('P=' + Pdisp.toFixed(0) + 'Н', px - 28, pBase - scP / 2); // Acceleration arrow if (a !== 0) { - ctx.strokeStyle = '#f97316'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.lineWidth = 2; var arDir = a > 0 ? -1 : 1; ctx.beginPath(); ctx.moveTo(ex - 20, ey + eh / 2); ctx.lineTo(ex - 20, ey + eh / 2 + arDir * 35); ctx.stroke(); ctx.beginPath(); var arTip = ey + eh / 2 + arDir * 35; ctx.moveTo(ex - 23, arTip - arDir * 6); ctx.lineTo(ex - 20, arTip + arDir * 4); ctx.lineTo(ex - 17, arTip - arDir * 6); - ctx.fillStyle = '#f97316'; ctx.fill(); - ctx.fillStyle = '#f97316'; ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center'; ctx.fillText('a=' + (a > 0 ? '+' : '') + a + ' м/с²', ex - 20, ey + eh / 2 + arDir * 50 + (a > 0 ? -5 : 10)); } // Label @@ -4130,31 +4130,31 @@ function drawSeesaw25() { // Left weight (blue, m1=4kg) at distance l1 var x1 = -l1 * scale; var bH = 30 + m1 * 4; - ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fillRect(x1 - 20, -6 - bH, 40, bH); - ctx.strokeStyle = '#1d4ed8'; ctx.lineWidth = 2; ctx.strokeRect(x1 - 20, -6 - bH, 40, bH); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceGravity:'#1d4ed8'); ctx.lineWidth = 2; ctx.strokeRect(x1 - 20, -6 - bH, 40, bH); ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center'; ctx.fillText(m1 + ' кг', x1, -6 - bH/2 + 4); // l1 label - ctx.fillStyle = '#3b82f6'; ctx.font = '8px Inter'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = '8px Inter'; ctx.fillText('l₁=' + l1.toFixed(1) + 'м', x1/2, 16); // M1 label - ctx.fillStyle = '#3b82f6'; ctx.font = 'bold 9px Inter'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 9px Inter'; ctx.fillText('M₁=' + M1.toFixed(0) + ' Н·м', x1, -6 - bH - 10); // Right weight (orange, m2=6kg) at distance l2 var x2 = l2 * scale; var bH2 = 30 + m2 * 4; - ctx.fillStyle = '#f97316'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fillRect(x2 - 20, -6 - bH2, 40, bH2); - ctx.strokeStyle = '#ea580c'; ctx.lineWidth = 2; ctx.strokeRect(x2 - 20, -6 - bH2, 40, bH2); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.strokeRect(x2 - 20, -6 - bH2, 40, bH2); ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.fillText(m2 + ' кг', x2, -6 - bH2/2 + 4); // l2 label - ctx.fillStyle = '#f97316'; ctx.font = '8px Inter'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = '8px Inter'; ctx.fillText('l₂=' + l2.toFixed(1) + 'м', x2/2, 16); // M2 label - ctx.fillStyle = '#f97316'; ctx.font = 'bold 9px Inter'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.font = 'bold 9px Inter'; ctx.fillText('M₂=' + M2.toFixed(0) + ' Н·м', x2, -6 - bH2 - 10); ctx.textAlign = 'left'; @@ -4164,7 +4164,7 @@ function drawSeesaw25() { var diff = Math.abs(M1 - M2); ctx.font = 'bold 11px Inter'; ctx.textAlign = 'center'; if (diff < 1.5) { - ctx.fillStyle = '#10b981'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fillText(' РАВНОВЕСИЕ! M₁ = M₂', W/2, H - 8); } else { ctx.fillStyle = dk ? '#94a3b8' : '#64748b'; @@ -4224,7 +4224,7 @@ function drawLever26() { ctx.lineTo(cx - 15, pivotY + 28); ctx.lineTo(cx + 15, pivotY + 28); ctx.closePath(); - ctx.fillStyle = '#f97316'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fill(); // Beam ctx.fillStyle = dk ? '#64748b' : '#94a3b8'; @@ -4234,31 +4234,31 @@ function drawLever26() { // Load (left, down) — mg arrow var arrowScale = Math.min(55, mg * 0.055); ctx.beginPath(); ctx.moveTo(x_load, pivotY - 5); ctx.lineTo(x_load, pivotY - 5 - arrowScale); - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.stroke(); ctx.beginPath(); ctx.moveTo(x_load, pivotY - 5 - arrowScale); ctx.lineTo(x_load - 6, pivotY - 5 - arrowScale + 12); ctx.lineTo(x_load + 6, pivotY - 5 - arrowScale + 12); - ctx.fillStyle = '#ef4444'; ctx.fill(); - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#ef4444'; ctx.textAlign = 'center'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill(); + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.textAlign = 'center'; ctx.fillText('G = ' + mg + ' Н', x_load, pivotY - 5 - arrowScale - 5); // Applied force (right, down) var fArrow = Math.min(55, F * 0.055); ctx.beginPath(); ctx.moveTo(x_force, pivotY - 5); ctx.lineTo(x_force, pivotY - 5 - fArrow); - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.stroke(); ctx.beginPath(); ctx.moveTo(x_force, pivotY - 5 - fArrow); ctx.lineTo(x_force - 6, pivotY - 5 - fArrow + 12); ctx.lineTo(x_force + 6, pivotY - 5 - fArrow + 12); - ctx.fillStyle = '#3b82f6'; ctx.fill(); - ctx.fillStyle = '#3b82f6'; ctx.font = 'bold 9px Inter'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.font = 'bold 9px Inter'; ctx.fillText('F = ' + F.toFixed(0) + ' Н', x_force, pivotY - 5 - fArrow - 5); // l1 and l2 labels - ctx.font = '9px Inter'; ctx.fillStyle = '#ef4444'; + ctx.font = '9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fillText('l₂ = ' + l2.toFixed(1) + ' м', (x_load + cx) / 2, pivotY + 20); - ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fillText('l₁ = ' + l1.toFixed(1) + ' м', (cx + x_force) / 2, pivotY + 20); // Gain badge - ctx.font = 'bold 11px Inter'; ctx.fillStyle = '#10b981'; ctx.textAlign = 'center'; + ctx.font = 'bold 11px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.textAlign = 'center'; ctx.fillText('Выигрыш = ' + gain.toFixed(1) + '× → F в ' + gain.toFixed(1) + ' раз меньше нагрузки!', W/2, H - 8); ctx.textAlign = 'left'; } @@ -4335,8 +4335,8 @@ function drawIncline27() { // Angle arc ctx.beginPath(); ctx.arc(rightX, rightY, 28, Math.PI - rad, Math.PI); - ctx.strokeStyle = '#f59e0b'; ctx.lineWidth = 1.5; ctx.stroke(); - ctx.font = 'bold 10px Inter'; ctx.fillStyle = '#f59e0b'; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); ctx.lineWidth = 1.5; ctx.stroke(); + ctx.font = 'bold 10px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.warn:'#f59e0b'); ctx.fillText('α=' + alpha + '°', rightX - 52, rightY - 10); // Block on slope @@ -4360,10 +4360,10 @@ function drawIncline27() { // mg arrow (vertical down) var arLen = Math.min(55, mg * 0.25); ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY); ctx.lineTo(bBlockX, bBlockY + arLen); - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.stroke(); ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY+arLen); ctx.lineTo(bBlockX-5,bBlockY+arLen-10); ctx.lineTo(bBlockX+5,bBlockY+arLen-10); - ctx.fillStyle = '#ef4444'; ctx.fill(); - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#ef4444'; ctx.textAlign = 'left'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill(); + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.textAlign = 'left'; ctx.fillText('mg=' + mg + 'Н', bBlockX + 6, bBlockY + arLen - 2); // F arrow (along slope, up) @@ -4371,13 +4371,13 @@ function drawIncline27() { var slopeUx = -triW / slopeLen, slopeUy = -triH / slopeLen; // up the slope ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY); ctx.lineTo(bBlockX + slopeUx * fLen, bBlockY + slopeUy * fLen); - ctx.strokeStyle = '#3b82f6'; ctx.lineWidth = 2.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.lineWidth = 2.5; ctx.stroke(); var ax2 = bBlockX + slopeUx * fLen, ay2 = bBlockY + slopeUy * fLen; ctx.beginPath(); ctx.moveTo(ax2, ay2); ctx.lineTo(ax2 - slopeUx * 12 + slopeUy * 5, ay2 - slopeUy * 12 - slopeUx * 5); ctx.lineTo(ax2 - slopeUx * 12 - slopeUy * 5, ay2 - slopeUy * 12 + slopeUx * 5); - ctx.fillStyle = '#3b82f6'; ctx.fill(); - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#3b82f6'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fill(); + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.liquid:'#3b82f6'); ctx.fillText('F=' + F.toFixed(0) + 'Н', ax2 + 5, ay2 - 3); // N arrow (perpendicular to slope, outward) @@ -4385,8 +4385,8 @@ function drawIncline27() { var nUx = triH / slopeLen, nUy = -triW / slopeLen; // outward normal ctx.beginPath(); ctx.moveTo(bBlockX, bBlockY); ctx.lineTo(bBlockX + nUx * nLen, bBlockY + nUy * nLen); - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2; ctx.stroke(); - ctx.font = '9px Inter'; ctx.fillStyle = '#10b981'; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.stroke(); + ctx.font = '9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fillText('N=' + N.toFixed(0) + 'Н', bBlockX + nUx * nLen + 3, bBlockY + nUy * nLen - 2); // h and l labels @@ -4421,7 +4421,7 @@ function drawEfficiency27(eta) { // Useful work (green) var usefulW = Math.max(0, (eta / 100) * (W - pad*2)); if (usefulW > 0) { - ctx.fillStyle = '#10b981'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.beginPath(); if (ctx.roundRect) ctx.roundRect(pad, barY, usefulW, barH, 8); else ctx.rect(pad, barY, usefulW, barH); @@ -4430,7 +4430,7 @@ function drawEfficiency27(eta) { // Waste (red) var wasteW = (W - pad*2) - usefulW; if (wasteW > 4) { - ctx.fillStyle = '#ef4444'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.beginPath(); ctx.rect(pad + usefulW, barY, wasteW, barH); ctx.fill(); @@ -4479,7 +4479,7 @@ function startAnim15() { } // Track labels ctx.font = 'bold 10px Inter,sans-serif'; - ctx.fillStyle = '#0284c7'; ctx.fillText(' Лёд — без трения', 8, 18); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.fillText(' Лёд — без трения', 8, 18); ctx.fillStyle = '#78716c'; ctx.fillText(' Асфальт — трение', 8, mid + 18); // Physics x_ice += v_ice; @@ -4492,27 +4492,27 @@ function startAnim15() { var yIce = mid / 2; ctx.beginPath(); ctx.arc(x_ice, yIce, 13, 0, Math.PI * 2); ctx.fillStyle = '#38bdf8'; ctx.fill(); - ctx.strokeStyle = '#0284c7'; ctx.lineWidth = 2; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 2; ctx.stroke(); if (Math.abs(v_ice) > 0.3) { var d = v_ice > 0 ? 1 : -1; ctx.beginPath(); ctx.moveTo(x_ice + d*14, yIce); ctx.lineTo(x_ice + d*28, yIce); - ctx.strokeStyle = '#0284c7'; ctx.lineWidth = 2; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 2; ctx.stroke(); ctx.beginPath(); ctx.moveTo(x_ice+d*28, yIce); ctx.lineTo(x_ice+d*21,yIce-5); ctx.lineTo(x_ice+d*21,yIce+5); - ctx.fillStyle = '#0284c7'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.fill(); } - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#0284c7'; + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.fillText('v=' + Math.abs(v_ice).toFixed(1), x_ice - 12, yIce + 24); // Asphalt ball (orange) var yAsp = mid + (H - mid) / 2; ctx.beginPath(); ctx.arc(x_asp, yAsp, 13, 0, Math.PI * 2); ctx.fillStyle = '#fb923c'; ctx.fill(); - ctx.strokeStyle = '#ea580c'; ctx.lineWidth = 2; ctx.stroke(); - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#ea580c'; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.stroke(); + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); if (v_asp > 0.3) { ctx.beginPath(); ctx.moveTo(x_asp+14,yAsp); ctx.lineTo(x_asp+28,yAsp); - ctx.strokeStyle = '#ea580c'; ctx.lineWidth = 2; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.stroke(); ctx.beginPath(); ctx.moveTo(x_asp+28,yAsp); ctx.lineTo(x_asp+21,yAsp-5); ctx.lineTo(x_asp+21,yAsp+5); - ctx.fillStyle = '#ea580c'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.fill(); ctx.fillText('v=' + v_asp.toFixed(1), x_asp - 12, yAsp - 17); } else { ctx.fillText(' СТОИТ', x_asp - 18, yAsp - 17); @@ -4590,25 +4590,25 @@ function startAnim17() { // Force arrow var aLen = Math.min(55, F17 * 1.1); ctx.beginPath(); ctx.moveTo(x17 + bW, by + bH / 2); ctx.lineTo(x17 + bW + aLen, by + bH / 2); - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 3; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 3; ctx.stroke(); ctx.beginPath(); var ax = x17 + bW + aLen; ctx.moveTo(ax, by+bH/2); ctx.lineTo(ax-11,by+bH/2-5); ctx.lineTo(ax-11,by+bH/2+5); - ctx.fillStyle = '#ef4444'; ctx.fill(); - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#ef4444'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill(); + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fillText('F=' + F17 + 'Н', x17 + bW + 2, by - 4); // Velocity if (v17 > 0.5) { ctx.font = 'bold 9px Inter'; ctx.fillStyle = dk ? '#818cf8' : '#4338ca'; ctx.fillText('v = ' + v17.toFixed(1) + ' м/с →', x17, by - 16); } - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#10b981'; + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fillText('a = ' + a17.toFixed(1) + ' м/с²', 6, 14); // Physics v17 += a17 * 0.06; x17 += v17 * 0.7; t17++; if (x17 < W - 70 && t17 < 280) { anim17Id = requestAnimationFrame(fr17); } else { - ctx.font = 'bold 12px Inter'; ctx.fillStyle = '#10b981'; ctx.textAlign = 'center'; + ctx.font = 'bold 12px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.textAlign = 'center'; ctx.fillText(' v = ' + v17.toFixed(0) + ' м/с | a = ' + a17.toFixed(1) + ' м/с²', W/2, H/2 - 5); ctx.font = '10px Inter'; ctx.fillStyle = dk?'#94a3b8':'#64748b'; ctx.fillText('Поменяй ползунки и нажми «Запустить снова»', W/2, H/2 + 12); @@ -4647,11 +4647,11 @@ function startAnim18() { if (phase18 === 0) { // Static with spring ctx.fillStyle = '#6366f1'; ctx.fillRect(x1 - 34, y, 34, bH); - ctx.fillStyle = '#f97316'; ctx.fillRect(x2, y, 44, bH); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fillRect(x2, y, 44, bH); ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center'; ctx.fillText(m18a + ' кг', x1 - 17, y + bH/2 + 4); ctx.fillText(m18b + ' кг', x2 + 22, y + bH/2 + 4); ctx.textAlign = 'left'; - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2; ctx.beginPath(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.beginPath(); for (var ss = x1; ss < x2; ss += 4) { ctx.lineTo(ss, y + (ss % 8 < 4 ? bH * 0.25 : bH * 0.75)); } @@ -4670,7 +4670,7 @@ function startAnim18() { } x1 += v1; x2 += v2; ctx.fillStyle = '#6366f1'; ctx.fillRect(x1 - 34, y, 34, bH); - ctx.fillStyle = '#f97316'; ctx.fillRect(x2, y, 44, bH); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#f97316'); ctx.fillRect(x2, y, 44, bH); ctx.fillStyle = '#fff'; ctx.font = 'bold 9px Inter'; ctx.textAlign = 'center'; ctx.fillText(m18a + ' кг', x1 - 17, y + bH/2 + 4); ctx.fillText(m18b + ' кг', x2 + 22, y + bH/2 + 4); ctx.textAlign = 'left'; @@ -4740,11 +4740,11 @@ function drawSpring19() { var arLen = Math.min(65, F * 0.55); if (arLen > 4) { ctx.beginPath(); ctx.moveTo(bX, sy); ctx.lineTo(bX - arLen, sy); - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.stroke(); ctx.beginPath(); ctx.moveTo(bX - arLen, sy); ctx.lineTo(bX - arLen + 11, sy - 5); ctx.lineTo(bX - arLen + 11, sy + 5); - ctx.fillStyle = '#ef4444'; ctx.fill(); - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#ef4444'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill(); + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fillText('F = ' + F.toFixed(1) + ' Н', bX - arLen - 2, sy + 15); } ctx.font = '9px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#64748b'; @@ -4869,15 +4869,15 @@ function startAnim21() { } // Drop ball (orange) ctx.beginPath(); ctx.arc(startX21, fallY_px, 11, 0, Math.PI * 2); - ctx.fillStyle = '#fb923c'; ctx.fill(); ctx.strokeStyle = '#ea580c'; ctx.lineWidth = 2; ctx.stroke(); + ctx.fillStyle = '#fb923c'; ctx.fill(); ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.lineWidth = 2; ctx.stroke(); // Thrown ball (blue) ctx.beginPath(); ctx.arc(thrX_px, thrY_px, 11, 0, Math.PI * 2); - ctx.fillStyle = '#38bdf8'; ctx.fill(); ctx.strokeStyle = '#0284c7'; ctx.lineWidth = 2; ctx.stroke(); + ctx.fillStyle = '#38bdf8'; ctx.fill(); ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 2; ctx.stroke(); // Labels (first frame only) if (t21 < 4) { - ctx.font = 'bold 9px Inter'; ctx.fillStyle = '#ea580c'; + ctx.font = 'bold 9px Inter'; ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.fillText(' падение', startX21 + 14, fallY_px); - ctx.fillStyle = '#0284c7'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.fillText(' бросок →', thrX_px + 14, thrY_px - 4); } // Velocity components on thrown ball @@ -4885,13 +4885,13 @@ function startAnim21() { var vxL = Math.min(22, v0_21 * scaleX21 * 0.3); var vyL = Math.min(22, g21 * simT21 * scaleY21 * 0.3); ctx.beginPath(); ctx.moveTo(thrX_px+12, thrY_px); ctx.lineTo(thrX_px+12+vxL, thrY_px); - ctx.strokeStyle = '#0284c7'; ctx.lineWidth = 1.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.velocity:'#0284c7'); ctx.lineWidth = 1.5; ctx.stroke(); ctx.beginPath(); ctx.moveTo(thrX_px, thrY_px+12); ctx.lineTo(thrX_px, thrY_px+12+vyL); - ctx.strokeStyle = '#7c3aed'; ctx.lineWidth = 1.5; ctx.stroke(); + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceFriction:'#7c3aed'); ctx.lineWidth = 1.5; ctx.stroke(); } if (frac21 >= 1.0) landed21 = true; if (landed21) { - ctx.fillStyle = '#10b981'; ctx.font = 'bold 13px Inter'; ctx.textAlign = 'center'; + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.font = 'bold 13px Inter'; ctx.textAlign = 'center'; ctx.fillText(' Упали ОДНОВРЕМЕННО! t = ' + tTotal.toFixed(1) + ' с', W/2, groundY21 - 16); ctx.font = '10px Inter'; ctx.fillStyle = dk ? '#94a3b8' : '#475569'; ctx.fillText('Горизонтальная скорость не влияет на время падения!', W/2, groundY21 - 3); @@ -4946,12 +4946,12 @@ function drawEquilibrium28(typeIdx, ang) { ctx.beginPath(); ctx.arc(px, pivY, 6, 0, Math.PI * 2); ctx.fillStyle = dark ? '#64748b' : '#94a3b8'; ctx.fill(); ctx.beginPath(); ctx.arc(bx, by, 18, 0, Math.PI * 2); - ctx.fillStyle = '#1d4ed8'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.forceGravity:'#1d4ed8'); ctx.fill(); ctx.fillStyle = '#fff'; ctx.font = 'bold 10px Inter'; ctx.textAlign = 'center'; ctx.fillText('ЦТ', bx, by + 4); // Restore arrow if (Math.abs(ang) > 5) { - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2; ctx.beginPath(); ctx.arc(px, pivY, rodLen + 15, Math.PI/2, Math.PI/2 - rad * 0.5, rad > 0); ctx.stroke(); } @@ -5039,18 +5039,18 @@ function drawArchimedes29(rhoT, V, Ft, Farch) { ctx.fillText(rhoT, cx, blockY + blockSize / 2 + 4); // Archimedes arrow (up, green) var sc = Math.max(10, Math.min(60, Farch / 10)); - ctx.strokeStyle = '#10b981'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(cx + 35, blockY + blockSize); ctx.lineTo(cx + 35, blockY + blockSize - sc); ctx.stroke(); ctx.beginPath(); ctx.moveTo(cx + 32, blockY + blockSize - sc + 6); ctx.lineTo(cx + 35, blockY + blockSize - sc - 4); ctx.lineTo(cx + 38, blockY + blockSize - sc + 6); - ctx.fillStyle = '#10b981'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.force:'#10b981'); ctx.fill(); ctx.font = '10px Inter'; ctx.textAlign = 'left'; ctx.fillText('F_выт=' + Farch.toFixed(0) + 'Н', cx + 40, blockY + blockSize - sc / 2 + 4); // Weight arrow (down, red) var scFt = Math.max(10, Math.min(60, Ft / 10)); - ctx.strokeStyle = '#ef4444'; ctx.lineWidth = 2.5; + ctx.strokeStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.lineWidth = 2.5; ctx.beginPath(); ctx.moveTo(cx - 35, blockY); ctx.lineTo(cx - 35, blockY + scFt); ctx.stroke(); ctx.beginPath(); ctx.moveTo(cx - 38, blockY + scFt - 6); ctx.lineTo(cx - 35, blockY + scFt + 4); ctx.lineTo(cx - 32, blockY + scFt - 6); - ctx.fillStyle = '#ef4444'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.plotPrimary:'#ef4444'); ctx.fill(); ctx.font = '10px Inter'; ctx.textAlign = 'right'; ctx.fillText('F_т=' + Ft.toFixed(0) + 'Н', cx - 40, blockY + scFt / 2 + 4); ctx.textAlign = 'left'; @@ -5584,7 +5584,7 @@ function drawLab11() { const b1x = bpx - Math.sin(ang) * (BR + 1); const b1y = bpy + Math.cos(ang) * (BR + 1); ctx.beginPath(); ctx.arc(b1x, b1y, BR, 0, Math.PI * 2); - ctx.fillStyle = '#2563eb'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.displacement:'#2563eb'); ctx.fill(); ctx.strokeStyle = '#93c5fd'; ctx.lineWidth = 1.5; ctx.stroke(); ctx.fillStyle = '#fff'; ctx.font = 'bold 8px Inter'; ctx.textAlign = 'center'; ctx.fillText('1', b1x, b1y + 3); @@ -5592,7 +5592,7 @@ function drawLab11() { // ── Ball 2 at edge ──────────────────────────────────────────── const b2x = EX + BR + 2, b2y = TY - BR; ctx.beginPath(); ctx.arc(b2x, b2y, BR, 0, Math.PI * 2); - ctx.fillStyle = '#ea580c'; ctx.fill(); + ctx.fillStyle = (window.PHYS9_COLORS?window.PHYS9_COLORS.acceleration:'#ea580c'); ctx.fill(); ctx.strokeStyle = '#fbbf24'; ctx.lineWidth = 1.5; ctx.stroke(); ctx.fillStyle = '#fff'; ctx.font = 'bold 8px Inter'; ctx.textAlign = 'center'; ctx.fillText('2', b2x, b2y + 3);