onmouseover -> onmouseenteronmouseout -> onmouseleave
function animateMarquee(el, duration) {
const innerEl = el.querySelector('.marquee__inner');
const innerWidth = innerEl.offsetWidth;
const cloneEl = innerEl.cloneNode(true);
el.appendChild(cloneEl);
let start = 0;
let rafId = null;
let progressElapsed = 0;
let progress = 0;
function step(now) {
progress = progressElapsed + (now - start) % duration / duration;
const translateX = innerWidth * progress;
innerEl.style.transform = `translate3d(-${translateX}px, 0 , 0)`;
cloneEl.style.transform = `translate3d(-${translateX}px, 0 , 0)`;
rafId = requestAnimationFrame(step);
}
function play() {
if (rafId) return;
progressElapsed = progress;
start = performance.now();
rafId = requestAnimationFrame(step);
}
function pause() {
cancelAnimationFrame(rafId);
rafId = null;
}
play();
return { play, pause };
}
const marquee1 = document.querySelector('#marquee1');
const playback = animateMarquee(marquee1, 15000);
marquee1.addEventListener('mouseenter', () => playback.pause());
marquee1.addEventListener('mouseleave', () => playback.play());
const objectEl = document.querySelector("#holst");
const svgEl = objectEl.getSVGDocument().rootElement;
расстояние от боков карточки до боков экрана может отличаться
50vw - 50%. В этом случае нужно еще учесть ширину скроллбара, которую придется определять в js.
// табы
const tabsBtn = [...document.querySelectorAll(".widget-chat__tabs__btn")];if (xDiff > 0) {
/* left swipe */
const currIdx = tabsBtn.findIndex((el) => el.classList.contains("active"));
const prevIdx = currIdx - 1;
if (prevIdx > -1) {
tabsBtn[prevIdx].click();
}
} else {
/* right swipe */
const currIdx = tabsBtn.findIndex((el) => el.classList.contains("active"));
const nextIdx = currIdx + 1;
if (nextIdx < tabsBtn.length) {
tabsBtn[nextIdx].click();
}
}
image.naturalHeight. Плюс ко всему document.querySelector выбирает первый попавшийся элемент, а не тот который бы создан последним