Lit — современный фреймворк для создания Web Components, который обеспечивает реактивность, шаблонность и высокую производительность. Он идеально подходит для интеграции с WebGL, позволяя создавать интерактивные 3D-приложения на вебе с использованием компонетной архитектуры.
Для работы с WebGL внутри Lit-компонента используется стандартный
элемент. Основная структура компонента
включает:
import { LitElement, html, css } from 'lit';
class ThreeDComponent extends LitElement {
static styles = css`
canvas {
width: 100%;
height: 100%;
display: block;
}
`;
firstUpdated() {
this.initWebGL();
}
initWebGL() {
const canvas = this.renderRoot.querySelector('canvas');
const gl = canvas.getContext('webgl2');
if (!gl) {
console.error('WebGL2 не поддерживается этим браузером');
return;
}
// Настройка сцены
gl.clearColor(0.1, 0.1, 0.1, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
}
render() {
return html``;
}
}
customElements.define('three-d-component', ThreeDComponent);
Ключевые моменты:
firstUpdated() используется для инициализации WebGL
после того, как DOM компонента готов.this.renderRoot предоставляет доступ к Shadow DOM
компонента, позволяя работать с локальными элементами.webgl2 обеспечивает современные возможности
OpenGL ES 3.0, включая шейдеры и буферы.Lit позволяет объявлять реактивные свойства, которые автоматически обновляют компонент при изменении:
import { property } from 'lit/decorators.js';
class ThreeDComponent extends LitElement {
@property({ type: Number }) rotationX = 0;
@property({ type: Number }) rotationY = 0;
// Обновление сцены при изменении свойств
updated(changedProperties) {
if (changedProperties.has('rotationX') || changedProperties.has('rotationY')) {
this.renderScene();
}
}
renderScene() {
const canvas = this.renderRoot.querySelector('canvas');
const gl = canvas.getContext('webgl2');
// Логика обновления сцены с использованием rotationX и rotationY
}
}
Примечание: Свойства с декоратором
@property автоматически отслеживаются, и
updated() вызывается при любом изменении их значений.
Для упрощения работы с WebGL часто используют библиотеку Three.js. Lit позволяет легко интегрировать её, сохраняя реактивность компонентов:
import * as THREE from 'three';
class ThreeJSComponent extends LitElement {
firstUpdated() {
const canvas = this.renderRoot.querySelector('canvas');
this.scene = new THREE.Scene();
this.camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight, 0.1, 1000);
this.renderer = new THREE.WebGLRenderer({ canvas });
this.camera.position.z = 5;
this.cube = this.createCube();
this.scene.add(this.cube);
this.animate();
}
createCube() {
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
return new THREE.Mesh(geometry, material);
}
animate() {
requestAnimationFrame(() => this.animate());
this.cube.rotation.x += 0.01;
this.cube.rotation.y += 0.01;
this.renderer.render(this.scene, this.camera);
}
render() {
return html``;
}
}
customElements.define('three-js-component', ThreeJSComponent);
Особенности интеграции:
остаётся доступным для рендеринга.requestAnimationFrame, который поддерживает плавные
обновления сцены.Lit позволяет легко добавлять обработку событий, например, для управления камерой или объектами:
render() {
return html``;
}
onMouseMove(event) {
const rect = this.renderRoot.querySelector('canvas').getBoundingClientRect();
this.rotationX = (event.clientY - rect.top) / rect.height * 2 - 1;
this.rotationY = (event.clientX - rect.left) / rect.width * 2 - 1;
}
Преимущества:
@event.Для 3D-приложений важно учитывать производительность:
updated(), чтобы не
рендерить сцену лишний раз.Для крупных приложений рекомендуется разделять логику:
Такой подход обеспечивает модульность, повторное использование кода и легкую поддержку больших проектов.