Я пытаюсь воссоздать этот стиль с веб-сайта: https://www.polestar.com/us/polestar-1/ В третьем разделе, который называется «Точность», я хочу воссоздать такой стиль. Например, как он изменил цвет текста абзаца с белого на rgb (211, 188, 141).. и удалил липкую позицию, когда он закончился. изменение цвета текста..
Как это работает?
Я пытался использовать тот же метод, что и они, используя разные элементы для каждой буквы и скрывая белую букву буквы при прокрутке, но я не уверен с js
Пожалуйста, посмотрите stackoverflow.com/help/minimal-reproducible-example Мы очень рады помочь отладить ваш код, но мы не здесь, чтобы писать его с нуля.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Пример. Я попытался тщательно прокомментировать все, что происходит в JS.
// at what yPosition should we stick?
const stickyAtYPos = 100;
// minumum time between coloring a character
const minTimeColorCharMs = 50;
// browser, do not remember scroll positions for me
history.scrollRestoration = "manual";
// a flag that is set later (yPos to lock the scroll at)
// + which sticky that is currently locked
// + lastTime we colored a span
let lockedAt, lockedSticky, lastColorTime = 0;
// divide text inside .stickyColor elements
// into one span per character
[...document.querySelectorAll('.stickyColor')]
.forEach(x => x.innerHTML = '<span>'
+ x.innerText.trim().split('')
.join('</span><span>') + '</span>');
// listen to the scroll event of the window
window.addEventListener('scroll', e => {
// if scroll is locked and the user scrolls down
// and time enough between coloring characters
if (lockedAt && window.scrollY > lockedAt &&
(!lastColorTime || Date.now() - lastColorTime > minTimeColorCharMs)) {
// find the first uncolored span
let span = [...lockedSticky.querySelectorAll('span')]
.find(x => !x.classList.contains('newColor'));
// color it and remember when we did that
span && span.classList.add('newColor') || (lastColorTime = Date.now());
// if no more spans to color, release the scroll lock
!span && (lockedAt = false);
}
// if locked, then don't allow scroll down
lockedAt && window.scrollY > lockedAt && window.scrollTo(0, lockedAt);
// get the stickycolor elements
let stickies = [...document.querySelectorAll('.stickyColor')];
// loop through them
stickies.forEach((sticky, i) => {
// if we have a lock already do nothing
if (lockedAt) { return; }
// check if the sticky should stick :)
if (sticky.getBoundingClientRect().top < stickyAtYPos
&& !sticky.classList.contains('locked')) {
// remember y pos to lock scroll at + locked sticky
lockedAt = window.scrollY;
lockedSticky = sticky;
// add class signaling that we are locked
sticky.classList.add('locked');
}
});
});body {
background-color: black;
margin: 20px 30px;
color: white;
}
p.stickyColor {
font-family: 'Verdana';
margin-top: 200px;
top: 100px;
transition: color 1s;
}
p.stickyColor span {
color: white;
transition: color 0.1s;
}
p.stickyColor span.newColor {
color: rgb(192, 143, 35);
}
.big {
height: 1000px;
}<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<title>Sticky Color</title>
</head>
<body>
<p>Please scroll down...</p>
<p class = "stickyColor">Hello there! Nice to see you!</p>
<p class = "stickyColor">Let's play a game of colors...</p>
<p class = "stickyColor">Goodbye everyone! That's all.</p>
<div class = "big"></div>
</body>
</html>Примечание. Хотя вы не можете видеть его здесь, скрипт должен быть включен в качестве последнего элемента в тело, поскольку все элементы должны быть в DOM до его запуска, и я не жду, когда документ будет готов...
Хороший. Можете ли вы сбросить его при прокрутке назад?
Не будет ли сброс его при прокрутке назад очень раздражающим с точки зрения пользователей? (Я бы так подумал...) Постоянная блокировка прокрутки, когда вы хотите двигаться вверх и вниз по содержимому...
Это может быть правдой
@mplungjan: Это выполнимо, но я уже потратил слишком много времени на это ... так что не я. (Слишком много экранного времени, предупреждение... ;))
Да, я тоже ответил и был не совсем доволен, поэтому удалил свой ответ, так как ваш был лучше. У меня было два набора пролетов, и я сделал const index = Math.floor(scrollTop / elementHeight); if (normalSpan) normalSpan.style.opacity = (i < index ? 1 : 0); if (colorSpan) colorSpan.style.opacity = (i >= index ? 1 : 0);
@mplungjan: Ваш ответ был хорошей отправной точкой (я проголосовал за него)
Что меня не совсем устраивает в моем, так это то, что при быстрой прокрутке он «трясется» (хуже в этом маленьком «тестовом окне», чем в большом окне просмотра, но: чтобы исправить это, вам нужно добавить прослушиватели событий на колесо, touchstart и touchmove, установите для них значение {passive: false} и вызовите event.preventDefault, но в то же время прочитайте, в каком направлении пользователь хотел выполнить прокрутку (от колеса e.yDelta, при касании, посмотрев на измененный указатель...) Тоже много работы прямо сейчас Но это устранило бы дрожь, я бы сделал это, если буду жить с профессиональной версией.
Пожалуйста, посетите справочный центр , совершите тур , чтобы узнать, что и Как спросить . Проведите небольшое исследование, поищите связанные темы на SO; если вы застряли, опубликуйте минимально воспроизводимый пример вашей попытки, отметив ввод и ожидаемый результат, желательно в Stacksnippet