ЖМК-301/2. Веб-дизайн. Практическое занятие №7. 3D дизайн с HDR-панорамой и particles-паттерном
Вам нужно создать страницу, реализованную по принципам 3D-дизайна и содержащую:
- основной слой с меню, заголовком и описанием;
- нижний слой, содержащий HDR-панораму;
- средний слой, содержащий particles компонент в видеоформате webm.
Подготовительный этап.
Выберите любую HDR-панораму и сохраните ее в формате .hdr предпочтительно в размере не более 5-6 мб. Загрузите ее в репозиторий.
Или здесь: https://ambientcg.com/
Скачайте любой видеофайл, содержащий particles компонент. Найти такие файлы можно, например, здесь: https://enter-media.org/webm/particles/
После этого вам нужно удалить фон из этого видеофайла. Достаточно будет даже короткого демонстрационного отрывка в несколько секунд. Это можно сделать через любой онлайн-сервис, например, https://airbrush.com/ru/video-background-remover или https://picsart.com/ru/video-background-remover/ или https://www.cutout.pro/ru/remove-video-background и т.д. Финальный файл должен быть в формате webm. Также загрузите результат в репозиторий.
I CSS
1) Указываем селекторы страницы и шрифт, используемый в проекте. Можно специально прописать стиль курсора на панораме - в моем примере используется навигационный курсор (cursor: all-scroll):
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
background-color: #000;
font-family: "Montserrat", sans-serif;
}
2) Указываем цвет ссылок при наведении курсора:
a:hover {
color: цветссылок;
}
3) Положение класса библиотеки 3D:
.webgl {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
4) Слоя с компонентами и отображения курсора:
.ui-layer {
position: absolute;
margin-top: -350px;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
pointer-events: none;
display: flex;
flex-direction: column;
justify-content: space-between;
padding: 40px;
box-sizing: border-box;
color: #fff;
}
.pointer-auto {
pointer-events: auto;
}
5) Теперь параметры хэдера, лого (поле слева вверху):
header {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.logo {
font-family: "Oswald", sans-serif;
font-size: 1.5rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 2px;
}
.logo span {
display: block;
font-family: "Montserrat", sans-serif;
font-size: 0.8rem;
font-weight: 400;
letter-spacing: 1px;
opacity: 0.8;
}
6) Панель навигации:
nav ul {
display: flex;
gap: 30px;
list-style: none;
padding: 0;
margin: 0;
}
7) Ссылки в навигационном меню и их цвета. Используйте свои если необходимо:
nav a {
color: #FFFFFF;
text-decoration: none;
font-size: 0.9rem;
text-transform: uppercase;
letter-spacing: 1px;
transition: opacity 0.3s;
position: relative;
}
nav a:hover {
opacity: 1;
}
nav a.active {
opacity: 1;
color: #ff0055;
text-shadow: 0 0 15px rgba(255, 0, 85, 0.4);
}
nav a.active::after {
content: "";
position: absolute;
bottom: -6px;
left: 50%;
transform: translateX(-50%);
width: 4px;
height: 4px;
background: #ff0055;
border-radius: 50%;
box-shadow: 0 0 8px rgba(255, 0, 85, 0.8);
}
8) Текстовая часть:
.text-section {
position: relative;
flex-grow: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
padding-left: 5%;
}
.text-subtitle {
font-size: 1rem;
text-transform: uppercase;
letter-spacing: 5px;
margin-bottom: 0;
display: flex;
align-items: center;
gap: 15px;
opacity: 0.9;
font-weight: 500;
}
.text-subtitle::before {
content: "";
display: block;
width: 40px;
height: 2px;
background: #ff0055;
}
h1.text-title {
font-size: 10rem;
margin: 10px 0;
line-height: 0.9;
text-transform: uppercase;
letter-spacing: -2px;
color: #fff;
background: none;
-webkit-text-fill-color: initial;
text-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.text-desk {
max-width: 450px;
font-size: 1rem;
line-height: 1.7;
opacity: 0.9;
margin-top: 20px;
border-left: 0;
padding-left: 0;
font-weight: 300;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
}
9) Футер (справа внизу) и его компоненты:
footer {
display: flex;
justify-content: space-between;
align-items: flex-end;
}
.footer-right {
font-size: 1.5rem;
font-family: "Oswald", sans-serif;
letter-spacing: 8px;
text-transform: uppercase;
opacity: 0.8;
display: flex;
align-items: center;
}
.footer-right::before {
content: "";
display: block;
width: 60px;
height: 1px;
background: #fff;
margin-right: 20px;
}
10) Добавляем параметры для мобильных устройств:
@media (max-width: 768px) {
.ui-layer {
padding: 24px;
}
header {
flex-direction: column;
align-items: center;
gap: 15px;
position: relative;
}
.logo {
margin-bottom: 5px;
text-align: center;
}
.logo span {
display: inline-block;
}
nav ul {
gap: 20px;
flex-wrap: wrap;
justify-content: center;
}
nav a {
font-size: 0.75rem;
letter-spacing: 2px;
}
.text-section {
padding-left: 0;
align-items: center;
text-align: center;
margin-top: 40px;
justify-content: flex-start;
}
.text-subtitle {
justify-content: center;
font-size: 0.8rem;
margin-bottom: 10px;
}
.text-subtitle::before {
display: none;
}
h1.text-title {
font-size: clamp(3rem, 13vw, 5rem);
line-height: 0.9;
margin-bottom: 20px;
}
.text-desk {
font-size: 0.9rem;
max-width: 90%;
border: none;
margin-top: 10px;
padding: 0;
line-height: 1.6;
}
footer {
flex-direction: column;
justify-content: flex-end;
align-items: center;
width: 100%;
padding-bottom: 30px;
gap: 30px;
}
.footer-right {
display: none;
}
}
II JavaScript
11) Указываем параметры камеры и отображения 3D-сцены:
import * as THREE from "three";
import { OrbitControls } from "jsm/controls/OrbitControls.js";
import { HDRLoader } from "jsm/loaders/HDRLoader.js";
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x000000);
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000,
);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector(".webgl"),
antialias: true,
});
renderer.setSize(window.innerWidth, window.innerHeight);
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
const textureLoader = new THREE.TextureLoader();
const particlesGroup = new THREE.Group();
scene.add(particlesGroup);
const groupCount = 3;
const particlesPerGroup = 30;
const palette = [
new THREE.Color(0x00ffcc),
new THREE.Color(0x00e5ff),
new THREE.Color(0xffffff),
];
12) Добавляем ссылку на particles-компонент из репозитория. Ссылка должна быть в виде: https://raw.githubusercontent.com/никнейм/имя репозитория/main/Particles.webm
for (let g = 0; g < groupCount; g++) {
const video = document.createElement("video");
video.crossOrigin = "anonymous";
video.src =
"ссылка на particles-компонент";
video.loop = true;
video.muted = true;
video.playbackRate = 0.010 + Math.random() * 1.0;
video.play();
const videoTexture = new THREE.VideoTexture(video);
videoTexture.colorSpace = THREE.SRGBColorSpace;
videoTexture.minFilter = THREE.LinearFilter;
videoTexture.magFilter = THREE.LinearFilter;
const particlesGeometry = new THREE.BufferGeometry();
const positionsArray = new Float32Array(particlesPerGroup * 3);
const colorsArray = new Float32Array(particlesPerGroup * 3);
for (let i = 0; i < particlesPerGroup; i++) {
const i3 = i * 3;
positionsArray[i3] = (Math.random() - 0.5) * 30;
positionsArray[i3 + 1] = (Math.random() - 0.5) * 30;
positionsArray[i3 + 2] = (Math.random() - 0.5) * 30;
const randomColor = palette[Math.floor(Math.random() * palette.length)];
colorsArray[i3] = randomColor.r;
colorsArray[i3 + 1] = randomColor.g;
colorsArray[i3 + 2] = randomColor.b;
}
particlesGeometry.setAttribute(
"position",
new THREE.BufferAttribute(positionsArray, 3),
);
particlesGeometry.setAttribute(
"color",
new THREE.BufferAttribute(colorsArray, 3),
);
const particlesMaterial = new THREE.PointsMaterial({
size: 10,
transparent: true,
depthWrite: false,
alphaTest: 0.001,
alphaMap: videoTexture,
vertexColors: false,
});
const particles = new THREE.Points(particlesGeometry, particlesMaterial);
particles.frustumCulled = false;
particlesGroup.add(particles);
}
13) Добавляем 3D-панораму в формате HDR. Исходная ссылка из репозитория у вас будет выглядеть так (view raw):
https://github.com/никнейм/имя репозитория/raw/refs/heads/main/st_peters_square_night_2k.hdr
Отредактируйте ее до следующего формата:
https://raw.githubusercontent.com/никнейм/имя репозитория/refs/heads/main/st_peters_square_night_2k.hdr
Добавьте ссылку в JavaScript:
const hdrLoader = new HDRLoader();
const hdrTexture = hdrLoader.load(
"ссылка на HDR",
() => {
hdrTexture.mapping = THREE.EquirectangularReflectionMapping;
hdrTexture.colorSpace = THREE.SRGBColorSpace;
scene.background = hdrTexture;
scene.backgroundRotation.y = (Math.PI / 180) * -160;
scene.backgroundRotation.x = (Math.PI / 180) * -20;
},
);
const clock = new THREE.Clock();
const tick = () => {
const elapsedTime = clock.getElapsedTime();
particlesGroup.rotation.x = elapsedTime * 0.1;
controls.update();
renderer.render(scene, camera);
requestAnimationFrame(tick);
};
tick();
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
III HTML
14) Указываем стандартные теги и имя вкладки:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Ваше название</title>
15) Встраиваем CSS
16) Закрываем основной </head>, открываем <body> и второй <head>
17) Встраиваем шрифтры:
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;500&family=Oswald:wght@700&display=swap" rel="stylesheet">
18) Закрываем </head>
19) Встраиваем модуль 3D-карты:
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.182.0/build/three.module.js",
"jsm/": "https://cdn.jsdelivr.net/npm/three@0.182.0/examples/jsm/"
}
}
</script>
20) Открываем классы слоя, хэдера, текста лого и названия:
<div class="ui-layer">
<header>
<div class="logo pointer-auto">
Название лого
<span>Текст под лого</span>
</div>
21) Задаем навигационное меню. Используйте свои названия вкладок и ссылки:
<nav class="pointer-auto">
<ul>
<li><a href="">имя вкладки</a></li>
<li><a href="">имя вкладки</a></li>
<li><a href="">имя вкладки</a></li>
<li><a href="">имя вкладки</a></li>
</ul>
</nav>
</header>
22) Теперь добавляем секцию с текстом. Используйте свой текст:
<section class="text-section">
<p class="text-subtitle">Заголовок вверху</p>
<h1 class="text-title">Крупный заголовок</h1>
<div class="text-desk">Основной абзац текста.</div>
</section>
23) Добавляем футер с вашим текстом:
<footer>
<br>
<br>
<br>
<div class="footer-right">Текст футера</div>
</footer>
</div>
24) Внедряем 3D-библиотеку:
<canvas class="webgl"></canvas>
25) Подключаем ваш JavaScript файл в теге script с атрибутом type и свойством module:
<script type="module"></script>
26) Закрываем оставшиеся теги </body> и </html>
Если все верно, то ваш проект будет выглядеть примерно так: https://konoplevdesign3.blogspot.com/p/3d-panorama-html-body-width-100-height_9.html
Ссылки на выполненное задание принимаются в комментариях к этому посту для ЖМК-302 до 17:00 20 марта, для ЖМК-301 до 17:00 23 марта.
РЕЗУЛЬТАТЫ (данные обновляются):
Ананина Виктория - 5
Власов Максим - 5
Гостева Полина - 5
Жукова Виктория - 5
Климович Мария - 5
Куликова Мария - 5
Маханек Вера - 5
Орлова Арина - 5
Слободская Елизавета - 5
Цветкова Виктория - 5
Хайруддинов Тимур - 5
Чугунова Елизавета - 5
Шабалина Виктория - 5
Широкоумова Полина - 5
https://kukukukukukukukuky.blogspot.com/p/imports-three-httpscdn.html - Чугунова Елизавета
ОтветитьУдалитьhttps://slobodskayaelizavta.blogspot.com/p/html-body-width-100-height-100-margin-0_87.html
ОтветитьУдалитьhttps://makhanekvera.blogspot.com/2026/03/html-body-width-100-height-100-margin-0_17.html
ОтветитьУдалитьhttps://polinashirokoumova.blogspot.com/2026/03/html-body-width-100-height-100-margin-0_44.html
ОтветитьУдалитьhttps://supervikaw.blogspot.com/p/html-body-width-100-height-100-margin-0.html
ОтветитьУдалитьhttps://philosopherarishka.blogspot.com/2026/03/html-body-width-100-height-100-margin-0.html
ОтветитьУдалитьhttps://mediaeconomicsananina.blogspot.com/2026/03/imports-three-httpscdn.htm
ОтветитьУдалитьhttps://vikka56.blogspot.com/p/html-body-width-100-height-100-margin-0.html
ОтветитьУдалитьhttps://mariaklimovich.blogspot.com/p/room-html-body-width-100-height-100.html
ОтветитьУдалитьhttps://gostevapolina.blogspot.com/2026/03/imports-three-httpscdn.html
ОтветитьУдалитьhttps://maxvlasovblog.blogspot.com/p/20.html
ОтветитьУдалитьhttps://kulikovam22.blogspot.com/2026/03/html-body-width-100-height-100-margin-0_49.html
ОтветитьУдалитьhttps://shadowdarksaid.blogspot.com/p/html-body-width-100-height-100-margin-0.html
ОтветитьУдалитьЖукова Виктория ЖМК-302
ОтветитьУдалить6 (прошлое) задание https://whisk0ss.blogspot.com/p/proto-3d-music-player-html-body-padding.html
Текущее задание https://whisk0ss.blogspot.com/p/html-body-width-100-height-100-margin-0.html
https://besheniff.blogspot.com/2026/03/imports-three-httpscdn.html
ОтветитьУдалитьhttps://uchebaandriuk.blogspot.com/2026/03/andriukphoto.html
ОтветитьУдалить