Как сделать 2 бесконечно, по очереди бегущие строки

Рейтинг: 1Ответов: 1Опубликовано: 14.01.2023

Есть массив строк и они должны по очереди выежать и заезжать за контейнер

Первый выезжает сверху слева и заезжает за контейнер, двигаясь направо, потом второй снизу справа выезжает и заезжает за контейнер, двигаясь налево и так по кругу, но по очереди

На данный момент, имеется только вёрстка этого макета как на видео, но скидывать наверное не нужно. Можете пожалуйста показать примером или же если есть готовое решение, буду сильно благодарен

Ответы

▲ 4Принят

Можно сделать так:

  1. Запоминаем наши div-ы в переменные и на их основе создаём словарик. Это нам понадобится чтобы легко и просто переключаться между правым и левым div-ом

  2. С помощью getComputedStyle достаём значение переменной --animation-duration, который объявлен в CSS

  3. Достаем оттуда число и делим пополам. На пополам надо делить, чтобы скрипт успевал обновлять значения для каждой из сторон. Иначе он будет либо слишком быстро менять либо слишком медленно, а нам надо чтобы прямо перед началом очередной стороны текст менялся

  4. Т.к. нам надо циклически гулять по массиву, то я использую формулу (currIndex + 1) % arrayLength. Именно % arrayLength позволяет гулять циклически по массиву, т.к. он возвращает значения от 0 до arrayLength - 1. P.S. Но эта формула верна только если вы всегда увеличиваете индекс. Если вы будете уменьшать, то в более общем виде формула будет такой: (arrayLength + currIndex +/- 1) % arrayLength

const texts = [
  'Right text one',
  'Left text one',
  'Right text two',
  'Left text two',
  'Right text three',
  'Left text three',
];

const rightSide = document.querySelector('.text-from-right');
const leftSide = document.querySelector('.text-from-left');

const sidesMap = new Map([
  [rightSide, leftSide], 
  [leftSide, rightSide]
]);

const animationDurationInSecs = getComputedStyle(document.body).getPropertyValue('--animation-duration'); // '4s'
const animationDurationHalf = parseFloat(animationDurationInSecs) / 2; // 2

let currTextIndex = -1;
let currSide = leftSide;

setInterval(() => {
  currTextIndex = (currTextIndex + 1) % texts.length;
  currSide = sidesMap.get(currSide);
  
  currSide.innerHTML = texts[currTextIndex];
  
}, animationDurationHalf * 1000);
:root {
  --animation-duration: 4s;
}

body {
  margin: 0;
}

.section {
  display: flex;
  width: 100%;
}

.block {
  width: 100%;
}

.center-block {
  height: 180px;
  border: 1px solid black;
}

.left-block,
.right-block {
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.left-block {
  justify-content: start;  
}

.right-block {
  justify-content: end;
}

.text-from-left,
.text-from-right {
  white-space: nowrap;
  width: fit-content;
  padding-left: 100%;
}

.text-from-left {
  animation: right-stream var(--animation-duration) linear infinite;
}

.text-from-right {
  animation: left-stream var(--animation-duration) linear infinite;
}

@keyframes right-stream {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

@keyframes left-stream {
  0% {
    transform: translateX(100%);
  }
  100% {
    transform: translateX(-100%);
  }
}
<div class="section">
  <div class="block left-block">
    <div class="text-from-left">Left text onee</div>
  </div>

  <div class="block center-block"></div>

  <div class="block right-block">
    <div class="text-from-right">Right text onee</div>
  </div>
</div>