Как центрировать элементы в карусельном слайдере?

Вопросы и ответы

В настоящее время я работаю над слайдером с флагами стран, в котором около 14 различных флагов.

Мне нужно, чтобы анимация заключалась в том, что есть контейнер/карта, показывающая только 3 страны, и через 2 секунды она сдвигается:

Страна слева выходит из контейнера, страна посередине двигается в левую сторону, а страна справа перемещается в середину и немного увеличивается в размере (так она становится более заметной), когда двигается к ней.

Новая страна появляется с правой стороны.

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу понять, как центрировать среднее изображение в центре карты, так как в том варианте, который я реализовал, есть 14 изображений, и когда я использую justify-content: center;, на карте в центре отображается Филиппины, что нормально, но не является желаемым результатом.

Что я уже пробовал:

  • Использование пикселей и расчет необходимого перемещения, но это не делает его отзывчивым, а мне нужно, чтобы он был отзывчивым.
  • Justify-content: center; на div

Что происходит сейчас: [Нажмите]
Желаемая анимация: [Нажмите]

Это мой первый пост на Stackoverflow, и я надеюсь, что мне удалось все объяснить понятно; если нет, не стесняйтесь оставлять отзыв о том, как я могу улучшить свой пост.

Код:

const slider = document.querySelector('.flag-slider');
const flags = document.querySelectorAll('.flag');
let currentIndex = 2; // Средний флаг

function updateFlags() {
  flags.forEach((flag, index) => {
    flag.classList.remove('active');
    if (index === currentIndex - 1) {
      flag.classList.add('active');
    }
  });
}

function slideFlags() {
  // Сдвиг влево
  slider.style.transform = `translateX(-${(currentIndex - 1) * (75 / 3)}%)`;

  currentIndex++;

  if (currentIndex > flags.length) {
    console.log('сброс');
    currentIndex = 2;
    slider.style.transform = `translateX(0%)`;
  }

  updateFlags();
}

// Начальная настройка флагов
updateFlags();

// Автосдвиг каждые 2 секунды
setInterval(slideFlags, 2000);
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  background-color: #f0f0f0;
}

.countries {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 300px;
  padding: 20px;
}

.slider-container {
  width: 100%;
  margin: 50px auto;
  overflow: hidden;
  position: relative;
}

.flag-slider {
  display: flex;
  transition: transform 0.5s ease-in-out;
}

.flag,
.last_flag {
  width: 33.33%;
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
}

.flag img {
  width: 100%;
  object-fit: contain;
}

.flag.active {
  transform: scale(1.2);
}
<html class="no-js" lang="">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title></title>
  <link rel="stylesheet" href="https://stackoverflow.com/questions/78990433/css/style.css">
  <meta name="description" content="">
  <meta property="og:title" content="">
  <meta property="og:type" content="">
  <meta property="og:url" content="">
  <meta property="og:image" content="">
  <meta property="og:image:alt" content="">
  <link rel="icon" href="http://stackoverflow.com/favicon.ico" >
  <link rel="icon" href="http://stackoverflow.com/icon.svg" type="image/svg+xml">
  <link rel="apple-touch-icon" href="icon.png">
  <link rel="manifest" href="site.webmanifest">
  <meta name="theme-color" content="#fafafa">
</head>

<body>

  <div class="countries">
    <div class="slider-container">
      <div class="flag-slider">
        <img class="flag" src="https://picsum.photos/200" alt="Австралия">
        <img class="flag" src="https://picsum.photos/200" alt="Австрия">
        <img class="flag" src="https://picsum.photos/200" alt="Бразилия">
        <img class="flag" src="https://picsum.photos/200" alt="Канада">
        <img class="flag" src="https://picsum.photos/200" alt="Франция">
        <img class="flag" src="https://picsum.photos/200" alt="Германия">
        <img class="flag" src="https://picsum.photos/200" alt="Индия">
        <img class="flag" src="https://picsum.photos/200" alt="Мексика">
        <img class="flag" src="https://picsum.photos/200" alt="Филиппины">
        <img class="flag" src="https://picsum.photos/200" alt="Южная Африка">
        <img class="flag" src="https://picsum.photos/200" alt="Египет">
        <img class="flag" src="https://picsum.photos/200" alt="Великобритания">
        <img class="flag" src="https://picsum.photos/200" alt="США">
        <img class="flag" src="https://picsum.photos/200" alt="Венесуэла">
        <img class="flag" src="https://picsum.photos/200" alt="Австралия">
        <img class="last_flag" src="https://picsum.photos/200" alt="Австрия">
      </div>
    </div>
    <span>Разные страны</span>
  </div>
  <script src="js/app.js"></script>
