TIST-29: ThreeJS #18
@ -8,13 +8,23 @@
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
|
<div class="welcome">
|
||||||
|
<div class="container">
|
||||||
|
<div class="welcome__inner">
|
||||||
|
<div class="text-container">
|
||||||
|
<div class="quote">
|
||||||
|
<h2><span class="black-qoute-word">Your</span> Fridge.</h2>
|
||||||
|
<h2><span class="black-qoute-word">Your</span> Rules.</h2>
|
||||||
|
<h2><span class="black-qoute-word">Our</span> Recipes.</h2>
|
||||||
|
</div>
|
||||||
|
<p>Discover delicious recipes tailored to exactly what you have on hand — no extra shopping trips, no wasted food, just tasty meals made easy.</p>
|
||||||
|
</div>
|
||||||
|
<canvas id="food-3d"></canvas>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="quote">
|
|
||||||
<h2><span class="black-qoute-word">Your</span> Fridge. <span class="black-qoute-word">Your</span> Rules.
|
|
||||||
<span class="black-qoute-word">Our</span> Recipes.
|
|
||||||
</h2>
|
|
||||||
</div>
|
|
||||||
<div class="latest-recipes">
|
<div class="latest-recipes">
|
||||||
<h2 class="title">Latest Recipes Added</h2>
|
<h2 class="title">Latest Recipes Added</h2>
|
||||||
<!-- Slider main container -->
|
<!-- Slider main container -->
|
||||||
@ -402,6 +412,17 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script type="importmap">
|
||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"three": "https://cdn.jsdelivr.net/npm/three@v0.149.0/build/three.module.js",
|
||||||
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@v0.149.0/examples/jsm/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script type="module" src="<?= ASSETS_PATH . '/js/threejs-scene.js' ?>"></script>
|
||||||
|
|
||||||
|
|
||||||
<?php the_footer(array(
|
<?php the_footer(array(
|
||||||
ASSETS_PATH . '/swiper/swiper-bundle.min.js',
|
ASSETS_PATH . '/swiper/swiper-bundle.min.js',
|
||||||
ASSETS_PATH . '/js/index.js',
|
ASSETS_PATH . '/js/index.js',
|
||||||
|
|||||||
@ -148,14 +148,35 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.quote {
|
.quote {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
font-family: var(--common-font);
|
font-family: var(--common-font);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
color: var(--panel-text);
|
color: var(--panel-text);
|
||||||
margin: 0 auto;
|
|
||||||
margin-top: 46px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
}
|
||||||
|
.quote h2 {
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.welcome {
|
||||||
|
background: var(--panel-background);
|
||||||
|
margin-bottom: 30px;
|
||||||
|
font-size: 24px;
|
||||||
|
line-height: 32px;
|
||||||
|
}
|
||||||
|
.welcome__inner {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.welcome__inner .quote {
|
||||||
|
font-size: 38px;
|
||||||
|
text-align: left;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.welcome .text-container {
|
||||||
|
padding: 50px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.black-qoute-word {
|
.black-qoute-word {
|
||||||
@ -799,6 +820,9 @@ label span {
|
|||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
.welcome__inner {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@media (max-width: 900px) {
|
@media (max-width: 900px) {
|
||||||
@ -909,6 +933,9 @@ label span {
|
|||||||
width: 150px;
|
width: 150px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#food-3d {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 400px){
|
@media (max-width: 400px){
|
||||||
|
|||||||
BIN
assets/food_3d.glb
Normal file
BIN
assets/food_3d.glb
Normal file
Binary file not shown.
68
assets/js/threejs-scene.js
Normal file
68
assets/js/threejs-scene.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import * as THREE from 'three';
|
||||||
|
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
|
||||||
|
|
||||||
|
// Сцена, камера, рендерер
|
||||||
|
const scene = new THREE.Scene();
|
||||||
|
scene.background = new THREE.Color(0xeaf8eb);
|
||||||
|
|
||||||
|
const width = 430;
|
||||||
|
const height = 350;
|
||||||
|
|
||||||
|
const camera = new THREE.PerspectiveCamera(
|
||||||
|
75,width / height, 0.1, 1000
|
||||||
|
);
|
||||||
|
camera.position.set(9, 3, 3); // Слегка сверху и сбоку
|
||||||
|
camera.lookAt(0, 0, 0);
|
||||||
|
|
||||||
|
const renderer = new THREE.WebGLRenderer({ antialias: true, canvas: document.querySelector('#food-3d'), });
|
||||||
|
renderer.setSize(width, height, false);
|
||||||
|
|
||||||
|
// Еда
|
||||||
|
const loader = new GLTFLoader();
|
||||||
|
let foodModel;
|
||||||
|
loader.load('/assets/food_3d.glb', function(gltf) {
|
||||||
|
foodModel = gltf.scene;
|
||||||
|
foodModel.position.set(0, -1, 1.5);
|
||||||
|
foodModel.scale.set(25, 25, 30);
|
||||||
|
scene.add(foodModel);
|
||||||
|
|
||||||
|
}, function (xhr) {
|
||||||
|
// called while loading is progressing
|
||||||
|
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
|
||||||
|
},
|
||||||
|
function (error) {
|
||||||
|
// called when loading has errors
|
||||||
|
console.log('An error happened', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Свет (не обязателен для MeshNormalMaterial, но пригодится для других)
|
||||||
|
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
|
||||||
|
scene.add(ambientLight);
|
||||||
|
|
||||||
|
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.4);
|
||||||
|
directionalLight.position.set(3, 5, 2);
|
||||||
|
directionalLight.castShadow = false;
|
||||||
|
scene.add(directionalLight);
|
||||||
|
|
||||||
|
const hemisphereLight = new THREE.HemisphereLight(0xaaaaaa, 0x444444, 0.6);
|
||||||
|
scene.add(hemisphereLight);
|
||||||
|
|
||||||
|
let mouseX = 0;
|
||||||
|
let mouseY = 0;
|
||||||
|
|
||||||
|
window.addEventListener('mousemove', (event) => {
|
||||||
|
// Нормализуем координаты мыши в [-1, 1]
|
||||||
|
mouseX = (event.clientX / window.innerWidth) * 2 - 1;
|
||||||
|
mouseY = -((event.clientY / window.innerHeight) * 2 - 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
function animate() {
|
||||||
|
requestAnimationFrame(animate);
|
||||||
|
|
||||||
|
foodModel.position.z = 1.5 + mouseX * 0.7;
|
||||||
|
foodModel.position.y = -1 + mouseY * -0.7;
|
||||||
|
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
animate();
|
||||||
Loading…
x
Reference in New Issue
Block a user