Как плавно изменять фон сайта при нажатии на определенное изображение/кнопку и запомнить выбранное изображение в текущей или следующих сессиях?
Сайт делаю на тильде, извините. Я только учусь и не умею писать полноценные коды. Перепробовал уйму вариантов с форумов, вопрос оказался актуальным, но ни один код не смог нормально вписать в тильду.
Каким способом я частично решил задачу: Создал 6 элементов. Первые 3 с изображениями имеют классы: uc-tab1, uc-tab2, uc-tab3. В 4-6 разместил 3 мини-изображения-кнопки с одинаковым классом: tab-btn и разными ссылками href="#tab1","#tab2","#tab3".
<style> /* Стиль кнопки для активного элемента */
.my-active-class {
outline: 4px solid #fff !important;
outline-offset: 6px;
}
</style>
<script>
// Скрыть все вкладки, кроме первой
$('[class*="uc-tab"]').not('.uc-tab1').fadeOut(0);
// Добавить класс "bactive" для первой вкладки
$('[href="#tab1"]').addClass('my-active-class');
// Обработчик события для клика по кнопкам вкладок
$('.tab-btn a').click(function() {
// Убрать класс "bactive" у всех кнопок
$('.tab-btn a').removeClass('my-active-class');
// Добавить класс "my-active-class" к кнопке, по которой кликнули
$(this).addClass('my-active-class');
// Получить идентификатор вкладки из атрибута href кнопки
var slide = $(this).attr('href').slice(1);
// Скрыть все вкладки
$('[class*="uc-tab"]').fadeOut(0);
// Показать вкладку с идентификатором, соответствующим кнопке
$('.uc-' + slide + '').fadeIn(0);
t_lazyload_update();
});
</script>
Работает это по принципу: показать выбранный блок и скрыть остальные. Но при перезагрузке - все возвращается к начальному состоянию. Где и как прописывать localStorage и sessionStorage я не знаю. И стоит ли вообще использовать такой костыльный код для моей задачи? Было бы очень здорово еще сделать плавную смену изображений, но это, наверное, я много хочу. Прошу помощи у вас господа программисты и жду ваши предложения.
Ответы (1 шт):
В данном примере реализованна плавное изменение фона при помощи background-image и transition, но данный способ может работать не везде (Chrome на Window тут всё ок работает).
Так же тут реализовано сохранение выбранного фона в localStorage, но в сниппете это не работает.
Описание в коде.
// массив изображений для фона
const wallpapers = [
'https://i.imgur.com/hspxf3p.png',
'https://i.imgur.com/HKg999L.png',
'https://i.imgur.com/EajFv0e.png'
];
const changeBg = $('.change-bg'); // блок куда будут создаваться элементы и там же выбираться
const toBg = $('body'); // блок где будет меняться фон
let isTransitionFlag = false; // флаг для плавности анимации смены фона
// в сниппете не работает localStorage (в целях безопасности), по этому в рабочем коде ниже строчку раскомментировать, а под ней удалить.
// const selectedBg = localStorage.getItem('body-bg') ? +(localStorage.getItem('body-bg')) : 0;
const selectedBg = 0;
toBg.css('background-image', `url(${wallpapers[selectedBg]})`); // если ранее был сохранён фон, то устанавливаем его
// добавляем варианты бэкграундов в блок
wallpapers.map(function(value, index) {
const item = $('<div class="change-bg__item"></div>'); // создаём айтем
const img = $('<div class="change-bg__item-img"></div>'); // вложенный блок
img.css('background-image', `url(${value})`); // вложенному ставим изображение
if(selectedBg === index) item.addClass('change-bg__item--active'); // если по индексу совпадение с выбранным, то выдаём айтему активный класс
item.append(img); // добавляем вложенный в айтем
changeBg.append(item); // добавляем айтем в блок с выбором
});
// смена фона
changeBg.on('click', '.change-bg__item', function() {
if(isTransitionFlag === false && !$(this).hasClass('change-bg__item--active')) { // если класс не активый и флаг "выключен", то выполняем код ниже
isTransitionFlag = true; // переключаем флаг
changeBg.find('.change-bg__item--active').removeClass('change-bg__item--active'); // удаляем у предыдущего активного айтема активный класс
$(this).addClass('change-bg__item--active'); // вешаем активный класс на нажатый
const index = $(this).index(); // получаем индекс айтема
toBg.css('background-image', `url(${wallpapers[index]})`); // по индексу выбираем и ставим фон
// localStorage.setItem('body-bg', index); // сохраняем индекс в localStorage
// запускаем таймер
setTimeout(function() {
isTransitionFlag = false; // после окончания таймера меняем обратно флаг
}, 1000); // время таймера должно быть равным кол-во времени на transition background-image, в данном случае 1s == 1000 (ms)
// Есть ивент transitionend, но в данном случае он не отрабатывает :\
}
});
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
margin: 0;
transition: background-image 1s ease;
}
.change-bg {
display: flex;
gap: 10px;
}
.change-bg__item {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
border-radius: 50%;
border: 3px solid transparent;
box-sizing: border-box;
cursor: pointer;
transition: border-color .3s ease;
}
.change-bg__item:not(.change-bg__item--active):hover {
border-color: rgba(255,255,255, .5);
}
.change-bg__item--active {
border-color: #fff;
}
.change-bg__item-img {
width: calc(100% - 8px);
height: calc(100% - 8px);
border-radius: 50%;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<div class="change-bg"></div>
Вариант на JS:
// массив изображений для фона
const wallpapers = [
'https://i.imgur.com/hspxf3p.png',
'https://i.imgur.com/HKg999L.png',
'https://i.imgur.com/EajFv0e.png'
];
const changeBg = document.querySelector('.change-bg');
const toBg = document.body;
let isTransitionFlag = false;
// в сниппете не работает localStorage (в целях безопасности), по этому в рабочем коде ниже строчку раскомментировать, а под ней удалить.
// const selectedBg = localStorage.getItem('body-bg') ? +(localStorage.getItem('body-bg')) : 0;
const selectedBg = 0;
toBg.style.backgroundImage = `url(${wallpapers[selectedBg]})`;
// добавляем варианты бэкграундов в блок
wallpapers.map(function(value, index) {
const item = document.createElement('div');
item.classList.add('change-bg__item');
const img = document.createElement('div');
img.classList.add('change-bg__item-img');
img.style.backgroundImage = `url(${value})`;
if(selectedBg === index) item.classList.add('change-bg__item--active');
item.append(img);
changeBg.append(item);
});
// смена фона
changeBg.addEventListener('click', (event) => {
const target = event.target.closest('.change-bg__item');
if(target && isTransitionFlag === false && !target.classList.contains('change-bg__item--active')) {
isTransitionFlag = true;
const oldActive = changeBg.querySelector('.change-bg__item--active')
if(oldActive) oldActive.classList.remove('change-bg__item--active');
target.classList.add('change-bg__item--active');
const index = [...target.parentElement.children].indexOf(target);
toBg.style.backgroundImage = `url(${wallpapers[index]})`;
// localStorage.setItem('body-bg', index); // сохраняем индекс в localStorage
// запускаем таймер
setTimeout(function() {
isTransitionFlag = false;
}, 1000);
}
});
body {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
margin: 0;
transition: background-image 1s ease;
}
.change-bg {
display: flex;
gap: 10px;
}
.change-bg__item {
display: flex;
justify-content: center;
align-items: center;
width: 100px;
height: 100px;
border-radius: 50%;
border: 3px solid transparent;
box-sizing: border-box;
cursor: pointer;
transition: border-color .3s ease;
}
.change-bg__item:not(.change-bg__item--active):hover {
border-color: rgba(255,255,255, .5);
}
.change-bg__item--active {
border-color: #fff;
}
.change-bg__item-img {
width: calc(100% - 8px);
height: calc(100% - 8px);
border-radius: 50%;
background-repeat: no-repeat;
background-position: center center;
background-size: cover;
}
<div class="change-bg"></div>