</body>

</html>

Я пытался это рассчитать и жестко закодировать, но это работало только для фиксированной ширины, а для меньшего экрана не работало.

Это похвально, что вы сами пишете элемент карусели. Я вижу, что вы используете свойство CSS transform, чтобы сдвигать элементы с их исходных позиций. Если вы здесь будете рассчитывать с помощью более правильных значений, ваш элемент будет центрирован.

// Заменил 75 / 3 на 100 / 3
slider.style.transform = `translateX(-${(currentIndex - 1) * (100 / 3)}%)`;

Элемент должен занимать одну треть от 100% (33.33 %), так что вы сдвинете его ровно на это значение (в зависимости от индекса элемента).
75% здесь, на мой взгляд, хоть и замысловато, но не является хорошим стартовым значением.

const slider = document.querySelector('.flag-slider');
const flags = document.querySelectorAll('.flag');
let currentIndex = 2; // Средний флаг

function updateFlags() {
  flags.forEach((flag, index) => {
    flag.classList.remove('active');
    if (index === currentIndex - 1) {
      flag.classList.add('active');
    }
  });
}

function slideFlags() {
  // Сдвиг влево
  slider.style.transform = `translateX(-${(currentIndex - 1) * (100 / 3)}%)`;

  currentIndex++;

  if (currentIndex > flags.length) {
    console.log('сброс');
    currentIndex = 2;
    slider.style.transform = `translateX(0%)`;
  }

  updateFlags();
}

// Начальная настройка флагов
updateFlags();

// Автосдвиг каждые 2 секунды
setInterval(slideFlags, 2000);
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  background-color: #f0f0f0;
}

.countries {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 300px;
  padding: 20px;
}

.slider-container {
  width: 100%;
  margin: 50px auto;
  overflow: hidden;
  position: relative;
}

.flag-slider {
  display: flex;
  transition: transform 0.5s ease-in-out;
}

.flag,
.last_flag {
  width: 33.33%;
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
}

.flag img {
  width: 100%;
  object-fit: contain;
}

.flag.active {
  transform: scale(1.2);
}
<div class="countries">
  <div class="slider-container">
    <div class="flag-slider">
      <img class="flag" src="https://picsum.photos/200?1" alt="Австралия">
      <img class="flag" src="https://picsum.photos/200?2" alt="Австрия">
      <img class="flag" src="https://picsum.photos/200?3" alt="Бразилия">
      <img class="flag" src="https://picsum.photos/200?4" alt="Канада">
      <img class="flag" src="https://picsum.photos/200?5" alt="Франция">
      <img class="flag" src="https://picsum.photos/200?6" alt="Германия">
      <img class="flag" src="https://picsum.photos/200?7" alt="Индия">
      <img class="flag" src="https://picsum.photos/200?8" alt="Мексика">
      <img class="flag" src="https://picsum.photos/200?9" alt="Филиппины">
      <img class="flag" src="https://picsum.photos/200?10" alt="Южная Африка">
      <img class="flag" src="https://picsum.photos/200?11" alt="Египет">
      <img class="flag" src="https://picsum.photos/200?12" alt="Великобритания">
      <img class="flag" src="https://picsum.photos/200?13" alt="США">
      <img class="flag" src="https://picsum.photos/200?14" alt="Венесуэла">
      <img class="flag" src="https://picsum.photos/200?15" alt="Австралия">
      <img class="last_flag" src="https://picsum.photos/200?16" alt="Австрия">
    </div>
  </div>
  <span>Разные страны</span>
</div>

Ответ

Чтобы центрировать элементы в карусели с флагами стран, вам нужно внести небольшие изменения в ваш JavaScript и CSS. Ниже приведены шаги, которые помогут вам достичь желаемого результата:

Шаг 1: Измените JavaScript

В вашем функции slideFlags, текущая логика перемещения слайдера требует корректировки. Вам нужно изменить значение translateX, чтобы адаптировать его к ширине элементов. Вместо 75 / 3, вы должны использовать 100 / 3, чтобы точно центровать элементы. Вот обновленный код:

const slider = document.querySelector('.flag-slider');
const flags = document.querySelectorAll('.flag');
let currentIndex = 2; // Индекс средней флаги (начальная позиция)

function updateFlags() {
  flags.forEach((flag, index) => {
    flag.classList.remove('active');
    if (index === currentIndex - 1) {
      flag.classList.add('active');
    }
  });
}

function slideFlags() {
  // Перемещение влево
  slider.style.transform = `translateX(-${(currentIndex - 1) * (100 / 3)}%)`;

  currentIndex++;

  if (currentIndex > flags.length) {
    console.log('reset');
    currentIndex = 2; // Сброс индекса
    slider.style.transform = `translateX(0%)`;
  }

  updateFlags();
}

// Инициализация флагов
updateFlags();

// Авто-прокрутка каждые 2 секунды
setInterval(slideFlags, 2000);

Шаг 2: Обновите CSS

Ваш CSS выглядит в целом хорошо, но убедитесь, что ширина .flag установлена правильно для обеспечения, что три флага могут поместиться в контейнере.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: Arial, sans-serif;
  background-color: #f0f0f0;
}

.countries {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 300px;
  padding: 20px;
}

.slider-container {
  width: 100%;
  margin: 50px auto;
  overflow: hidden;
  position: relative;
}

.flag-slider {
  display: flex;
  transition: transform 0.5s ease-in-out;
}

.flag {
  width: 33.33%; /* Каждый флаг занимает 33.33% от ширины контейнера */
  padding: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: transform 0.5s ease-in-out, opacity 0.5s ease-in-out;
}

.flag img {
  width: 100%;
  object-fit: contain;
}

.flag.active {
  transform: scale(1.2); /* Увеличение масштаба активного флага */
}

Шаг 3: HTML

Ваш HTML также в принципе правильный. Вот как он может выглядеть:

<div class="countries">
  <div class="slider-container">
    <div class="flag-slider">
      <img class="flag" src="https://picsum.photos/200?1" alt="Australia">
      <img class="flag" src="https://picsum.photos/200?2" alt="Austria">
      <img class="flag" src="https://picsum.photos/200?3" alt="Brazil">
      <img class="flag" src="https://picsum.photos/200?4" alt="Canada">
      <img class="flag" src="https://picsum.photos/200?5" alt="France">
      <img class="flag" src="https://picsum.photos/200?6" alt="Germany">
      <img class="flag" src="https://picsum.photos/200?7" alt="India">
      <img class="flag" src="https://picsum.photos/200?8" alt="Mexico">
      <img class="flag" src="https://picsum.photos/200?9" alt="Philippines">
      <img class="flag" src="https://picsum.photos/200?10" alt="South Africa">
      <img class="flag" src="https://picsum.photos/200?11" alt="Egypt">
      <img class="flag" src="https://picsum.photos/200?12" alt="UK">
      <img class="flag" src="https://picsum.photos/200?13" alt="USA">
      <img class="flag" src="https://picsum.photos/200?14" alt="Venezuela">
      <img class="flag" src="https://picsum.photos/200?15" alt="Australia">
      <img class="last_flag" src="https://picsum.photos/200?16" alt="Austria">
    </div>
  </div>
  <span>Разные страны</span>
</div>

Заключение

С этими изменениями ваша карусель должна теперь правильно центрировать флаг прямо на середине контейнера. Если у вас возникнут дополнительные вопросы или проблемы, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...