Meta Description" name="description" />

Share this result

Previews are deleted daily. Get a permanent share link sent to your inbox:
Script
<!DOCTYPE html> <html lang="fr"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Les Vecteurs — 3ème | Capsule Interactive</title> <!-- MathJax --> <script> MathJax = { tex: { inlineMath: [['$','$'], ['\\(','\\)']], displayMath: [['$$','$$'], ['\\[','\\]']] }, options: { skipHtmlTags: ['script','noscript','style','textarea','pre'] } }; </script> <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js" async></script> <style> /* ===== DESIGN SYSTEM ===== */ @import url('https://fonts.googleapis.com/css2?family=Syne:wght@400;600;700;800&family=DM+Sans:wght@300;400;500&display=swap'); :root { --bg: #0d0f1a; --surface: #141726; --card: #1a1f35; --border: #272d4a; --accent1: #5b8fff; /* bleu vif */ --accent2: #ff6b6b; /* rouge coral */ --accent3: #4ecdc4; /* turquoise */ --accent4: #ffd166; /* jaune */ --accent5: #a29bfe; /* violet doux */ --text: #e8ecf8; --muted: #8892b0; --success: #56cf8c; --radius: 16px; --shadow: 0 8px 32px rgba(0,0,0,.4); } *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { scroll-behavior: smooth; } body { font-family: 'DM Sans', sans-serif; background: var(--bg); color: var(--text); line-height: 1.65; overflow-x: hidden; } /* ===== HEADER ===== */ header { position: relative; padding: 80px 24px 60px; text-align: center; overflow: hidden; } header::before { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse 80% 60% at 50% -10%, rgba(91,143,255,.25) 0%, transparent 70%); pointer-events: none; } .header-badge { display: inline-block; background: rgba(91,143,255,.15); border: 1px solid rgba(91,143,255,.4); color: var(--accent1); font-size: .8rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; padding: 6px 18px; border-radius: 999px; margin-bottom: 20px; animation: fadeUp .6s ease both; } header h1 { font-family: 'Syne', sans-serif; font-size: clamp(2.6rem, 6vw, 5rem); font-weight: 800; line-height: 1.05; animation: fadeUp .6s .1s ease both; } header h1 span { color: var(--accent1); } header p.subtitle { max-width: 560px; margin: 16px auto 0; color: var(--muted); font-size: 1.05rem; animation: fadeUp .6s .2s ease both; } /* nav pills */ .nav-pills { display: flex; flex-wrap: wrap; justify-content: center; gap: 10px; margin-top: 36px; animation: fadeUp .6s .3s ease both; } .nav-pill { background: var(--card); border: 1px solid var(--border); color: var(--muted); font-size: .85rem; font-weight: 500; padding: 8px 18px; border-radius: 999px; cursor: pointer; transition: all .2s; text-decoration: none; } .nav-pill:hover { border-color: var(--accent1); color: var(--accent1); } /* ===== LAYOUT ===== */ main { max-width: 1100px; margin: 0 auto; padding: 0 20px 100px; } /* ===== SECTION ===== */ .section { margin-bottom: 60px; opacity: 0; transform: translateY(30px); transition: opacity .6s ease, transform .6s ease; } .section.visible { opacity: 1; transform: none; } .section-header { display: flex; align-items: center; gap: 14px; margin-bottom: 24px; } .section-number { width: 42px; height: 42px; background: linear-gradient(135deg, var(--accent1), var(--accent5)); border-radius: 12px; display: flex; align-items: center; justify-content: center; font-family: 'Syne', sans-serif; font-weight: 800; font-size: .95rem; flex-shrink: 0; } .section-title { font-family: 'Syne', sans-serif; font-size: 1.55rem; font-weight: 700; } /* ===== CARDS ===== */ .card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow); } .card + .card { margin-top: 16px; } .card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; } .highlight-card { border-color: rgba(91,143,255,.5); background: linear-gradient(135deg, rgba(91,143,255,.08), rgba(162,155,254,.06)); } /* ===== DEFINITION CHIPS ===== */ .def-chips { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 16px; } .def-chip { display: flex; align-items: flex-start; gap: 10px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px 18px; flex: 1; min-width: 200px; } .def-chip .chip-icon { font-size: 1.4rem; margin-top: 2px; flex-shrink: 0; } .def-chip .chip-label { font-size: .75rem; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); } .def-chip .chip-value { font-size: .95rem; margin-top: 2px; } /* ===== FORMULA BOX ===== */ .formula-box { background: linear-gradient(135deg, rgba(78,205,196,.08), rgba(91,143,255,.06)); border: 1px solid rgba(78,205,196,.35); border-radius: 12px; padding: 20px 24px; margin: 16px 0; text-align: center; font-size: 1.1rem; } /* ===== CANVAS WIDGETS ===== */ .widget { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); } .widget-header { padding: 16px 22px; border-bottom: 1px solid var(--border); display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 10px; } .widget-title { font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1rem; display: flex; align-items: center; gap: 8px; } .widget-tag { font-size: .72rem; font-weight: 600; letter-spacing: .1em; text-transform: uppercase; padding: 3px 10px; border-radius: 999px; background: rgba(91,143,255,.15); color: var(--accent1); } .widget-body { padding: 20px; } canvas { display: block; border-radius: 10px; background: #0f1220; cursor: crosshair; touch-action: none; max-width: 100%; } .info-panel { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 14px 18px; margin-top: 14px; font-size: .9rem; display: flex; flex-wrap: wrap; gap: 16px; } .info-item { display: flex; flex-direction: column; gap: 2px; } .info-label { font-size: .73rem; text-transform: uppercase; letter-spacing: .1em; color: var(--muted); } .info-value { font-family: 'Syne', sans-serif; font-weight: 700; font-size: 1.05rem; } .info-value.blue { color: var(--accent1); } .info-value.red { color: var(--accent2); } .info-value.teal { color: var(--accent3); } .info-value.gold { color: var(--accent4); } /* ===== BUTTONS ===== */ .btn { display: inline-flex; align-items: center; gap: 7px; padding: 10px 20px; border-radius: 10px; font-family: 'DM Sans', sans-serif; font-size: .88rem; font-weight: 500; cursor: pointer; border: 1px solid transparent; transition: all .2s; } .btn-primary { background: var(--accent1); color: #fff; } .btn-primary:hover { background: #7aa5ff; transform: translateY(-1px); } .btn-ghost { background: transparent; border-color: var(--border); color: var(--muted); } .btn-ghost:hover { border-color: var(--accent1); color: var(--accent1); } .btn-danger { background: rgba(255,107,107,.15); border-color: rgba(255,107,107,.4); color: var(--accent2); } .btn-danger:hover { background: rgba(255,107,107,.25); } .btn-success { background: rgba(86,207,140,.15); border-color: rgba(86,207,140,.4); color: var(--success); } .btn-success:hover { background: rgba(86,207,140,.25); } .btn-group { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; } /* ===== EXERCISES ===== */ .exercise { background: var(--surface); border: 1px solid var(--border); border-left: 4px solid var(--accent4); border-radius: 12px; padding: 22px 24px; margin-bottom: 16px; } .exercise-num { font-size: .72rem; font-weight: 700; text-transform: uppercase; letter-spacing: .1em; color: var(--accent4); margin-bottom: 8px; } .exercise h4 { font-family: 'Syne', sans-serif; font-size: 1rem; margin-bottom: 10px; } .exercise p { color: var(--muted); font-size: .93rem; } .answer-input { background: var(--card); border: 1px solid var(--border); color: var(--text); font-family: 'DM Sans', sans-serif; font-size: .95rem; padding: 10px 14px; border-radius: 8px; width: 100%; margin-top: 10px; outline: none; transition: border-color .2s; } .answer-input:focus { border-color: var(--accent1); } .feedback { margin-top: 10px; padding: 10px 14px; border-radius: 8px; font-size: .9rem; display: none; } .feedback.correct { background: rgba(86,207,140,.12); border: 1px solid rgba(86,207,140,.35); color: var(--success); display: block; } .feedback.wrong { background: rgba(255,107,107,.12); border: 1px solid rgba(255,107,107,.35); color: var(--accent2); display: block; } /* ===== PROF MODE ===== */ .prof-mode { border: 2px solid var(--accent4); border-radius: var(--radius); overflow: hidden; } .prof-header { background: linear-gradient(135deg, rgba(255,209,102,.12), rgba(255,209,102,.05)); border-bottom: 1px solid rgba(255,209,102,.3); padding: 16px 22px; display: flex; align-items: center; gap: 10px; } .prof-badge { background: var(--accent4); color: #0d0f1a; font-size: .72rem; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; padding: 4px 12px; border-radius: 999px; } .prof-tools { padding: 14px 20px; border-bottom: 1px solid var(--border); display: flex; flex-wrap: wrap; gap: 8px; align-items: center; } .tool-btn { padding: 8px 14px; border-radius: 8px; font-size: .83rem; font-weight: 500; cursor: pointer; border: 1px solid var(--border); background: var(--surface); color: var(--muted); transition: all .2s; display: flex; align-items: center; gap: 6px; } .tool-btn:hover { border-color: var(--accent1); color: var(--accent1); } .tool-btn.active { background: rgba(91,143,255,.15); border-color: var(--accent1); color: var(--accent1); } /* color picker row */ .color-row { display: flex; gap: 8px; align-items: center; } .color-dot { width: 22px; height: 22px; border-radius: 50%; cursor: pointer; border: 2px solid transparent; transition: border-color .15s, transform .15s; } .color-dot:hover { transform: scale(1.15); } .color-dot.active { border-color: #fff; } input[type="range"] { accent-color: var(--accent1); width: 90px; } /* ===== GEOGEBRA ===== */ .ggb-wrap { border-radius: 12px; overflow: hidden; border: 1px solid var(--border); position: relative; background: #fff; } .ggb-wrap iframe { display: block; width: 100%; } /* ===== PROGRESS BAR ===== */ .progress-wrap { position: fixed; top: 0; left: 0; right: 0; height: 3px; background: transparent; z-index: 999; } #progress-bar { height: 100%; background: linear-gradient(90deg, var(--accent1), var(--accent3)); width: 0%; transition: width .1s; } /* ===== ANIMATIONS ===== */ @keyframes fadeUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: none; } } @keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 rgba(91,143,255,.4); } 50% { box-shadow: 0 0 0 8px rgba(91,143,255,0); } } /* ===== TOOLTIP ===== */ .tooltip-text { background: rgba(20,23,38,.95); border: 1px solid var(--border); border-radius: 8px; padding: 6px 10px; font-size: .8rem; color: var(--text); pointer-events: none; position: absolute; z-index: 99; white-space: nowrap; } /* ===== SCROLLBAR ===== */ ::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar-track { background: var(--bg); } ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; } /* ===== RESPONSIVE ===== */ @media (max-width: 640px) { header { padding: 60px 16px 40px; } .widget-header { flex-direction: column; align-items: flex-start; } canvas { height: 260px !important; } .info-panel { flex-direction: column; gap: 10px; } } </style> </head> <body> <!-- Progress bar --> <div class="progress-wrap"><div id="progress-bar"></div></div> <!-- ===== HEADER ===== --> <header> <div class="header-badge">Mathématiques · 3ème</div> <h1>Les <span>Vecteurs</span></h1> <p class="subtitle">Capsule interactive — comprends, explore et maîtrise les vecteurs avec des outils dynamiques</p> <nav class="nav-pills"> <a class="nav-pill" href="#intro">Introduction</a> <a class="nav-pill" href="#definition">Définition</a> <a class="nav-pill" href="#egaux">Vecteurs égaux</a> <a class="nav-pill" href="#chasles">Relation de Chasles</a> <a class="nav-pill" href="#coordonnees">Coordonnées</a> <a class="nav-pill" href="#norme">Norme</a> <a class="nav-pill" href="#geogebra">GeoGebra</a> <a class="nav-pill" href="#exercices">Exercices</a> <a class="nav-pill" href="#prof">Mode Prof</a> </nav> </header> <main> <!-- ===== 1. INTRODUCTION ===== --> <section class="section" id="intro"> <div class="section-header"> <div class="section-number">1</div> <div class="section-title">Introduction intuitive</div> </div> <div class="card card-grid" style="display:grid"> <div style="grid-template-columns:1fr 1fr;display:grid;gap:16px"> <div class="card highlight-card"> <p style="font-size:2rem;margin-bottom:10px">🚶</p> <h3 style="font-family:'Syne',sans-serif;margin-bottom:8px">Un déplacement</h3> <p style="color:var(--muted)">Imagine que tu te déplaces de la maison jusqu'à l'école. Ce déplacement a une <strong style="color:var(--text)">direction</strong> (la rue), un <strong style="color:var(--text)">sens</strong> (maison → école) et une <strong style="color:var(--text)">longueur</strong>.</p> </div> <div class="card highlight-card"> <p style="font-size:2rem;margin-bottom:10px">➡️</p> <h3 style="font-family:'Syne',sans-serif;margin-bottom:8px">Un vecteur, c'est ça !</h3> <p style="color:var(--muted)">Un <strong style="color:var(--accent1)">vecteur</strong> représente mathématiquement ce déplacement. On le dessine avec une flèche. Peu importe où tu commences, si tu fais le même déplacement, c'est le <strong style="color:var(--text)">même vecteur</strong>.</p> </div> </div> </div> <div class="card" style="margin-top:16px;padding:0;overflow:hidden"> <div class="widget-header"> <span class="widget-title">🎯 Déplace les points A et B</span> <span class="widget-tag">Interactif</span> </div> <div class="widget-body"> <canvas id="introCanvas" width="660" height="300" style="width:100%;height:300px"></canvas> <div class="info-panel" id="introInfo"> <div class="info-item"><span class="info-label">Vecteur</span><span class="info-value blue" id="introVec">AB</span></div> <div class="info-item"><span class="info-label">Coordonnées</span><span class="info-value teal" id="introCoord">(0, 0)</span></div> <div class="info-item"><span class="info-label">Norme</span><span class="info-value gold" id="introNorm">0</span></div> <div class="info-item"><span class="info-label">Direction</span><span class="info-value" id="introAngle" style="color:var(--accent5)">0°</span></div> </div> </div> </div> </section> <!-- ===== 2. DEFINITION ===== --> <section class="section" id="definition"> <div class="section-header"> <div class="section-number">2</div> <div class="section-title">Définition d'un vecteur</div> </div> <div class="card"> <p>Un <strong style="color:var(--accent1)">vecteur \(\overrightarrow{AB}\)</strong> est caractérisé par <strong>trois éléments</strong> :</p> <div class="def-chips"> <div class="def-chip"> <span class="chip-icon">📐</span> <div> <div class="chip-label">Direction</div> <div class="chip-value">La droite qui porte le vecteur (son inclinaison)</div> </div> </div> <div class="def-chip"> <span class="chip-icon">➡️</span> <div> <div class="chip-label">Sens</div> <div class="chip-value">Le côté vers lequel pointe la flèche (de A vers B)</div> </div> </div> <div class="def-chip"> <span class="chip-icon">📏</span> <div> <div class="chip-label">Norme (longueur)</div> <div class="chip-value">La longueur de la flèche, notée $|\overrightarrow{AB}|$</div> </div> </div> </div> <div class="formula-box" style="margin-top:20px"> La notation correcte d'un vecteur : $$\overrightarrow{AB}$$ Le point $A$ est l'<strong>origine</strong>, le point $B$ est l'<strong>extrémité</strong>. </div> <p style="color:var(--muted);font-size:.9rem;margin-top:12px">⚠️ Attention : $\overrightarrow{AB} \neq \overrightarrow{BA}$ — ils ont le même sens de droite, mais des <strong style="color:var(--text)">sens opposés</strong> !</p> </div> </section> <!-- ===== 3. VECTEURS EGAUX ===== --> <section class="section" id="egaux"> <div class="section-header"> <div class="section-number">3</div> <div class="section-title">Vecteurs égaux</div> </div> <div class="card"> <p>Deux vecteurs sont <strong style="color:var(--accent3)">égaux</strong> s'ils ont la même direction, le même sens et la même norme.</p> <div class="formula-box"> $\overrightarrow{AB} = \overrightarrow{CD}$ si et seulement si $ABDC$ est un <strong>parallélogramme</strong> <br><small style="color:var(--muted)">(ou si les deux vecteurs sont nuls)</small> </div> </div> <div class="widget" style="margin-top:16px"> <div class="widget-header"> <span class="widget-title">🔁 Vecteurs égaux — Parallélogramme</span> <span class="widget-tag">Interactif</span> </div> <div class="widget-body"> <p style="color:var(--muted);font-size:.87rem;margin-bottom:12px">Déplace A ou B — C et D sont construits automatiquement pour que $\overrightarrow{AB} = \overrightarrow{CD}$</p> <canvas id="equalCanvas" width="660" height="320" style="width:100%;height:320px"></canvas> <div class="info-panel"> <div class="info-item"><span class="info-label">AB</span><span class="info-value blue" id="eqAB">(0, 0)</span></div> <div class="info-item"><span class="info-label">CD</span><span class="info-value teal" id="eqCD">(0, 0)</span></div> <div class="info-item"><span class="info-label">Égaux ?</span><span class="info-value green" id="eqStatus" style="color:var(--success)">✓ Oui</span></div> </div> </div> </div> </section> <!-- ===== 4. CHASLES ===== --> <section class="section" id="chasles"> <div class="section-header"> <div class="section-number">4</div> <div class="section-title">Relation de Chasles</div> </div> <div class="card highlight-card"> <h3 style="font-family:'Syne',sans-serif;margin-bottom:12px">📌 Théorème</h3> <div class="formula-box"> $$\overrightarrow{AC} = \overrightarrow{AB} + \overrightarrow{BC}$$ </div> <p style="color:var(--muted)">Pour aller de A à C, je peux passer par un point intermédiaire B. Le vecteur $\overrightarrow{AC}$ est la <strong style="color:var(--text)">somme</strong> de $\overrightarrow{AB}$ et $\overrightarrow{BC}$.</p> <div class="formula-box" style="margin-top:12px;border-color:rgba(255,107,107,.35);background:rgba(255,107,107,.06)"> Conséquence : $\overrightarrow{AB} + \overrightarrow{BA} = \overrightarrow{AA} = \vec{0}$ </div> </div> <div class="widget" style="margin-top:16px"> <div class="widget-header"> <span class="widget-title">➕ Visualisation de la relation de Chasles</span> <span class="widget-tag">Interactif</span> </div> <div class="widget-body"> <p style="color:var(--muted);font-size:.87rem;margin-bottom:12px">Déplace A, B ou C pour voir comment $\overrightarrow{AB} + \overrightarrow{BC} = \overrightarrow{AC}$</p> <canvas id="chaslesCanvas" width="660" height="340" style="width:100%;height:340px"></canvas> <div class="info-panel"> <div class="info-item"><span class="info-label">AB</span><span class="info-value blue" id="chAB">(0,0)</span></div> <div class="info-item"><span class="info-label">BC</span><span class="info-value teal" id="chBC">(0,0)</span></div> <div class="info-item"><span class="info-label">AC = AB + BC</span><span class="info-value" style="color:var(--accent5)" id="chAC">(0,0)</span></div> <div class="info-item"><span class="info-label">|AC|</span><span class="info-value gold" id="chNorm">0</span></div> </div> </div> </div> </section> <!-- ===== 5. COORDONNEES ===== --> <section class="section" id="coordonnees"> <div class="section-header"> <div class="section-number">5</div> <div class="section-title">Coordonnées d'un vecteur</div> </div> <div class="card"> <p>Dans un repère, si $A(x_A ; y_A)$ et $B(x_B ; y_B)$, alors :</p> <div class="formula-box"> $$\overrightarrow{AB} = \begin{pmatrix} x_B - x_A \\ y_B - y_A \end{pmatrix}$$ </div> <p style="color:var(--muted);margin-top:8px">Exemple : si $A(2\,;\,1)$ et $B(5\,;\,4)$, alors $\overrightarrow{AB} = \begin{pmatrix} 3 \\ 3 \end{pmatrix}$</p> </div> <div class="widget" style="margin-top:16px"> <div class="widget-header"> <span class="widget-title">📊 Repère interactif avec coordonnées</span> <span class="widget-tag">Interactif</span> </div> <div class="widget-body"> <canvas id="coordCanvas" width="660" height="360" style="width:100%;height:360px"></canvas> <div class="info-panel"> <div class="info-item"><span class="info-label">A</span><span class="info-value blue" id="coordA">(0, 0)</span></div> <div class="info-item"><span class="info-label">B</span><span class="info-value teal" id="coordB">(0, 0)</span></div> <div class="info-item"><span class="info-label">$x_B - x_A$</span><span class="info-value gold" id="coordDx">0</span></div> <div class="info-item"><span class="info-label">$y_B - y_A$</span><span class="info-value" style="color:var(--accent5)" id="coordDy">0</span></div> <div class="info-item"><span class="info-label">Vecteur</span><span class="info-value red" id="coordVec">(0; 0)</span></div> </div> </div> </div> </section> <!-- ===== 6. NORME ===== --> <section class="section" id="norme"> <div class="section-header"> <div class="section-number">6</div> <div class="section-title">Norme d'un vecteur</div> </div> <div class="card highlight-card"> <div class="formula-box"> $$\left|\overrightarrow{AB}\right| = \sqrt{(x_B - x_A)^2 + (y_B - y_A)^2}$$ </div> <p style="color:var(--muted);margin-top:8px">C'est simplement la <strong style="color:var(--text)">distance</strong> entre A et B — le théorème de Pythagore !</p> </div> <div class="card" style="margin-top:16px"> <h4 style="font-family:'Syne',sans-serif;margin-bottom:12px">Exemple de calcul</h4> <p>Soit $A(1\,;\,2)$ et $B(4\,;\,6)$. Calcule $|\overrightarrow{AB}|$.</p> <div class="formula-box" style="margin-top:12px;text-align:left"> $\overrightarrow{AB} = \begin{pmatrix} 4-1 \\ 6-2 \end{pmatrix} = \begin{pmatrix} 3 \\ 4 \end{pmatrix}$ <br><br> $|\overrightarrow{AB}| = \sqrt{3^2 + 4^2} = \sqrt{9+16} = \sqrt{25} = 5$ </div> </div> <!-- Calculatrice de norme --> <div class="card" style="margin-top:16px"> <h4 style="font-family:'Syne',sans-serif;margin-bottom:14px">🧮 Calculatrice de norme</h4> <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px"> <div><label style="font-size:.8rem;color:var(--muted);display:block;margin-bottom:5px">$x_A$</label><input type="number" id="nxA" value="1" class="answer-input" style="margin:0"></div> <div><label style="font-size:.8rem;color:var(--muted);display:block;margin-bottom:5px">$y_A$</label><input type="number" id="nyA" value="2" class="answer-input" style="margin:0"></div> <div><label style="font-size:.8rem;color:var(--muted);display:block;margin-bottom:5px">$x_B$</label><input type="number" id="nxB" value="4" class="answer-input" style="margin:0"></div> <div><label style="font-size:.8rem;color:var(--muted);display:block;margin-bottom:5px">$y_B$</label><input type="number" id="nyB" value="6" class="answer-input" style="margin:0"></div> </div> <button class="btn btn-primary" onclick="calcNorme()" style="margin-top:14px">Calculer</button> <div id="normeResult" style="margin-top:14px;padding:14px;border-radius:10px;background:var(--surface);display:none;font-size:.95rem"></div> </div> </section> <!-- ===== 7. GEOGEBRA ===== --> <section class="section" id="geogebra"> <div class="section-header"> <div class="section-number">7</div> <div class="section-title">Exploration GeoGebra</div> </div> <div class="card"> <p style="margin-bottom:16px;color:var(--muted)">Manipule directement les vecteurs dans cet applet GeoGebra — déplace les points, observe les propriétés !</p> <div class="ggb-wrap"> <iframe src="https://www.geogebra.org/material/iframe/id/rfhq44kb/width/800/height/480/border/888888/sfsb/true/smb/false/stb/false/stbh/false/ai/false/asb/false/sri/true/rc/false/ld/false/sdz/true/ctl/false" width="800" height="480" style="width:100%" allowfullscreen title="GeoGebra — Vecteurs interactifs"> </iframe> </div> <p style="margin-top:12px;font-size:.82rem;color:var(--muted)">💡 Tip : déplace les points directement dans l'applet pour explorer la relation de Chasles.</p> </div> </section> <!-- ===== 8. EXERCICES ===== --> <section class="section" id="exercices"> <div class="section-header"> <div class="section-number">8</div> <div class="section-title">Exercices interactifs</div> </div> <!-- Ex 1 --> <div class="exercise"> <div class="exercise-num">Exercice 1 — Coordonnées</div> <h4>Calcule les coordonnées du vecteur $\overrightarrow{AB}$</h4> <p>On donne $A(3\,;\,1)$ et $B(7\,;\,5)$.</p> <p style="margin-top:8px">Donne la valeur de $x_B - x_A$ (la première coordonnée) :</p> <input type="number" id="ex1" class="answer-input" placeholder="Votre réponse..." oninput="checkEx1()"> <div id="fb1" class="feedback"></div> </div> <!-- Ex 2 --> <div class="exercise"> <div class="exercise-num">Exercice 2 — Norme</div> <h4>Calcule la norme du vecteur $\overrightarrow{AB}$</h4> <p>On donne $A(0\,;\,0)$ et $B(3\,;\,4)$. Quelle est la norme de $\overrightarrow{AB}$ ?</p> <input type="number" id="ex2" class="answer-input" placeholder="Votre réponse..." oninput="checkEx2()"> <div id="fb2" class="feedback"></div> </div> <!-- Ex 3 --> <div class="exercise"> <div class="exercise-num">Exercice 3 — Relation de Chasles</div> <h4>Simplifie l'expression suivante :</h4> <p>Soit $\overrightarrow{AB} + \overrightarrow{BC} = ?$</p> <div style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px"> <button class="btn btn-ghost" onclick="checkEx3('AB')">$\overrightarrow{AB}$</button> <button class="btn btn-ghost" onclick="checkEx3('AC')">$\overrightarrow{AC}$</button> <button class="btn btn-ghost" onclick="checkEx3('BC')">$\overrightarrow{BC}$</button> <button class="btn btn-ghost" onclick="checkEx3('0')">$\vec{0}$</button> </div> <div id="fb3" class="feedback"></div> </div> <!-- Ex 4 --> <div class="exercise"> <div class="exercise-num">Exercice 4 — Vecteurs égaux</div> <h4>Vrai ou Faux ?</h4> <p>$\overrightarrow{AB}$ et $\overrightarrow{BA}$ sont des vecteurs égaux.</p> <div style="display:flex;gap:10px;margin-top:12px"> <button class="btn btn-ghost" onclick="checkEx4(true)">✓ Vrai</button> <button class="btn btn-ghost" onclick="checkEx4(false)">✗ Faux</button> </div> <div id="fb4" class="feedback"></div> </div> <!-- Ex 5 --> <div class="exercise"> <div class="exercise-num">Exercice 5 — Chasles avancé</div> <h4>Complète la relation de Chasles</h4> <p>$\overrightarrow{AC} - \overrightarrow{BC} = ?$</p> <div style="display:flex;flex-wrap:wrap;gap:10px;margin-top:12px"> <button class="btn btn-ghost" onclick="checkEx5('AB')">$\overrightarrow{AB}$</button> <button class="btn btn-ghost" onclick="checkEx5('BC')">$\overrightarrow{BC}$</button> <button class="btn btn-ghost" onclick="checkEx5('CA')">$\overrightarrow{CA}$</button> <button class="btn btn-ghost" onclick="checkEx5('0')">$\vec{0}$</button> </div> <div id="fb5" class="feedback"></div> </div> </section> <!-- ===== 9. MODE PROF ===== --> <section class="section" id="prof"> <div class="section-header"> <div class="section-number">9</div> <div class="section-title">Mode Professeur</div> </div> <div class="prof-mode widget"> <div class="prof-header"> <span class="prof-badge">👩‍🏫 PROF</span> <span style="font-family:'Syne',sans-serif;font-weight:700">Tableau de démonstration libre</span> </div> <div class="prof-tools"> <!-- Tool buttons --> <button class="tool-btn active" id="toolDraw" onclick="setProfTool('draw')">✏️ Dessiner</button> <button class="tool-btn" id="toolVector" onclick="setProfTool('vector')">➡️ Vecteur</button> <button class="tool-btn" id="toolPoint" onclick="setProfTool('point')">📍 Point</button> <button class="tool-btn" id="toolText" onclick="setProfTool('text')">🔤 Texte</button> <div style="width:1px;height:28px;background:var(--border)"></div> <!-- Color row --> <div class="color-row"> <div class="color-dot active" style="background:#5b8fff" onclick="setProfColor('#5b8fff',this)"></div> <div class="color-dot" style="background:#ff6b6b" onclick="setProfColor('#ff6b6b',this)"></div> <div class="color-dot" style="background:#4ecdc4" onclick="setProfColor('#4ecdc4',this)"></div> <div class="color-dot" style="background:#ffd166" onclick="setProfColor('#ffd166',this)"></div> <div class="color-dot" style="background:#ffffff" onclick="setProfColor('#ffffff',this)"></div> <div class="color-dot" style="background:#a29bfe" onclick="setProfColor('#a29bfe',this)"></div> </div> <div style="width:1px;height:28px;background:var(--border)"></div> <label style="font-size:.8rem;color:var(--muted);display:flex;align-items:center;gap:8px"> Épaisseur <input type="range" id="profSize" min="1" max="12" value="3"> </label> <div style="margin-left:auto;display:flex;gap:8px"> <button class="btn btn-ghost" onclick="undoProf()">↩️ Annuler</button> <button class="btn btn-danger" onclick="clearProf()">🗑️ Effacer tout</button> </div> </div> <div style="padding:16px"> <canvas id="profCanvas" width="800" height="500" style="width:100%;height:500px;cursor:crosshair"></canvas> </div> <div style="padding:10px 16px;border-top:1px solid var(--border);font-size:.8rem;color:var(--muted)"> 💡 Clic + glisser pour dessiner · Mode Vecteur : cliquer le point de départ puis l'extrémité · Mode Point : cliquer pour placer </div> </div> </section> </main> <!-- ===== FOOTER ===== --> <footer style="text-align:center;padding:40px 20px;border-top:1px solid var(--border);color:var(--muted);font-size:.85rem"> <p>Capsule interactive Vecteurs · 3ème · Mathématiques</p> <p style="margin-top:4px;font-size:.78rem;opacity:.6">Conçu pour être utilisé en classe ou en autonomie</p> </footer> <!-- ===== JAVASCRIPT ===== --> <script> /* ============================================================ UTILITAIRES CANVAS COMMUNES ============================================================ */ // Dessiner une flèche sur canvas function drawArrow(ctx, x1,y1,x2,y2, color='#5b8fff', width=2.5, label='', labelColor='') { const dx = x2-x1, dy = y2-y1; const len = Math.hypot(dx,dy); if (len < 2) return; const angle = Math.atan2(dy,dx); const headLen = Math.min(18, len*0.35); ctx.save(); ctx.strokeStyle = color; ctx.fillStyle = color; ctx.lineWidth = width; ctx.lineJoin = 'round'; ctx.lineCap = 'round'; ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); // arrowhead ctx.beginPath(); ctx.moveTo(x2, y2); ctx.lineTo(x2 - headLen*Math.cos(angle-0.42), y2 - headLen*Math.sin(angle-0.42)); ctx.lineTo(x2 - headLen*Math.cos(angle+0.42), y2 - headLen*Math.sin(angle+0.42)); ctx.closePath(); ctx.fill(); // label if (label) { ctx.font = 'bold 13px Syne, sans-serif'; ctx.fillStyle = labelColor || color; const mx = (x1+x2)/2 - 14*Math.sin(angle); const my = (y1+y2)/2 + 14*Math.cos(angle); ctx.fillText(label, mx, my); } ctx.restore(); } function drawPoint(ctx, x, y, color='#fff', radius=6, label='', labelOffset={x:10,y:-10}) { ctx.save(); ctx.beginPath(); ctx.arc(x,y,radius,0,Math.PI*2); ctx.fillStyle = color; ctx.fill(); ctx.strokeStyle = 'rgba(0,0,0,.4)'; ctx.lineWidth = 1.5; ctx.stroke(); if (label) { ctx.font = 'bold 14px Syne, sans-serif'; ctx.fillStyle = color; ctx.fillText(label, x+labelOffset.x, y+labelOffset.y); } ctx.restore(); } function drawGrid(ctx, w, h, step=40, originX, originY) { ctx.save(); ctx.strokeStyle = 'rgba(255,255,255,.05)'; ctx.lineWidth = 1; for (let x=0; x<w; x+=step) { ctx.beginPath(); ctx.moveTo(x,0); ctx.lineTo(x,h); ctx.stroke(); } for (let y=0; y<h; y+=step) { ctx.beginPath(); ctx.moveTo(0,y); ctx.lineTo(w,y); ctx.stroke(); } // axes if (originX !== undefined) { ctx.strokeStyle = 'rgba(255,255,255,.25)'; ctx.lineWidth = 1.5; ctx.beginPath(); ctx.moveTo(0,originY); ctx.lineTo(w,originY); ctx.stroke(); ctx.beginPath(); ctx.moveTo(originX,0); ctx.lineTo(originX,h); ctx.stroke(); // ticks and labels ctx.fillStyle = 'rgba(255,255,255,.35)'; ctx.font = '10px DM Sans'; for (let x=originX; x<w; x+=step) { const val = Math.round((x-originX)/step); if (val!==0) ctx.fillText(val, x-4, originY+14); ctx.beginPath(); ctx.moveTo(x,originY-3); ctx.lineTo(x,originY+3); ctx.stroke(); } for (let x=originX; x>0; x-=step) { const val = Math.round((x-originX)/step); ctx.fillText(val, x-8, originY+14); ctx.beginPath(); ctx.moveTo(x,originY-3); ctx.lineTo(x,originY+3); ctx.stroke(); } for (let y=originY; y<h; y+=step) { const val = -Math.round((y-originY)/step); if (val!==0) ctx.fillText(val, originX-20, y+4); ctx.beginPath(); ctx.moveTo(originX-3,y); ctx.lineTo(originX+3,y); ctx.stroke(); } for (let y=originY; y>0; y-=step) { const val = -Math.round((y-originY)/step); ctx.fillText(val, originX-20, y+4); ctx.beginPath(); ctx.moveTo(originX-3,y); ctx.lineTo(originX+3,y); ctx.stroke(); } ctx.fillStyle='rgba(255,255,255,.5)';ctx.font='bold 12px Syne'; ctx.fillText('x',w-16,originY-8); ctx.fillText('y',originX+8,12); ctx.fillText('O',originX+5,originY+14); } ctx.restore(); } // drag helper function makeDraggable(canvas, points, onUpdate) { let drag = null; const rect = () => canvas.getBoundingClientRect(); const pos = (e) => { const r = rect(); const scaleX = canvas.width / r.width; const scaleY = canvas.height / r.height; const src = e.touches ? e.touches[0] : e; return { x: (src.clientX - r.left)*scaleX, y: (src.clientY - r.top)*scaleY }; }; const start = (e) => { e.preventDefault(); const p = pos(e); let best = null, bestD = 999; points.forEach((pt,i) => { const d = Math.hypot(pt.x-p.x, pt.y-p.y); if (d < 20 && d < bestD) { bestD=d; best=i; } }); drag = best; }; const move = (e) => { e.preventDefault(); if (drag===null) return; const p = pos(e); points[drag].x = Math.max(16, Math.min(canvas.width-16, p.x)); points[drag].y = Math.max(16, Math.min(canvas.height-16, p.y)); onUpdate(); }; const end = () => { drag=null; }; canvas.addEventListener('mousedown', start); canvas.addEventListener('mousemove', move); canvas.addEventListener('mouseup', end); canvas.addEventListener('touchstart', start, {passive:false}); canvas.addEventListener('touchmove', move, {passive:false}); canvas.addEventListener('touchend', end); } /* ============================================================ WIDGET 1 — INTRO (vecteur AB déplaçable) ============================================================ */ (function() { const canvas = document.getElementById('introCanvas'); const ctx = canvas.getContext('2d'); const W = canvas.width, H = canvas.height; const pts = [{x:200,y:200},{x:450,y:120}]; function draw() { ctx.clearRect(0,0,W,H); drawGrid(ctx,W,H,40); // glow effect on vector ctx.save(); ctx.shadowColor = '#5b8fff'; ctx.shadowBlur = 18; drawArrow(ctx, pts[0].x, pts[0].y, pts[1].x, pts[1].y, '#5b8fff', 3, ''); ctx.restore(); drawPoint(ctx, pts[0].x, pts[0].y, '#ff6b6b', 7, 'A', {x:-18,y:-10}); drawPoint(ctx, pts[1].x, pts[1].y, '#4ecdc4', 7, 'B', {x:10,y:-10}); const dx = pts[1].x - pts[0].x, dy = pts[1].y - pts[0].y; const norm = Math.hypot(dx,dy).toFixed(1); const angle = (Math.atan2(dy,dx)*180/Math.PI).toFixed(1); document.getElementById('introCoord').textContent = `(${dx.toFixed(0)} ; ${(-dy).toFixed(0)})`; document.getElementById('introNorm').textContent = norm + ' px'; document.getElementById('introAngle').textContent = angle + '°'; } makeDraggable(canvas, pts, draw); draw(); })(); /* ============================================================ WIDGET 2 — VECTEURS EGAUX ============================================================ */ (function() { const canvas = document.getElementById('equalCanvas'); const ctx = canvas.getContext('2d'); const W = canvas.width, H = canvas.height; // A, B déplaçables; offset de C par rapport à A const pts = [{x:180,y:240},{x:340,y:160}]; const offset = {x:100, y:80}; function draw() { ctx.clearRect(0,0,W,H); drawGrid(ctx,W,H,40); const A=pts[0], B=pts[1]; const C={x:A.x+offset.x, y:A.y+offset.y}; const D={x:B.x+offset.x, y:B.y+offset.y}; // parallélogramme fill ctx.save(); ctx.beginPath(); ctx.moveTo(A.x,A.y); ctx.lineTo(B.x,B.y); ctx.lineTo(D.x,D.y); ctx.lineTo(C.x,C.y); ctx.closePath(); ctx.fillStyle = 'rgba(91,143,255,.07)'; ctx.fill(); ctx.strokeStyle = 'rgba(91,143,255,.25)'; ctx.setLineDash([5,5]); ctx.lineWidth = 1.2; ctx.stroke(); ctx.restore(); ctx.save(); ctx.shadowColor='#5b8fff'; ctx.shadowBlur=14; drawArrow(ctx,A.x,A.y,B.x,B.y,'#5b8fff',3,'AB⃗'); ctx.restore(); ctx.save(); ctx.shadowColor='#4ecdc4'; ctx.shadowBlur=14; drawArrow(ctx,C.x,C.y,D.x,D.y,'#4ecdc4',3,'CD⃗'); ctx.restore(); drawPoint(ctx,A.x,A.y,'#ff6b6b',6,'A',{x:-18,y:-10}); drawPoint(ctx,B.x,B.y,'#ff6b6b',6,'B',{x:10,y:-10}); drawPoint(ctx,C.x,C.y,'#4ecdc4',6,'C',{x:-18,y:12}); drawPoint(ctx,D.x,D.y,'#4ecdc4',6,'D',{x:10,y:12}); const dx=B.x-A.x, dy=B.y-A.y; document.getElementById('eqAB').textContent=`(${dx.toFixed(0)} ; ${(-dy).toFixed(0)})`; document.getElementById('eqCD').textContent=`(${dx.toFixed(0)} ; ${(-dy).toFixed(0)})`; } makeDraggable(canvas, pts, draw); // also allow dragging offset via C let dragOff = false; const r = () => canvas.getBoundingClientRect(); const pos = e => { const rc = r(); const scaleX=canvas.width/rc.width; const scaleY=canvas.height/rc.height; const src = e.touches?e.touches[0]:e; return {x:(src.clientX-rc.left)*scaleX, y:(src.clientY-rc.top)*scaleY}; }; canvas.addEventListener('mousedown', e => { const p=pos(e); const C={x:pts[0].x+offset.x,y:pts[0].y+offset.y}; if (Math.hypot(C.x-p.x,C.y-p.y)<20) dragOff=true; }); canvas.addEventListener('mousemove', e => { if (!dragOff) return; const p=pos(e); offset.x=p.x-pts[0].x; offset.y=p.y-pts[0].y; draw(); }); canvas.addEventListener('mouseup',()=>{dragOff=false;}); draw(); })(); /* ============================================================ WIDGET 3 — CHASLES ============================================================ */ (function() { const canvas = document.getElementById('chaslesCanvas'); const ctx = canvas.getContext('2d'); const W=canvas.width, H=canvas.height; const pts=[{x:130,y:260},{x:340,y:150},{x:540,y:240}]; function draw() { ctx.clearRect(0,0,W,H); drawGrid(ctx,W,H,40); const [A,B,C]=pts; // AC en arrière-plan ctx.save(); ctx.shadowColor='#a29bfe'; ctx.shadowBlur=20; ctx.globalAlpha=.7; drawArrow(ctx,A.x,A.y,C.x,C.y,'#a29bfe',3.5,'AC⃗'); ctx.restore(); // AB ctx.save(); ctx.shadowColor='#5b8fff'; ctx.shadowBlur=16; drawArrow(ctx,A.x,A.y,B.x,B.y,'#5b8fff',3,'AB⃗'); ctx.restore(); // BC ctx.save(); ctx.shadowColor='#4ecdc4'; ctx.shadowBlur=16; drawArrow(ctx,B.x,B.y,C.x,C.y,'#4ecdc4',3,'BC⃗'); ctx.restore(); drawPoint(ctx,A.x,A.y,'#ff6b6b',7,'A',{x:-18,y:-10}); drawPoint(ctx,B.x,B.y,'#5b8fff',7,'B',{x:10,y:-10}); drawPoint(ctx,C.x,C.y,'#4ecdc4',7,'C',{x:10,y:8}); const abx=B.x-A.x, aby=B.y-A.y; const bcx=C.x-B.x, bcy=C.y-B.y; const acx=C.x-A.x, acy=C.y-A.y; const norm=Math.hypot(acx,acy).toFixed(1); document.getElementById('chAB').textContent=`(${abx.toFixed(0)} ; ${(-aby).toFixed(0)})`; document.getElementById('chBC').textContent=`(${bcx.toFixed(0)} ; ${(-bcy).toFixed(0)})`; document.getElementById('chAC').textContent=`(${acx.toFixed(0)} ; ${(-acy).toFixed(0)})`; document.getElementById('chNorm').textContent=norm+' px'; } makeDraggable(canvas,pts,draw); draw(); })(); /* ============================================================ WIDGET 4 — REPERE + COORDONNEES ============================================================ */ (function() { const canvas = document.getElementById('coordCanvas'); const ctx = canvas.getContext('2d'); const W=canvas.width, H=canvas.height; const step=40, ox=Math.round(W/2), oy=Math.round(H/2); const pts=[{x:ox-80,y:oy+40},{x:ox+100,y:oy-80}]; function toPx(mx,my){return{x:ox+mx*step,y:oy-my*step};} function toMath(px,py){return{x:(px-ox)/step,y:-(py-oy)/step};} function draw() { ctx.clearRect(0,0,W,H); drawGrid(ctx,W,H,step,ox,oy); const A=pts[0], B=pts[1]; // dashed horizontal/vertical lines ctx.save(); ctx.setLineDash([4,4]); ctx.strokeStyle='rgba(255,255,255,.18)'; ctx.lineWidth=1; ctx.beginPath(); ctx.moveTo(A.x,A.y); ctx.lineTo(B.x,A.y); ctx.stroke(); ctx.beginPath(); ctx.moveTo(B.x,A.y); ctx.lineTo(B.x,B.y); ctx.stroke(); ctx.restore(); ctx.save(); ctx.shadowColor='#5b8fff'; ctx.shadowBlur=18; drawArrow(ctx,A.x,A.y,B.x,B.y,'#5b8fff',3,'AB⃗'); ctx.restore(); drawPoint(ctx,A.x,A.y,'#ff6b6b',7,'A',{x:-18,y:-10}); drawPoint(ctx,B.x,B.y,'#4ecdc4',7,'B',{x:10,y:-10}); const ma=toMath(A.x,A.y), mb=toMath(B.x,B.y); const dx=mb.x-ma.x, dy=mb.y-ma.y; document.getElementById('coordA').textContent=`(${ma.x.toFixed(1)} ; ${ma.y.toFixed(1)})`; document.getElementById('coordB').textContent=`(${mb.x.toFixed(1)} ; ${mb.y.toFixed(1)})`; document.getElementById('coordDx').textContent=dx.toFixed(2); document.getElementById('coordDy').textContent=dy.toFixed(2); document.getElementById('coordVec').textContent=`(${dx.toFixed(2)} ; ${dy.toFixed(2)})`; } makeDraggable(canvas,pts,draw); draw(); })(); /* ============================================================ CALCULATRICE DE NORME ============================================================ */ function calcNorme() { const xa=+document.getElementById('nxA').value; const ya=+document.getElementById('nyA').value; const xb=+document.getElementById('nxB').value; const yb=+document.getElementById('nyB').value; const dx=xb-xa, dy=yb-ya; const norm=Math.sqrt(dx*dx+dy*dy); const el=document.getElementById('normeResult'); el.style.display='block'; el.innerHTML=` <strong style="color:var(--accent1)">Calcul détaillé :</strong><br> \\[\\overrightarrow{AB} = \\begin{pmatrix} ${xb}-${xa} \\\\ ${yb}-${ya} \\end{pmatrix} = \\begin{pmatrix} ${dx} \\\\ ${dy} \\end{pmatrix}\\] \\[|\\overrightarrow{AB}| = \\sqrt{(${dx})^2 + (${dy})^2} = \\sqrt{${dx*dx}+${dy*dy}} = \\sqrt{${dx*dx+dy*dy}} \\approx \\color{#ffd166}{${norm.toFixed(3)}}\\] `; MathJax.typesetPromise([el]); } /* ============================================================ EXERCICES — VÉRIFICATIONS ============================================================ */ function checkEx1() { const v=+document.getElementById('ex1').value; const fb=document.getElementById('fb1'); if(v===4){fb.className='feedback correct';fb.textContent='✓ Bravo ! x_B - x_A = 7 - 3 = 4';} else{fb.className='feedback wrong';fb.textContent='✗ Réessaie… Calcule 7 - 3.';} } function checkEx2() { const v=+document.getElementById('ex2').value; const fb=document.getElementById('fb2'); if(v===5){fb.className='feedback correct';fb.textContent='✓ Parfait ! √(3² + 4²) = √25 = 5';} else{fb.className='feedback wrong';fb.textContent='✗ Calcule √(3² + 4²). Pense au théorème de Pythagore !';} } function checkEx3(ans) { const fb=document.getElementById('fb3'); if(ans==='AC'){fb.className='feedback correct';fb.textContent='✓ Excellent ! C\'est bien AC⃗ — c\'est la relation de Chasles !';} else{fb.className='feedback wrong';fb.textContent='✗ Relis la relation de Chasles : AB⃗ + BC⃗ = AC⃗';} } function checkEx4(ans) { const fb=document.getElementById('fb4'); if(!ans){fb.className='feedback correct';fb.textContent='✓ Correct ! AB⃗ et BA⃗ ont des sens opposés, donc ils ne sont pas égaux (sauf si nul).';} else{fb.className='feedback wrong';fb.textContent='✗ Non ! AB⃗ va de A vers B, BA⃗ va de B vers A — sens opposés !';} } function checkEx5(ans) { const fb=document.getElementById('fb5'); if(ans==='AB'){fb.className='feedback correct';fb.textContent='✓ Bravo ! AC⃗ - BC⃗ = AC⃗ + CB⃗ = AB⃗ (Chasles)';} else{fb.className='feedback wrong';fb.textContent='✗ Rappel : soustraire BC⃗ = ajouter CB⃗, puis AC⃗ + CB⃗ = AB⃗';} } /* ============================================================ MODE PROFESSEUR ============================================================ */ (function() { const canvas=document.getElementById('profCanvas'); const ctx=canvas.getContext('2d'); const W=canvas.width, H=canvas.height; let tool='draw', color='#5b8fff', size=3; let drawing=false, startX=0, startY=0; let history=[], snapshot=null; // init background function initBg() { ctx.fillStyle='#0f1220'; ctx.fillRect(0,0,W,H); drawGrid(ctx,W,H,40,W/2,H/2); } initBg(); window.setProfTool = function(t) { tool=t; document.querySelectorAll('.tool-btn').forEach(b=>b.classList.remove('active')); document.getElementById('tool'+t.charAt(0).toUpperCase()+t.slice(1))?.classList.add('active'); }; window.setProfColor = function(c, el) { color=c; document.querySelectorAll('.color-dot').forEach(d=>d.classList.remove('active')); el.classList.add('active'); }; document.getElementById('profSize').addEventListener('input', e => { size=+e.target.value; }); function saveHistory() { history.push(canvas.toDataURL()); if(history.length>40) history.shift(); } window.undoProf = function() { if(!history.length) return; const img=new Image(); img.src=history.pop(); img.onload=()=>ctx.drawImage(img,0,0); }; window.clearProf = function() { saveHistory(); ctx.clearRect(0,0,W,H); initBg(); }; const rc=()=>canvas.getBoundingClientRect(); const pos=e=>{ const r=rc(); const scaleX=canvas.width/r.width; const scaleY=canvas.height/r.height; const src=e.touches?e.touches[0]:e; return {x:(src.clientX-r.left)*scaleX,y:(src.clientY-r.top)*scaleY}; }; canvas.addEventListener('mousedown', e=>{ drawing=true; const p=pos(e); startX=p.x; startY=p.y; saveHistory(); if(tool==='point'){ drawPoint(ctx,p.x,p.y,color,6,'',''); // label dialog const lbl=prompt('Nom du point (optionnel):','P'); if(lbl) { ctx.font=`bold 14px Syne,sans-serif`; ctx.fillStyle=color; ctx.fillText(lbl,p.x+10,p.y-10); } drawing=false; } if(tool==='text'){ const txt=prompt('Texte à ajouter:',''); if(txt){ ctx.font=`${size*4+10}px DM Sans,sans-serif`; ctx.fillStyle=color; ctx.fillText(txt,p.x,p.y); } drawing=false; } if(tool==='draw') { snapshot=ctx.getImageData(0,0,W,H); ctx.beginPath(); ctx.moveTo(p.x,p.y); } if(tool==='vector') snapshot=ctx.getImageData(0,0,W,H); }); canvas.addEventListener('mousemove', e=>{ if(!drawing) return; const p=pos(e); if(tool==='draw') { ctx.strokeStyle=color; ctx.lineWidth=size; ctx.lineCap='round'; ctx.lineJoin='round'; ctx.lineTo(p.x,p.y); ctx.stroke(); ctx.beginPath(); ctx.moveTo(p.x,p.y); } if(tool==='vector' && snapshot) { ctx.putImageData(snapshot,0,0); drawArrow(ctx,startX,startY,p.x,p.y,color,size+1); } }); canvas.addEventListener('mouseup', e=>{ if(!drawing) return; drawing=false; const p=pos(e); if(tool==='vector') drawArrow(ctx,startX,startY,p.x,p.y,color,size+1); snapshot=null; }); canvas.addEventListener('touchstart',e=>{e.preventDefault();canvas.dispatchEvent(new MouseEvent('mousedown',{clientX:e.touches[0].clientX,clientY:e.touches[0].clientY}));},{passive:false}); canvas.addEventListener('touchmove',e=>{e.preventDefault();canvas.dispatchEvent(new MouseEvent('mousemove',{clientX:e.touches[0].clientX,clientY:e.touches[0].clientY}));},{passive:false}); canvas.addEventListener('touchend',e=>{canvas.dispatchEvent(new MouseEvent('mouseup',{}));}); })(); /* ============================================================ SCROLL ANIMATIONS + PROGRESS BAR ============================================================ */ const sections = document.querySelectorAll('.section'); const obs = new IntersectionObserver(entries => { entries.forEach(e=>{ if(e.isIntersecting) e.target.classList.add('visible'); }); },{threshold:0.08}); sections.forEach(s=>obs.observe(s)); window.addEventListener('scroll',()=>{ const scrollTop=window.scrollY||document.documentElement.scrollTop; const docH=document.documentElement.scrollHeight-window.innerHeight; document.getElementById('progress-bar').style.width=(scrollTop/docH*100)+'%'; }); </script> </body> </html>
Landing Page
This ad does not have a landing page available
Network Timeline
Performance Summary

17

Requests

6

Domains

3053KB

Transfer Size

9078KB

Content Size

1,598.0ms

Dom Content Loaded

200.0ms

First Paint

3,192.0ms

Load Time
Domain Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...
Timings (ms)
Loading...
Total Time
Loading...
Content Breakdown
Transfer Size (bytes)
Loading...
Content Size (bytes)
Loading...
Header Size (bytes)
Loading...
Requests
Loading...