df8b5ff18b
Корневая причина: каждый redraw() заменял SVG через innerHTML,
уничтожая элемент svgEl который onMove захватил в замыкании через
const svgEl = wrap.querySelector('svg'). На следующем pointermove
svgEl.getBoundingClientRect() возвращал {left:0,top:0,w:0,h:0} —
вершина прыгала в начало координат SVG, drag разваливался.
Применено к 5 интерактивам:
1. §4 Конструктор параллелограмма
2. §5 Живой параллелограмм — все свойства
3. §7 Живой прямоугольник — равенство диагоналей
4. §8 Признак прямоугольника — живая демонстрация
5. §9 Живой ромб
Что изменилось:
- Состояние (p4Active, p4Vname, p4OffX/Y и т.д.) вынесено на уровень
модуля, ВНЕ redraw().
- Один pointerdown-listener на wrapper-div через делегирование событий
(ev.target.closest('[data-v]')).
- clientToSvg() делает свежий document.getElementById(SVG_ID) на
каждый вызов — не закрепляется на устаревшем DOM-узле.
- SVG получают стабильный id.
- viewBox.baseVal для точного coordinate scaling.
- Offset capture на pointerdown (нет snap-to-pointer).
- touch-action:none на SVG root.
- Hit area r=16 (visible r=8) — легче попасть на touch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>