Cannon.js и Cannon-es: выбор версии

Основы Cannon.js

Cannon.js — это легковесная физическая библиотека на JavaScript для работы с динамическими объектами в 3D-пространстве. Она позволяет моделировать твердые тела, столкновения, гравитацию и контакты между объектами с минимальной нагрузкой на браузер. Основные компоненты библиотеки включают:

  • World — пространство, в котором происходят физические расчёты.
  • Body — физическое тело с массой, положением, ориентацией и инерцией.
  • Shape — геометрическая форма объекта (Box, Sphere, Plane, Cylinder и ConvexPolyhedron).
  • Material и ContactMaterial — материалы для настройки трения и упругости контактов.

Простейший пример создания физического мира:

import * as CANNON from 'cannon-es';

const world = new CANNON.World();
world.gravity.set(0, -9.82, 0); // Земная гравитация по оси Y

const groundBody = new CANNON.Body({
  mass: 0, // неподвижное тело
  shape: new CANNON.Plane(),
});
groundBody.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
world.addBody(groundBody);

const sphereBody = new CANNON.Body({
  mass: 5,
  shape: new CANNON.Sphere(1),
  position: new CANNON.Vec3(0, 10, 0),
});
world.addBody(sphereBody);

function simulate(deltaTime) {
  world.step(deltaTime);
}

Cannon-es: современная альтернатива

Cannon-es — это форк оригинальной Cannon.js с поддержкой ES-модулей, улучшенной совместимостью с современными сборщиками (Webpack, Vite, Rollup) и активным сопровождением. Отличия и преимущества:

  • Импорт через ES6 синтаксис (import { World, Body, Box } from 'cannon-es').
  • Исправлены некоторые баги оригинальной Cannon.js, например, некорректные расчёты столкновений для сложных форм.
  • Поддержка современных инструментов сборки и Tree Shaking, что уменьшает итоговый размер бандла.
  • Совместимость с Three.js и другими рендерерами без глобальных объектов.

Пример инициализации Cannon-es:

import { World, Body, Sphere, Plane, Vec3 } from 'cannon-es';

const world = new World();
world.gravity.set(0, -9.82, 0);

const ground = new Body({
  mass: 0,
  shape: new Plane(),
});
ground.quaternion.setFromEuler(-Math.PI / 2, 0, 0);
world.addBody(ground);

const ball = new Body({
  mass: 1,
  shape: new Sphere(1),
  position: new Vec3(0, 5, 0),
});
world.addBody(ball);

function update(deltaTime) {
  world.step(deltaTime);
}

Сравнение Cannon.js и Cannon-es

Характеристика Cannon.js Cannon-es
Статус разработки Стагнирует, мало обновлений Активный форк, исправления багов
Модули CommonJS или глобальные объекты ES-модули
Совместимость с сборщиками Ограничена Полная (Webpack, Vite, Rollup)
Tree Shaking Нет Да
Поддержка современных браузеров Частичная Полная

Вывод по выбору версии: Для современных проектов предпочтительнее использовать Cannon-es из-за модульности, исправленных багов и совместимости с инструментами сборки. Оригинальная Cannon.js актуальна только для старых проектов или когда необходима минимальная зависимость без сборщиков.

Настройка материалов и столкновений

Одна из сильных сторон Cannon.js и Cannon-es — точная настройка материалов и взаимодействий. Пример с разными коэффициентами трения и упругости:

import { Material, ContactMaterial } from 'cannon-es';

const iceMaterial = new Material('ice');
const rubberMaterial = new Material('rubber');

const iceRubberContact = new ContactMaterial(
  iceMaterial,
  rubberMaterial,
  {
    friction: 0.1,    // низкое трение
    restitution: 0.9, // высокая упругость
  }
);

world.addContactMaterial(iceRubberContact);

Работа с коллизиями

Для отслеживания столкновений объектов используется событие collide на телах:

sphereBody.addEventListener('collide', (event) => {
  console.log('Сфера столкнулась с телом:', event.body);
});

Эта возможность позволяет реализовать физические реакции, звук столкновения или игровую логику на основе физики.

Шаг симуляции и стабильность

Метод world.step(timeStep) поддерживает точность и стабильность физики:

  • Фиксированный шаг (например, 1/60 секунды) обеспечивает предсказуемую симуляцию.
  • Дробление времени при больших дельтах позволяет избежать “проникновения” объектов друг в друга:
const fixedTimeStep = 1 / 60;
const maxSubSteps = 3;

world.step(fixedTimeStep, deltaTime, maxSubSteps);

Интеграция с Three.js

Чаще всего Cannon-es используется совместно с Three.js для визуализации. При этом физические объекты создаются в Cannon-es, а визуальные — в Three.js. Их позиции и ориентации синхронизируются на каждом кадре:

sphereMesh.position.copy(sphereBody.position);
sphereMesh.quaternion.copy(sphereBody.quaternion);

Это обеспечивает реалистичное движение с полной поддержкой физики и визуализации.

Поддержка сложных форм

Cannon-es поддерживает:

  • Box, Sphere, Cylinder, Plane — базовые формы.
  • ConvexPolyhedron — многогранники для произвольных объектов.
  • Trimesh — сетки с произвольными вершинами (ограниченная производительность).

Для сложных объектов важно учитывать производительность и стабильность симуляции, используя ConvexPolyhedron, когда это возможно.


Cannon.js и Cannon-es предоставляют полный набор инструментов для создания физики в 3D-пространстве. Основное различие заключается в модульности, исправлениях багов и совместимости с современными инструментами — именно эти факторы делают выбор между версиями критичным при разработке современных приложений.