{"id":28317337,"url":"https://github.com/ivanvit100/physjs","last_synced_at":"2025-06-24T14:32:09.415Z","repository":{"id":294167653,"uuid":"953626998","full_name":"ivanvit100/PhysJS","owner":"ivanvit100","description":"Библиотека для создания интерактивных лабораторных работ и физических симуляций в веб-браузере","archived":false,"fork":false,"pushed_at":"2025-06-12T21:06:47.000Z","size":12557,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-12T22:24:39.347Z","etag":null,"topics":["experiments","javascript","laboratory","physics","physics-simulation"],"latest_commit_sha":null,"homepage":"https://vps.ivanvit.ru/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivanvit100.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-23T19:33:08.000Z","updated_at":"2025-06-12T21:06:51.000Z","dependencies_parsed_at":"2025-06-04T18:07:01.828Z","dependency_job_id":null,"html_url":"https://github.com/ivanvit100/PhysJS","commit_stats":null,"previous_names":["ivanvit100/physjs"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ivanvit100/PhysJS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanvit100%2FPhysJS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanvit100%2FPhysJS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanvit100%2FPhysJS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanvit100%2FPhysJS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivanvit100","download_url":"https://codeload.github.com/ivanvit100/PhysJS/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivanvit100%2FPhysJS/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261694253,"owners_count":23195545,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["experiments","javascript","laboratory","physics","physics-simulation"],"created_at":"2025-05-25T04:20:40.362Z","updated_at":"2025-06-24T14:32:09.405Z","avatar_url":"https://github.com/ivanvit100.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Документация библиотеки PhysJS\n### Содержание\n1. Введение\n2. Начало работы\n3. Основные концепции\n4. API библиотеки\n    - Инициализация и настройка\n    - Управление объектами\n    - Управление точками крепления\n    - Управление шагами лабораторной работы\n    - Обработка событий\n    - Специальные эффекты\n    - Управление вращением объектов\n    - Расширенные обработчики событий\n    - Работа с проводами и соединениями\n    - Баллистические траектории\n5. Классы HTML-элементов\n6. Примеры использования\n7. Советы по производительности  \n8. Устранение неполадок\n\n## Введение\nPhysJS — это JavaScript библиотека для создания интерактивных лабораторных работ и физических симуляций в веб-браузере. Библиотека позволяет создавать перетаскиваемые объекты, определять точки крепления между ними, и организовывать последовательность шагов для выполнения лабораторной работы.\n\nС примерами использования библиотеки можно ознакомиться [здесь](/demo_app/). В данном каталоге представлена примерная реализация физической лаборатории, содержащей 18 экспериментов из физического практикума для учащихся 10-11 классов. Приложение реализовано с использованием Flask и JavaScript без сторонних библиотек.\n\n### Основные возможности библиотеки\n- Создание перетаскиваемых физических объектов\n- Определение точек крепления между объектами\n- Создание проводов и точек крепления для них\n- Организация последовательности шагов лабораторной работы\n- Отслеживание событий взаимодействия с объектами\n- Создание специальных визуальных эффектов\n\n## Начало работы\n\nПодключение библиотеки\n```html\n\u003clink rel=\"stylesheet\" href=\"phys.css\"\u003e\n\u003cscript src=\"phys.js\"\u003e\u003c/script\u003e\n```\nМинимальный HTML-шаблон\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n    \u003ctitle\u003ePhysJS Лабораторная работа\u003c/title\u003e\n    \u003clink rel=\"stylesheet\" href=\"phys.css\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    \u003cdiv id=\"experiment-area\"\u003e\n        \u003c!-- Здесь будут размещены физические объекты --\u003e\n        \u003cdiv id=\"object1\" class=\"phys phys-attachable\" style=\"left: 50px; top: 50px; width: 100px; height: 100px; background-color: red;\" data-type=\"object1\"\u003e\u003c/div\u003e\n        \u003cdiv id=\"object2\" class=\"phys phys-attachable\" style=\"left: 200px; top: 50px; width: 100px; height: 100px; background-color: blue;\" data-type=\"object2\"\u003e\u003c/div\u003e\n    \u003c/div\u003e\n\n    \u003cscript src=\"phys.js\"\u003e\u003c/script\u003e\n    \u003cscript\u003e\n        // Включение режима отладки для вывода логов\n        physjs.setDebugMode(true);\n        \n        // Добавление точек крепления\n        physjs.addAttachmentPoint('#object1', 'right', 100, 50, ['object2']);\n        physjs.addAttachmentPoint('#object2', 'left', 0, 50, ['object1']);\n        \n        // Создание шагов лабораторной работы\n        const step1 = physjs.createStep('step1', 'Соедините объекты', ['#object1', '#object2']);\n        physjs.addStep(step1);\n        physjs.goToStep('step1');\n    \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### Основные концепции\n\n#### Физические объекты\nФизические объекты — это DOM-элементы, которые могут быть перетаскиваемыми и взаимодействовать друг с другом. Для создания физического объекта необходимо добавить класс `phys` к HTML-элементу:\n```html\n\u003cdiv id=\"my-object\" class=\"phys\" data-type=\"object\"\u003e\u003c/div\u003e\n```\nОбъекты, которые могут быть прикреплены к другим объектам, должны иметь дополнительный класс `phys-attachable`:\n```html\n\u003cdiv id=\"my-attachable-object\" class=\"phys phys-attachable\" data-type=\"attachable-object\"\u003e\u003c/div\u003e\n```\n\n#### Точки крепления\nТочки крепления определяют, как объекты могут присоединяться друг к другу. Каждая точка крепления имеет:\n\n- Идентификатор\n- Координаты относительно родительского объекта (x, y)\n- Список типов объектов, которые могут быть прикреплены к этой точке\n\n#### Шаги лабораторной работы\nШаги лабораторной работы определяют последовательность действий, которые должен выполнить пользователь. Каждый шаг имеет:\n\n- Идентификатор\n- Описание\n- Список разрешенных объектов для прикрепления\n- Список разрешенных объектов для открепления\n\n## API библиотеки\n### Инициализация и настройка\n1. `physjs.init(options)`\n\nИнициализирует библиотеку с настройками.\n\nПараметры:\n- `debug (boolean)` - включает/выключает режим отладки\n\nПример:\n```js\nphysjs.init({ debug: true });\n```\n\n2. `physjs.setDebugMode(enabled)`\n\nВключает или выключает режим отладки.\n\nПараметры:\n- enabled (boolean) - true для включения, false для выключения\n\nПример:\n```js\nphysjs.setDebugMode(true); // Включить режим отладки\nphysjs.setDebugMode(false); // Выключить режим отладки\n```\n\n### Управление объектами\n3. `physjs.getObject(element)`\n\nВозвращает физический объект по DOM-элементу или селектору.\n\nПараметры:\n- element (DOM-элемент или строка) - DOM-элемент или CSS-селектор\n\nВозвращает: объект PhysObject или null, если объект не найден\n\nПример:\n```js\nconst obj = physjs.getObject('#my-object');\nconst pos = obj.getPosition();\nconsole.log(`Позиция объекта: x=${pos.x}, y=${pos.y}`);\n```\n\n4. `physjs.createObject(element)`\n\nСоздает новый физический объект из DOM-элемента.\n\nПараметры:\n- element (DOM-элемент или строка) - DOM-элемент или CSS-селектор\n\nВозвращает: созданный объект PhysObject или null в случае ошибки\n\nПример:\n```js \nconst newObj = physjs.createObject('#new-element');\n```\n\n5. `physjs.detachAll()`\n\nОткрепляет все прикрепленные объекты.\n\nПример:\n```js\nphysjs.detachAll();\n```\n\n6. `physjs.resetRotations()`\n\nСбрасывает поворот всех объектов к нулевому значению.\n\nПример:\n```js\nphysjs.resetRotations();\n```\n\n### Управление точками крепления\n7. `physjs.addAttachmentPoint(element, pointId, x, y, acceptedTypes)`\n\nДобавляет точку крепления к физическому объекту.\n\nПараметры:\n- element (DOM-элемент или строка) - DOM-элемент или CSS-селектор\n- pointId (строка) - идентификатор точки крепления\n- x (число) - координата X относительно родительского объекта\n- y (число) - координата Y относительно родительского объекта\n- acceptedTypes (массив строк) - список типов объектов, которые могут быть прикреплены\n\nПример:\n```js\n// Добавляем точку крепления 'top' к объекту #cylinder\n// в координатах (50, 0) относительно объекта\n// и разрешаем прикрепление только объектов с типом 'tube'\nphysjs.addAttachmentPoint('#cylinder', 'top', 50, 0, ['tube']);\n```\n\n### Управление шагами лабораторной работы\n8. `physjs.createStep(id, description, allowedAttachments, allowedDetachments)`\n\nСоздает новый шаг лабораторной работы.\n\nПараметры:\n- id (строка) - уникальный идентификатор шага\n- description (строка) - описание шага\n- allowedAttachments (массив строк) - CSS-селекторы объектов, которые можно прикреплять\n- allowedDetachments (массив строк) - CSS-селекторы объектов, которые можно откреплять\n\nВозвращает: объект LabStep\n\nПример:\n```js\n// Создаем шаг с идентификатором 'step1' и описанием\n// Разрешаем прикреплять объекты '#tube' и '#flask'\n// и откреплять объект '#tube'\nconst step1 = physjs.createStep('step1', 'Соедините трубку с колбой', ['#tube', '#flask'], ['#tube']);\n```\n\n9. `physjs.addStep(step)`\n\nДобавляет шаг в последовательность лабораторной работы.\n\nПараметры:\n- step (объект LabStep) - шаг, созданный с помощью createStep\n\nПример:\n```js\nphysjs.addStep(step1);\nphysjs.addStep(step2);\nphysjs.addStep(step3);\n```\n\n10. `physjs.nextStep()`\n\nПереходит к следующему шагу лабораторной работы.\n\nВозвращает: следующий шаг или null, если это последний шаг\n\nПример:\n```js\nconst nextStep = physjs.nextStep();\nif (nextStep) {\n    console.log(`Переход к шагу: ${nextStep.description}`);\n}\n```\n\n11. `physjs.previousStep()`\n\nПереходит к предыдущему шагу лабораторной работы.\n\nВозвращает: предыдущий шаг или null, если это первый шаг\n\nПример:\n```js\nconst prevStep = physjs.previousStep();\nif (prevStep) {\n    console.log(`Возврат к шагу: ${prevStep.description}`);\n}\n```\n\n12. `physjs.getCurrentStep()`\n\nВозвращает текущий шаг лабораторной работы.\n\nВозвращает: текущий шаг или null, если ни один шаг не активен\n\nПример:\n```js\nconst currentStep = physjs.getCurrentStep();\nconsole.log(`Текущий шаг: ${currentStep.description}`);\n```\n\n13. `physjs.goToStep(id)`\n\nПереходит к шагу с указанным идентификатором.\n\nПараметры:\n- id (строка) - идентификатор шага\n\nВозвращает: найденный шаг или null, если шаг не найден\n\nПример:\n```js\nphysjs.goToStep('step3'); // Переход к шагу с id='step3'\n```\n\n14. `physjs.resetLab()`\n\nСбрасывает лабораторную работу к начальному состоянию.\n\nПример:\n```js\nphysjs.resetLab();\n```\n\n### Обработка событий\n15. `physjs.onAttachment(callback)`\n\nРегистрирует обработчик события прикрепления объектов.\n\nПараметры:\n- callback (функция) - функция обратного вызова, принимающая sourceObject и targetObject\n\nПример:\n```js\nphysjs.onAttachment(function(sourceObject, targetObject) {\n    console.log(`Объект ${sourceObject.element.id} был прикреплен к ${targetObject.element.id}`);\n});\n```\n\n16. `physjs.onDetachment(callback)`\n\nРегистрирует обработчик события открепления объекта.\n\nПараметры:\n- callback (функция) - функция обратного вызова, принимающая объект\n\nПример:\n```js\nphysjs.onDetachment(function(object) {\n    console.log(`Объект ${object.element.id} был откреплен`);\n});\n```\n\n17. `physjs.onStepChange(callback)`\n\nРегистрирует обработчик события изменения шага лабораторной работы.\n\nПараметры:\n- callback (функция) - функция обратного вызова, принимающая новый шаг\n\nПример:\n```js\nphysjs.onStepChange(function(step) {\n    console.log(`Новый шаг: ${step.description}`);\n    document.getElementById('current-step').textContent = step.description;\n});\n```\n\n18. `physjs.onLabComplete(callback)`\n\nРегистрирует обработчик завершения лабораторной работы.\n\nПараметры:\n- callback (функция) - функция обратного вызова\n\nПример:\n```js\nphysjs.onLabComplete(function() {\n    console.log('Лабораторная работа завершена!');\n});\n```\n\n### Специальные эффекты\n19. `physjs.showTemporaryObjectAt(objectToHide, referenceObject, selectorToShow, offsetX, offsetY, durationMs)`\n\nВременно скрывает один объект и показывает другой в указанной позиции. \nФункция может быть полезна для создания анимаций для групп объектов, когда взаимодействие с изначальной группой объектов пользователем нежелательно. Например, анимация переливания воды из сосудов по шлангам и тд.\n\nПараметры:\n- objectToHide (DOM-элемент или строка) - объект, который нужно скрыть\n- referenceObject (DOM-элемент или строка) - объект, относительно которого позиционировать\n- selectorToShow (строка) - CSS-селектор объекта, который нужно показать\n- offsetX (число) - смещение по оси X относительно referenceObject\n- offsetY (число) - смещение по оси Y относительно referenceObject\n- durationMs (число) - продолжительность в миллисекундах\n\nПример:\n```js\n// Скрывает #flask, показывает #animation-overlay на 2 секунды\n// в позиции на 10px правее и 20px ниже #beaker\nphysjs.showTemporaryObjectAt('#flask', '#beaker', '#animation-overlay', 10, 20, 2000);\n```\n\n20. `physjs.swapObjectsWithElement(object1, object2, selectorToShow)`\n\nСкрывает два объекта и показывает вместо них третий объект. Позволяет \"соединять объекты\", подменяя два постоянно связанных объекта на один цельный.\n\nПараметры:\n- object1 (DOM-элемент или строка) - первый объект, который нужно скрыть\n- object2 (DOM-элемент или строка) - второй объект, который нужно скрыть\n- selectorToShow (строка) - CSS-селектор объекта, который нужно показать\nПример:\n```js\n// Скрывает #water и #salt, показывает #solution\nphysjs.swapObjectsWithElement('#water', '#salt', '#solution');\n```\n\n### Управление вращением объектов\n\n21. `physjs.disableRotation()`\n\nОтключает возможность вращения для всех объектов.\n\nПример:\n```js\nphysjs.disableRotation();\n```\n\n22. `physjs.enableRotation()`\n\nВключает возможность вращения для всех объектов.\n\nПример:\n```js\nphysjs.enableRotation();\n```\n\n23.`physjs.disableRotationFor(elements)`\n\nОтключает возможность вращения для указанных объектов.\n\nПараметры:\n- elements (массив или строка) - объекты или селекторы объектов\nПример:\n```js\nphysjs.disableRotationFor(['#tube', '#flask']);\n```\n\n24. `physjs.enableRotationFor(elements)`\n\nВключает возможность вращения для указанных объектов.\n\nПараметры:\n- elements (массив или строка) - объекты или селекторы объектов\nПример:\n```js\nphysjs.enableRotationFor('#microscope');\n```\n\n25. `physjs.setRotationKeysEnabled(enabled)`\n\nВключает или отключает использование клавиш Q/E для вращения объектов.\n\nПараметры:\n- enabled (boolean) - true для включения, false для отключения\nПример:\n```js\nphysjs.setRotationKeysEnabled(false); // Отключение вращения клавишами\n```\n\n### Расширенные обработчики событий\n26. `physjs.onBeforeAttachment(callback)`\n\nРегистрирует обработчик события перед прикреплением объектов. Позволяет предотвратить прикрепление, вернув false.\n\nПараметры:\n- callback (функция) - функция, принимающая sourceObject и targetObject\nПример:\n```js\nphysjs.onBeforeAttachment(function(sourceObject, targetObject) {\n    // Проверка условий прикрепления\n    if (someCondition) return false; // Предотвращает прикрепление\n    return true; // Разрешает прикрепление\n});\n```\n\n27. `physjs.onBeforeDetachment(callback)`\n\nРегистрирует обработчик события перед откреплением объекта. Позволяет предотвратить открепление, вернув false.\n\nПараметры:\n- callback (функция) - функция, принимающая объект\nПример:\n```js\nphysjs.onBeforeDetachment(function(object) {\n    // Проверка условий открепления\n    if (someCondition) return false; // Предотвращает открепление\n    return true; // Разрешает открепление\n});\n```\n\n28. `physjs.isAttached(element1, element2)`\n\nПроверяет, прикреплены ли два объекта друг к другу.\n\nПараметры:\n- element1 (DOM-элемент или строка) - первый объект\n- element2 (DOM-элемент или строка) - второй объект\nВозвращает: true, если объекты прикреплены друг к другу, иначе false\n\nПример:\n```js\nif (physjs.isAttached('#tube', '#flask')) {\n    console.log('Трубка прикреплена к колбе');\n}\n```\n\n### Работа с проводами и соединениями\n29. `physjs.addConnectionPoint(elementSelector, pointId, x, y)`\n\nДобавляет точку подключения проводов к объекту.\n\nПараметры:\n- elementSelector (строка) - CSS-селектор объекта\n- pointId (строка) - идентификатор точки подключения\n- x (число) - координата X в процентах от ширины элемента (0-100)\n- y (число) - координата Y в процентах от высоты элемента (0-100)\nПример:\n```js\n// Добавляет точку подключения на 80% ширины и 20% высоты элемента\nphysjs.addConnectionPoint('#power-source', 'power-positive', 80, 20);\n```\n\n30. `physjs.onConnect(callback)`\n\nРегистрирует обработчик события подключения проводов.\n\nПараметры:\n- callback (функция) - функция обратного вызова, принимающая fromId и toId\nПример:\n```js\nphysjs.onConnect(function(fromPointId, toPointId) {\n    console.log(`Соединение создано от ${fromPointId} к ${toPointId}`);\n});\n```\n\n31. `physjs.createWire(fromPointId, toPointId, color)`\n\nПрограммно создает провод между двумя точками подключения.\n\nПараметры:\n- fromPointId (строка) - идентификатор начальной точки\n- toPointId (строка) - идентификатор конечной точки\n- color (строка) - цвет провода в формате CSS\nВозвращает: ID созданного провода или null, если соединение не удалось\n\nПример:\n```js\nconst wireId = physjs.createWire('power-positive', 'ammeter-input', '#FF0000');\n```\n\n32. `physjs.removeWire(wireId)`\n\nУдаляет провод по его идентификатору.\n\nПараметры:\n- wireId (строка) - идентификатор провода\nПример:\n```js\nphysjs.removeWire('wire-1');\n```\n\n33. `physjs.removeAllWires()`\n\nУдаляет все провода.\n\nПример:\n```js\nphysjs.removeAllWires();\n```\n\n### Баллистические траектории\n34. `physjs.calculateTrajectory(v0, alpha, h, g)`\n\nРассчитывает траекторию полета тела, брошенного с начальной скоростью под углом.\n\nПараметры:\n- v0 (число) - начальная скорость\n- alpha (число) - угол в радианах\n- h (число) - начальная высота\n- g (число) - ускорение свободного падения\nВозвращает: объект с параметрами траектории (дальность, время полета, максимальная высота)\n\nПример:\n```js\nconst trajectory = physjs.calculateTrajectory(10, Math.PI/4, 0, 9.8);\nconsole.log(`Дальность полета: ${trajectory.range} м`);\n```\n\n35. `physjs.showTrajectory(startX, startY, vx, vy, g, floorArea, id, container_id)`\n\nphysjs.showTrajectory(startX, startY, vx, vy, g, floorArea, id, container_id)\nОтображает траекторию движения на экране.\n\nПараметры:\n- startX, startY (числа) - начальные координаты\n- vx, vy (числа) - компоненты скорости\n- g (число) - ускорение свободного падения\n- floorArea (DOM-элемент) - элемент, представляющий \"пол\"\n- id (строка) - идентификатор для созданного элемента траектории\n- container_id (строка) - идентификатор контейнера для размещения траектории\nПример:\n```js\nphysjs.showTrajectory(100, 100, 5, -10, 9.8, document.getElementById('floor'), 'trajectory-1', 'experiment-area');\n```\n\n## HTML и CSS\n### Классы\nБиблиотека PhysJS использует специальные CSS-классы для определения поведения элементов:\n\n| Класс | Описание |\n|-------|----------|\n| `phys` | Базовый класс для всех физических объектов. Делает объект перетаскиваемым |\n| `phys-attachable` | Позволяет объекту прикрепляться к другим объектам |\n| `phys-fixed` | Создает неподвижный объект, который нельзя перетащить |\n| `phys-connectors` | Объект может иметь точки подключения для проводов |\n\nПример использования классов:\n```html\n\u003c!-- Обычный перетаскиваемый объект --\u003e\n\u003cdiv id=\"beaker\" class=\"phys\" data-type=\"beaker\"\u003e\u003c/div\u003e\n\n\u003c!-- Объект, который можно прикрепить к другим объектам --\u003e\n\u003cdiv id=\"tube\" class=\"phys phys-attachable\" data-type=\"tube\"\u003e\u003c/div\u003e\n\n\u003c!-- Неподвижный объект (например, стол или штатив) --\u003e\n\u003cdiv id=\"stand\" class=\"phys phys-fixed\" data-type=\"stand\"\u003e\u003c/div\u003e\n\n\u003c!-- Электрический компонент с точками подключения --\u003e\n\u003cdiv id=\"battery\" class=\"phys phys-connectors\" data-type=\"battery\"\u003e\u003c/div\u003e\n```\n\n### Атрибут data-type\nАтрибут data-type используется для определения типа объекта, который проверяется при работе с точками крепления и в обработчиках событий:\n```html\n\u003cdiv id=\"resistor\" class=\"phys phys-connectors\" data-type=\"resistor\"\u003e\u003c/div\u003e\n```\nЭтот атрибут используется при настройке точек крепления для определения, какие типы объектов могут быть прикреплены:\n```js\nphysjs.addAttachmentPoint('#stand', 'top', 50, 0, ['tube', 'flask']);\n```\n\n## Примеры использования\n### Создание лабораторной работы\n```js\n// Создание шагов\nconst step1 = physjs.createStep('step1', 'Соедините трубку с колбой', ['#tube', '#flask']);\nconst step2 = physjs.createStep('step2', 'Нагрейте колбу горелкой', ['#burner', '#flask']);\nconst step3 = physjs.createStep('step3', 'Перелейте жидкость в пробирку', ['#flask', '#test-tube'], ['#flask']);\n\n// Добавление шагов\nphysjs.addStep(step1).addStep(step2).addStep(step3);\n\n// Начало лабораторной работы\nphysjs.goToStep('step1');\n\n// Обработка изменения шага\nphysjs.onStepChange(function(step) {\n    document.getElementById('current-step').textContent = step.description;\n});\n\n// Обработка завершения лабораторной работы\nphysjs.onLabComplete(function() {\n    alert('Поздравляем! Вы успешно выполнили все задания лабораторной работы.');\n});\n```\n\n### Настройка объектов и точек крепления\n```js\n// Добавление точек крепления для соединения трубки и колбы\nphysjs.addAttachmentPoint('#tube', 'bottom', 15, 90, ['flask']); // Нижняя точка трубки\nphysjs.addAttachmentPoint('#flask', 'top', 50, 0, ['tube']); // Верхняя точка колбы\n\n// Добавление точки крепления для горелки\nphysjs.addAttachmentPoint('#burner', 'flame', 25, 0, ['flask']); // Пламя горелки\nphysjs.addAttachmentPoint('#flask', 'bottom', 50, 100, ['burner']); // Нижняя точка колбы\n\n// Добавление точки крепления для пробирки\nphysjs.addAttachmentPoint('#flask', 'outlet', 90, 60, ['test-tube']); // Выходной патрубок колбы\nphysjs.addAttachmentPoint('#test-tube', 'inlet', 20, 10, ['flask']); // Входное отверстие пробирки\n```\n\n## Советы по производительности\n1. **Ограничьте количество физических объектов**\n   - Старайтесь не превышать 30-50 объектов на одной странице для оптимальной производительности\n   - При необходимости используйте технику \"пулинга\" объектов, показывая только нужные в данный момент\n\n2. **Используйте класс `phys-fixed` для неподвижных объектов**\n   - Это уменьшит количество вычислений при перетаскивании и взаимодействии\n\n3. **Группируйте сложные объекты**\n   - Для сложных объектов используйте один контейнер с классом `phys` и вложенные элементы без этого класса\n   - Используйте `physjs.swapObjectsWithElement()` для объединения часто соединяемых объектов\n\n4. **Оптимизируйте работу с проводами**\n   - Старайтесь не превышать 15-20 проводов на одной схеме\n   - Используйте `physjs.updateWirePositions()` только при необходимости\n\n## Устранение неполадок\n### Проблема: Объекты не прикрепляются друг к другу\nРешение:\n1. Убедитесь, что оба объекта имеют класс phys-attachable\n2. Проверьте правильность настройки точек крепления\n3. Проверьте, разрешено ли прикрепление этих объектов на текущем шаге\n4. Включите режим отладки для получения подробных логов: physjs.setDebugMode(true)\n\n### Проблема: Объект не перетаскивается\nРешение:\n1. Убедитесь, что объект имеет класс phys\n2. Проверьте, не является ли объект прикрепленным к родительскому объекту\n3. Убедитесь, что для объекта установлено position: absolute\n\n### Проблема: Лабораторная работа не переходит к следующему шагу\nРешение:\n1. Проверьте, правильно ли созданы и добавлены шаги\n2. Убедитесь, что вызывается метод physjs.nextStep()\n3. Проверьте консоль на наличие ошибок\n4. Включите режим отладки для получения подробных логов: physjs.setDebugMode(true)\n\n--- \n\nДокументация составлена для библиотеки PhysJS версии 1.2.4. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivanvit100%2Fphysjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivanvit100%2Fphysjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivanvit100%2Fphysjs/lists"}