Как сделать такой эффект, как на сайте https://www.fotonaut.cz/en/ ? Интересует поведение пилюль (таблеток), если присмотреться, они как бы живут своей жизнью, двигаются в независимости от движения мыши. И двигаются даже когда мышь не двигается. Интересует именно этот эффект. Кто-нибудь знает как это сделать?)) Спасибо!!!
Что-то такое получилось:
// функция линейной интерполяции
let lerp = (a, b, val) => a + val * (b - a);
// генератор псевдослучайных чисел
let rand = n => (Math.sin(n)*43758.5453123)%1;
// одномерный шум
let noise = p => lerp(rand(Math.floor(p)), rand(Math.floor(p) + 1.0), p%1);
// слои, принимающие участие в параллакс эффекте
let layers = document.querySelectorAll('.parallax');
// массив с состояниями слоёв
let offsets = [...layers].map(l => ({x:0, y:0, X:0, Y:0}));
// слушатель положения курсора
addEventListener('mousemove', e => {
let dx = innerWidth/2 - e.x; // дельта по X от центра экрана
let dy = innerHeight/2 - e.y; // дельта по X от центра экрана
offsets.forEach((layer, i) => { // для каждого слоя поменяем "целевое" положение
layer.X = (1 + i) * dx * 0.1; // положение слоя по X
layer.Y = (1 + i) * dy * 0.1; // положение слоя по Y
});
})
requestAnimationFrame(draw); // говорим браузеру что надо нарисовать кадр
// функция, которая рисует один кадр, ее аргумент - время с начала анимации в мс
function draw(t) {
offsets.forEach((layer, i) => { // для каждого слоя,
layer.x += (layer.X - layer.x) * 0.1; // двигаемся в сторону целевого положения по Х
layer.y += (layer.Y - layer.y) * 0.1; // и по Y
let x = layer.x + noise((1e5+t/9e3)*(i+1))*33; // + значение шума от времени по Х
let y = layer.y + noise((1e7+t/9e3)*(i+1))*22; // и по Y
layers[i].style.transform = `translate(${x}px,${y}px)`; // двигаем слой
})
requestAnimationFrame(draw); // говорим браузеру что надо-бы нарисовать еще один кадр
}
.parallax {
position: fixed;
}
<div class="parallax">
<img src="https://picsum.photos/id/41/900/300"
style="margin:-50px">
</div>
<div class="parallax">
<img src="https://picsum.photos/id/23/150"
style="margin:20px">
</div>
<div class="parallax">
<img src="https://picsum.photos/id/43/80"
style="margin:40px">
</div>
Вот как вариант. Конечно, на SO есть товарищи, которые могут реализовать это гораздо лучше. Мне и самому хотелось бы увидеть такие решения.
var currentX = '';
var currentY = '';
var movementConstant = 0.05;
$(document).mousemove(function(e) {
if (currentX == '') currentX = e.pageX;
var xdiff = e.pageX - currentX;
currentX = e.pageX;
if (currentY == '') currentY = e.pageY;
var ydiff = e.pageY - currentY;
currentY = e.pageY;
$('.parallax_contanier div').each(function(i, el) {
var movement = (i + 1) * (xdiff * movementConstant);
var movementy = (i + 1) * (ydiff * movementConstant);
var newX = $(el).position().left + movement;
var newY = $(el).position().top + movementy;
$(el).css('left', newX + 'px');
$(el).css('top', newY + 'px');
});
});
body,
html {
margin: 0;
padding: 0;
}
body {
overflow: hidden;
width: 100vw;
height: 100vh;
background: url('https://i.imgur.com/SPbeVMa.jpg') center center no-repeat;
background-size: cover;
}
.parallax {
position: absolute;
top: 0;
left: 0;
width: 30%;
height: 40%;
opacity: 0.5;
}
.layer1 {
top: 20%;
left: 10%;
background-color: red;
}
.layer2 {
top: 40%;
left: 60%;
background-color: blue;
}
.random {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
}
.random1 {
border-radius: 100%;
top: 30%;
left: 20%;
background-color: green;
animation: moveY 15s linear 0s infinite alternate;
}
.random2 {
top: 60%;
left: 50%;
background-color: gold;
animation: moveX 15s linear 0s infinite alternate;
}
@keyframes moveX {
0% {
top: 0;
left: 0;
transform: rotate(0deg);
}
20% {
top: 30%;
left: 20%;
transform: rotate(72deg);
}
40% {
top: 5%;
left: 40%;
transform: rotate(144deg);
}
60% {
top: 30%;
left: 60%;
transform: rotate(216deg);
}
80% {
top: 4%;
left: 70%;
transform: rotate(288deg);
}
100% {
top: 2%;
left: 80%;
transform: rotate(360deg);
}
}
@keyframes moveY {
0% {
top: 0%;
left: 30%;
}
20% {
top: 20%;
left: 40%;
}
40% {
top: 45%;
left: 30%;
}
60% {
top: 60%;
left: 5%;
}
80% {
top: 70%;
left: 30%;
}
100% {
top: 80%;
left: 20%;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parallax_contanier">
<div class="parallax layer1"></div>
<div class="parallax layer2"></div>
</div>
<div class="random_contanier">
<div class="random random1"></div>
<div class="random random2"></div>
</div>
Хотелось бы всё же дополнительно добавить вариант, в котором для передвижения элементов в независимости от движения мыши вместо @keyframes
используется очень интересное решение от @hu-fo (за что ему спасибо!).
//Решение @hu-fo. Передвижение элементов в независимости от движения мыши
var items = document.querySelectorAll('.layer__item');
var layer = document.querySelector('.layer');
items.forEach(item => requestAnimationFrame(() => move(item)));
function move(el) {
var s = Math.random() > 0.5 ? 1 : -1;
var x = s * (Math.random() * 40);
var y = s * (Math.random() * 40);
var td = Math.random() * 3 + 1;
el.style.transitionDuration = `${td}s`;
el.style.transform = `translate3d(${x}px, ${y}px, 0)`;
setTimeout(function() {
requestAnimationFrame(() => move(el));
}, td * 1000);
}
//Передвижение элементов в зависимости от движения мыши
var currentX = '';
var currentY = '';
var movementConstant = 0.05;
$(document).mousemove(function(e) {
if (currentX == '') currentX = e.pageX;
var xdiff = e.pageX - currentX;
currentX = e.pageX;
if (currentY == '') currentY = e.pageY;
var ydiff = e.pageY - currentY;
currentY = e.pageY;
$('.parallax_contanier div').each(function(i, el) {
var movement = (i + 1) * (xdiff * movementConstant);
var movementy = (i + 1) * (ydiff * movementConstant);
var newX = $(el).position().left + movement;
var newY = $(el).position().top + movementy;
$(el).css('left', newX + 'px');
$(el).css('top', newY + 'px');
});
});
body,
html {
margin: 0;
padding: 0;
}
body {
overflow: hidden;
width: 100vw;
height: 100vh;
background: url('https://i.imgur.com/SPbeVMa.jpg') center center no-repeat;
background-size: cover;
}
.parallax {
position: absolute;
top: 0;
left: 0;
width: 30%;
height: 40%;
opacity: 0.5;
}
.layer1 {
top: 20%;
left: 10%;
background-color: red;
}
.layer2 {
top: 40%;
left: 60%;
background-color: blue;
}
.layer {
position: absolute;
width: 100%;
height: 100%;
list-style: none;
}
.layer__item {
position: absolute;
height: 30px;
width: 30px;
border-radius: 100%;
}
.layer__item:nth-child(1) {
left: 70%;
top: 20%;
background-color: gold;
}
.layer__item:nth-child(2) {
left: 20%;
top: 20%;
background-color: green;
}
.layer__item:nth-child(3) {
left: 30%;
top: 70%;
background-color: pink;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parallax_contanier">
<div class="parallax layer1"></div>
<div class="parallax layer2"></div>
<ul class="layer">
<li class="layer__item"></li>
<li class="layer__item"></li>
<li class="layer__item"></li>
</ul>
</div>
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Есть php, он при определённых событиях выводит button
Новичок в js: Необходимо использовать переменные storeProducts(массив объектов) и detailProduct(конкретный объект) далее в программе, но они не видны за пределами...
Вопрос странныйЕсть ли в js встроенная хеш-функция для хеш таблиц? Искал информацию, не нашел
Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском