Как создать гладкий бесконечный горизонтальный свиток (цикл) с JSON-выноженным контентом в JavaScript? [закрыто]Jquery

Программирование на jquery
Ответить Пред. темаСлед. тема
Anonymous
 Как создать гладкий бесконечный горизонтальный свиток (цикл) с JSON-выноженным контентом в JavaScript? [закрыто]

Сообщение Anonymous »

Я строю веб -сайт портфеля, где я показываю обзоры клиентов в горизонтальном прокручиваемом разделе. Я динамически получаю обзорные карты из файла review.json. Когда я достигаю левой или правой, он резко сбрасывается или попадает в визуальный край, если я не клонирую содержание в 1000 раз (что, очевидно, отстает от браузера). Но нет никакой реальной бесконечной иллюзии, если я не использую 50–100+ клоны DOM, что не эффективно. Использование 20 клонов уже становится тяжелым. < /P>
Есть ли лучший способ имитировать это, но без огромного раздувания DOM? < /P>
с логикой сброса в реальном времени или зеркальным клонированием? Я видел это на некоторых веб -сайтах, но я понятия не имею, как это можно сделать ... это какая -то библиотека или что -то особенное?
json

Код: Выделить всё

[
{
"name": "Alice Novak",
"role": "COO of FutureTech",
"image": "images/alice.png",
"linkedin": "https://linkedin.com/in/reviewerLINKEDIN1",
"text": "Professional, fast and reliable results. Highly recommend."
},
{
"name": "Carlos Duran",
"role": "Founder of WebWave",
"image": "images/carlos.png",
"linkedin": "https://linkedin.com/in/reviewerLINKEDIN2",
"text": "Super helpful in scaling our outreach.  Great comms."
},
{
"name": "Linda Park",
"role": "Lead at PixelNest",
"image": "images/linda.png",
"linkedin": "https://linkedin.com/in/reviewerLINKEDIN3",
"text": "Very creative! A lot of attention to detail in the work."
}
//Many more random examples below
]
< /code>
[b] code < /strong> < /p>


// JSON Storage Bin, see: https://www.npoint.io
const dataURL = "https://api.npoint.io/0203fc45b524c37f2e1c"; // review.json

// Global flag to notify scroll script
window.reviewsReady = false;

fetch(dataURL)
.then(res => res.json())
.then(data => {
const track = document.getElementById('scrollCards');
track.innerHTML = ''; // clear any fallback

data.forEach(review => {
const card = document.createElement('div');
card.className = 'review-card';
card.innerHTML = `


[img]${review.image}[/img]

${review.name}
${review.role}

[url=${review.linkedin}]
[img]https://static.vecteezy.com/system/resources/previews/018/930/480/non_2x/linkedin-logo-linkedin-icon-transparent-free-png.png[/img]
[/url]


${review.text}
`;
track.appendChild(card);
});

// Notify that reviews are loaded
window.reviewsReady = true;
})
.catch(err => console.error("Failed to load reviews:", err));

function initReviewScroller() {
const wrapper = document.querySelector('.review-scroll-wrapper');
const track = document.getElementById('scrollCards');

const originalCards = Array.from(track.children);
const MULTIPLIER = 20;
for (let i = 0; i < MULTIPLIER - 1; i++) {
originalCards.forEach(card => track.appendChild(card.cloneNode(true)));
}

const allCards = track.querySelectorAll('.review-card');
const cardWidth = allCards[0].offsetWidth + 30;
const totalCards = allCards.length;
const totalWidth = cardWidth * totalCards;

wrapper.scrollLeft = totalWidth / 2;

let isDragging = false;
let dragStartX = 0;
let scrollStart = 0;
let pauseAuto = false;

wrapper.addEventListener('mousedown', (e) => {
isDragging = true;
pauseAuto = true;
dragStartX = e.pageX;
scrollStart = wrapper.scrollLeft;
});

wrapper.addEventListener('mouseup', () => {
isDragging = false;
pauseAuto = false;
});

wrapper.addEventListener('mouseleave', () => {
isDragging = false;
pauseAuto = false;
});

wrapper.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const dx = e.pageX - dragStartX;
wrapper.scrollLeft = scrollStart - dx;
});

