Raycasting — это технология, позволяющая определять пересечение луча с объектами сцены. В контексте A-Frame, raycasting используется для реализации интерактивности, наведения курсора, выбора объектов и управления событиями в виртуальной реальности. Лучи могут исходить от камеры, контроллеров VR, курсоров или пользовательских сущностей.
В A-Frame raycasting реализован через компонент
raycaster. Он автоматически отслеживает объекты, с которыми
пересекается луч, и генерирует соответствующие события.
<a-entity id="cursor"
raycaster="objects: .interactable"
cursor="fuse: true; fuseTimeout: 500">
</a-entity>
В этом примере:
raycaster="objects: .interactable" — луч будет
проверять пересечение только с объектами, имеющими класс
interactable.cursor="fuse: true; fuseTimeout: 500" — активирует
механизм “fuse”, то есть срабатывание после удержания курсора на объекте
500 мс.Компонент raycaster поддерживает несколько ключевых
параметров:
1000).0, то есть каждый кадр).Пример настройки:
<a-entity id="hand"
raycaster="objects: .clickable; far: 10; showLine: true">
</a-entity>
Здесь луч ограничен 10 единицами и визуализирован, что позволяет видеть траекторию проверки пересечений.
Основные события, которые генерирует raycaster:
raycaster-intersected — объект вошел в область
пересечения.raycaster-intersected-cleared — объект покинул область
пересечения.raycaster-intersection — срабатывает каждый кадр, пока
луч пересекает объект.Использование событий через A-Frame:
<a-entity id="cursor"
raycaster="objects: .interactable"
position="0 1.6 0">
</a-entity>
<script>
const cursor = document.querySelector('#cursor');
cursor.addEventListener('raycaster-intersected', evt => {
evt.detail.el.setAttribute('material', 'color', 'red');
});
cursor.addEventListener('raycaster-intersected-cleared', evt => {
evt.detail.el.setAttribute('material', 'color', 'white');
});
</script>
В этом примере объекты становятся красными при наведении и возвращаются к белому цвету после ухода луча.
Raycasting позволяет интегрировать интерактивность с контроллерами VR:
<a-entity laser-controls="hand: right"
raycaster="objects: .button">
</a-entity>
Компонент laser-controls автоматически создает луч,
исходящий из контроллера, имитируя лазерную указку. Луч может пересекать
только объекты с классом .button, что упрощает реализацию
интерфейсов виртуальной реальности.
При больших сценах важно контролировать производительность:
objects.interval, чтобы проверять пересечения не
каждый кадр.far для уменьшения длины луча.Множественные пересечения: raycaster поддерживает массив пересечений, что позволяет определить ближайший объект или все объекты на пути луча.
const raycasterEl = document.querySelector('[raycaster]');
const intersections = raycasterEl.components.raycaster.intersections;
intersections.forEach(intersect => {
console.log(intersect.el.id, intersect.distance);
});
Кастомные события: можно создавать свои события на основе пересечения:
raycasterEl.addEventListener('raycaster-intersection', evt => {
const nearest = evt.detail.intersections[0];
console.log('Ближайший объект:', nearest.el.id);
});
Анимации при наведении: сочетание
raycaster и animation позволяет визуально
подсвечивать объекты или менять их свойства при пересечении луча.
Raycasting эффективно работает с комплексными 3D-моделями:
geometry или aabb-collider)
для точного определения пересечений.three.js Mesh напрямую для
кастомного контроля пересечений позволяет оптимизировать raycasting для
больших сцен.Raycasting лежит в основе всех интерактивных UI-элементов в A-Frame:
mouseenter и mouseleave тесно
связаны с raycaster-intersected и
raycaster-intersected-cleared.Пример:
<a-box class="button" position="0 1 -3" color="blue"></a-box>
<script>
const buttons = document.querySelectorAll('.button');
buttons.forEach(btn => {
btn.addEventListener('mouseenter', () => btn.setAttribute('scale', '1.2 1.2 1.2'));
btn.addEventListener('mouseleave', () => btn.setAttribute('scale', '1 1 1'));
});
</script>
raycaster.Raycasting обеспечивает ключевую интерактивность в A-Frame, позволяя создавать реалистичные и отзывчивые виртуальные сцены.