Three.js использует объект WebGLRenderer, который
привязывается к HTML-элементу <canvas>. Для генерации
скриншота важно заранее правильно настроить рендерер и размеры
canvas.
import * as THREE from 'three';
// Создание сцены
const scene = new THREE.Scene();
// Настройка камеры
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
// Создание рендерера и привязка к canvas
const renderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
Ключевой момент: свойство
preserveDrawingBuffer: true позволяет сохранять содержимое
canvas после рендеринга, что необходимо для корректного создания
скриншотов.
Для демонстрации генерации изображения необходимо хотя бы несколько объектов и источников света.
// Геометрия и материал
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshStandardMaterial({ color: 0x0077ff });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// Освещение
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
Выделение: Без источников света объекты с материалами, чувствительными к освещению, будут отображаться полностью черными.
Для динамичного изображения часто используют цикл анимации с вращением объектов:
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
После настройки сцены и рендерера получение изображения осуществляется через метод toDataURL() у canvas.
function takeScreenshot() {
const dataURL = renderer.domElement.toDataURL('image/png');
downloadImage(dataURL, 'screenshot.png');
}
function downloadImage(data, filename) {
const link = document.createElement('a');
link.href = data;
link.download = filename;
link.click();
}
Ключевой момент: формат image/png
сохраняет прозрачность и обеспечивает высокое качество. Для JPEG можно
использовать 'image/jpeg'.
Чтобы получить изображение в высоком разрешении, рендерер можно масштабировать с помощью setSize:
function takeHighResScreenshot(multiplier = 2) {
const originalWidth = renderer.domElement.width;
const originalHeight = renderer.domElement.height;
renderer.setSize(originalWidth * multiplier, originalHeight * multiplier);
renderer.render(scene, camera);
const dataURL = renderer.domElement.toDataURL('image/png');
renderer.setSize(originalWidth, originalHeight); // возвращаем исходный размер
downloadImage(dataURL, `screenshot_${multiplier}x.png`);
}
Выделение: увеличение размеров canvas увеличивает качество скриншота без потери деталей. Важно восстановить исходные размеры, чтобы не нарушить отображение на странице.
Можно создавать отдельный рендерер и canvas, которые не прикрепляются к DOM. Это удобно для серверного или скрытого рендеринга:
const offscreenRenderer = new THREE.WebGLRenderer({ preserveDrawingBuffer: true });
offscreenRenderer.setSize(1920, 1080);
offscreenRenderer.render(scene, camera);
const hiddenScreenshot = offscreenRenderer.domElement.toDataURL('image/png');
Выделение: такой подход позволяет генерировать скриншоты без видимого canvas, что полезно для генерации миниатюр или серверного рендеринга.
Three.js позволяет управлять antialiasing для сглаживания краев:
const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });
Для получения более гладких скриншотов при масштабировании часто используют комбинацию увеличения разрешения canvas и включенного antialiasing.
Если сцена должна иметь прозрачный фон, необходимо:
const renderer = new THREE.WebGLRenderer({ alpha: true, preserveDrawingBuffer: true });
renderer.setClearColor(0x000000, 0); // полностью прозрачный
При генерации PNG изображения прозрачные области будут сохранены.
Для удобства можно интегрировать GUI (например, dat.GUI) для выбора разрешения и формата скриншота:
import GUI from 'dat.gui';
const gui = new GUI();
const params = {
resolution: 2,
capture: () => takeHighResScreenshot(params.resolution)
};
gui.add(params, 'resolution', 1, 5, 1);
gui.add(params, 'capture');
Это позволяет динамически управлять качеством и сохранять скриншоты без изменения кода.