wrapper.addEventListener('scroll', () =>  {
const current = wrapper.scrollLeft;
if (current = totalWidth - wrapper.clientWidth - cardWidth) {
wrapper.scrollLeft -= totalWidth / 2;
}
});

function autoScrollStep() {
if (!pauseAuto) {
wrapper.scrollBy({
left: cardWidth,
behavior: 'smooth'
});
}
setTimeout(autoScrollStep, 5000);
}

setTimeout(autoScrollStep, 500);
}

// Wait for reviews to load
function waitForReviews() {
if (window.reviewsReady) {
initReviewScroller();
} else {
setTimeout(waitForReviews, 100);
}
}

waitForReviews();< /code>



Review of our clients










css [/b]

Код: Выделить всё

/*Reviews/Testimony Section*/
.reviews-section {
background-color: #0c1624; /* dark blue background */
color: white;
padding: 120px 20px;
/* text-align: right;
min-height: 250px; */
}

.reviews-container {
max-width: 1400px;
margin: -200px auto 0 auto; /* top -20px, horizontal auto, bottom 0 */
}

.review-title {
font-size: 45px;
font-weight: bold;
margin-bottom: 15px;
text-align: center;
font-family: 'Orbitron', sans-serif;
}

.review-title-gold {
color: #Efc900; /* bright gold */
}

.review-scroll-wrapper {
position: relative;
cursor: grab;
overflow-x: auto;
scroll-behavior: smooth;
scrollbar-width: none;      /* Firefox */
-ms-overflow-style: none;   /* IE/Edge */
mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
-webkit-mask-image: linear-gradient(to right, transparent 0%, black 10%, black 90%, transparent 100%);
/* For Chrome, Safari */
&::-webkit-scrollbar {
display: none;
}
}

.review-scroll-wrapper:active {
cursor: grabbing;
}

.card-holder {
display: flex;
gap: 30px;
width: max-content;
padding: 10px;
}

.review-scroll-wrapper::before,
.review-scroll-wrapper::after {
content: "";
position: absolute;
top: 0;
width: 60px;
height: 100%;
z-index: 2;
pointer-events: none;
}

.review-scroll-wrapper::before {
left: 0;
background: linear-gradient(to right, #0c1624, transparent);
}

.review-scroll-wrapper::after {
right: 0;
background: linear-gradient(to left, #0c1624, transparent);
}

/* .card-holder::-webkit-scrollbar {
height: 8px;
}

.card-holder::-webkit-scrollbar-thumb {
background-color: #ece316;
border-radius: 10px;
} */

.review-card {
flex: 0 0 auto;                /* Prevent shrinking, enforce fixed width */
width: 320px;
background-color: #0d191f;
border: 1px solid #Efc900;
border-radius: 20px;
padding: 20px;
box-sizing: border-box;
display: flex;
flex-direction: column;
margin-top: 40px;
color: white;
}

/* Main layout: pic, text, and icon */
.review-header {
display: flex;
align-items: flex-start;
position: relative;
}

/* Profile pic */
.linkedin-pic {
flex-shrink: 0;
}

.pic-prof {
width: 50px;
height: 50px;
border-radius: 50%;
}

/* Name + role beside image */
.review-info {
margin-left: 15px;
}

/* LinkedIn icon on top right */
.linkpic-url {
position: absolute;
top: 0;
right: 0;
}

.linkedin-icon {
width: 50px;
height: 50px;
}

/* Name */
.review-name {
font-size: 18px;
font-weight: bold;
margin: 0;
font-family: 'Times New Roman', sans-serif;
}

/* Role */
.review-role {
font-size: 12px;
font-weight: bold;
margin-top: 5px;
color: #Efc900;
font-family: 'Times New Roman', sans-serif;
}

/* Quote */
.review-text {
font-size: 16px;
margin-top: 25px;
color: #bbb;
font-family: 'Times New Roman', serif;
}
также добавил CSS в соответствии с запросом ...

Подробнее здесь: https://stackoverflow.com/questions/796 ... ched-conte
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Jquery»