| name | build-3d-site |
| description | Создать сайт с 3D эффектами — Three.js, WebGL, Spline, particle systems, shader backgrounds. Для агентств, студий, портфолио, технологических продуктов где нужен wow-эффект. |
| argument-hint | описание сайта или клиент/бриф |
Build 3D Site — Alar Web Studio
Ты создаёшь 3D веб-сайт с визуальным wow-эффектом для $ARGUMENTS.
ШАГ 0 — Брифинг
Задай вопросы перед кодом:
1. Тип сайта: лендинг / портфолио / продуктовый / агентство?
2. Настроение: тёмный sci-fi / светлый органик / неоновый cyberpunk / минимал?
3. Главный 3D элемент: фон с частицами / интерактивный объект / 3D текст / blob / геометрия?
4. Есть ли Spline сцена? Если да — ссылка или embed код
5. Анимация: автоматическая / реагирует на мышь / на скролл?
6. Контент: что должно быть на сайте?
7. Примеры сайтов которые нравятся?
ТЕХНОЛОГИЧЕСКИЙ СТЕК
Выбор движка
| Задача | Инструмент |
|---|
| Фон с частицами | Three.js + Points/BufferGeometry |
| Интерактивный 3D объект | Three.js + GLTFLoader |
| Fluid blob / морфинг | Three.js + ShaderMaterial |
| Готовая 3D сцена | Spline (embed iframe или @splinetool/runtime) |
| 2.5D параллакс | GSAP + CSS transform3d |
| Particle cursor | Vanilla JS Canvas |
Подключение Three.js (CDN — без сборщика)
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.167/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.167/examples/jsm/"
}
}
</script>
<script type="module" src="main.js"></script>
БАЗОВЫЕ ПАТТЕРНЫ
1. Particle Background (частицы в пространстве)
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
document.body.appendChild(renderer.domElement);
renderer.domElement.style.cssText = 'position:fixed;top:0;left:0;z-index:-1;';
const count = 3000;
const geo = new THREE.BufferGeometry();
const pos = new Float32Array(count * 3);
for (let i = 0; i < count * 3; i++) pos[i] = (Math.random() - 0.5) * 20;
geo.setAttribute('position', new THREE.BufferAttribute(pos, 3));
const mat = new THREE.PointsMaterial({ size: 0.02, color: 0x8b5cf6, transparent: true, opacity: 0.8 });
const points = new THREE.Points(geo, mat);
scene.add(points);
camera.position.z = 5;
let mouseX = 0, mouseY = 0;
document.addEventListener('mousemove', e => {
mouseX = (e.clientX / innerWidth - 0.5) * 0.5;
mouseY = (e.clientY / innerHeight - 0.5) * 0.5;
});
(function animate() {
requestAnimationFrame(animate);
points.rotation.y += 0.0005;
points.rotation.x += 0.0002;
camera.position.x += (mouseX - camera.position.x) * 0.05;
camera.position.y += (-mouseY - camera.position.y) * 0.05;
camera.lookAt(scene.position);
renderer.render(scene, camera);
})();
window.addEventListener('resize', () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
2. Animated Gradient Blob (GLSL шейдер)
const geo = new THREE.PlaneGeometry(4, 4, 64, 64);
const mat = new THREE.ShaderMaterial({
uniforms: { uTime: { value: 0 }, uColor1: { value: new THREE.Color('#7c3aed') }, uColor2: { value: new THREE.Color('#2563eb') } },
vertexShader: `
uniform float uTime;
varying vec2 vUv;
void main() {
vUv = uv;
vec3 pos = position;
float wave = sin(pos.x * 3.0 + uTime) * 0.15 + sin(pos.y * 2.0 + uTime * 0.8) * 0.1;
pos.z += wave;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: `
uniform vec3 uColor1; uniform vec3 uColor2; varying vec2 vUv;
void main() {
vec3 col = mix(uColor1, uColor2, vUv.x + sin(vUv.y * 3.14) * 0.3);
gl_FragColor = vec4(col, 1.0);
}
`
});
3. Spline Embed (самый быстрый 3D)
<script type="module" src="https://unpkg.com/@splinetool/viewer@1/build/spline-viewer.js"></script>
<spline-viewer url="https://prod.spline.design/YOUR_SCENE_ID/scene.splinecode"></spline-viewer>
4. 3D Text с морфингом
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
const loader = new FontLoader();
loader.load('https://threejs.org/examples/fonts/helvetiker_bold.typeface.json', font => {
const geo = new TextGeometry('ALAR', { font, size: 1, height: 0.2, curveSegments: 12 });
geo.center();
const mesh = new THREE.Mesh(geo, new THREE.MeshStandardMaterial({ color: 0xffffff, metalness: 0.8, roughness: 0.2 }));
scene.add(mesh);
});
GSAP ИНТЕГРАЦИЯ
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12/dist/ScrollTrigger.min.js"></script>
gsap.registerPlugin(ScrollTrigger);
gsap.from('.hero-title', { y: 80, opacity: 0, duration: 1.2, ease: 'power4.out', delay: 0.3 });
gsap.from('.hero-sub', { y: 40, opacity: 0, duration: 1, ease: 'power3.out', delay: 0.6 });
gsap.to(threeObject.rotation, {
y: Math.PI * 2,
ease: 'none',
scrollTrigger: { trigger: '.section', start: 'top bottom', end: 'bottom top', scrub: 1 }
});
import { SplitText } from 'gsap/SplitText';
ТИПИЧНАЯ СТРУКТУРА 3D САЙТА
<canvas id="three-canvas" style="position:fixed;top:0;left:0;z-index:0;pointer-events:none"></canvas>
<div class="content" style="position:relative;z-index:1">
<nav>...</nav>
<section class="hero">
<h1 class="hero-title">Заголовок</h1>
<p class="hero-sub">Подзаголовок</p>
<a class="btn" href="#">CTA</a>
</section>
<section class="about">...</section>
</div>
ПАЛИТРЫ ДЛЯ 3D САЙТОВ
--bg: #050508;
--surface: #0d0d14;
--accent: #7c3aed;
--accent2: #2563eb;
--text: #f0f0ff;
--muted: #6b6b8a;
--bg: #030a06; --accent: #00ff87; --accent2: #00c4ff;
--bg: #080706; --accent: #d4a853; --accent2: #b8936a;
--bg: #060010; --accent: #ff00ff; --accent2: #00ffff;
ШРИФТЫ ДЛЯ 3D/TECH САЙТОВ
<link href="https://api.fontshare.com/v2/css?f[]=clash-display@400,500,600,700&display=swap" rel="stylesheet">
<link href="https://api.fontshare.com/v2/css?f[]=satoshi@700,900&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
PERFORMANCE ДЛЯ 3D
- Pixel ratio:
Math.min(devicePixelRatio, 2) — никогда больше 2
- На мобилке отключать Three.js, показывать CSS gradient fallback
renderer.setAnimationLoop вместо requestAnimationFrame для XR
- Dispose геометрий и материалов при размонтировании
- Particle count: desktop ≤ 5000, mobile ≤ 500
if (window.matchMedia('(max-width: 768px)').matches) {
document.getElementById('three-canvas').style.display = 'none';
}
ПОСЛЕ РАБОТЫ
git add -A && git commit -m "[UI] 3D — [название]" && git push origin main
Сохранить в web-studio/templates/ если это переиспользуемый шаблон.