У меня есть клиент, который использует область выделения, я знаю, я знаю, что это устаревший тег, и, честно говоря, его не следует использовать. Это его личный веб-сайт, и он какое-то время был моим клиентом, поэтому я решил реализовать выделение, но сделать это современным способом, без использования устаревших тегов. Я видел много разных решений для этого. Обычно я использую flexbox для чего-то подобного, потому что он не зависит от javascript или jQuery, но примеры выделения flexbox часто полагаются на жестко запрограммированную ширину для расчета скорости анимации ключевых кадров.
Короче говоря, я стремлюсь создать адаптивную область, но скорость не меняется в зависимости от того, сколько контента она прокручивает (я знаю, что об этом нужно много спрашивать). Мой клиент тоже пишет массу контента (я пыталась убедить его в обратном, но он все равно это делает).
Я собрал кое-что, что очень близко к решению. Он не использует flexbox, но хорошо меняет размер, не меняя скорость... Я уже довольно близок к тому, что мне нужно. В конце концов, мне не нужно использовать flexbox, поэтому, если все остальные флажки отмечены, меня это устраивает!
Это код, который я использую:
<div class = "pizza">
<p class = "duck"><span class = "red">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span> <span class = "green">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span> <span class = "blue">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>.</p>
</div>
CSS:
.green {
color: green;
}
.red {
color: red;
}
.blue {
color: blue;
}
.pizza {
line-height: 60px;
font-size: 16px;
overflow: hidden;
position: relative;
white-space: nowrap;
}
p.duck {
animation: scroll-left 20s linear infinite;
}
@keyframes scroll-left {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(-100%, 0);
}
}
p.duck:hover {
animation-play-state: paused;
}
Рабочий пример: https://jsfiddle.net/L7kbhyg6/
Я добавил несколько интервалов, чтобы проблему было легче увидеть, но по сути не весь текст прокручивается. Я вижу красный, затем зеленый, затем шатер подпрыгивает и все начинается заново. Не знаю, как заставить его отображать весь мой контент.
Спасибо,
Джош
Я просто предпочитаю делать это только с помощью CSS, но если есть более простой способ с помощью JavaScript или jQuery, я тоже годюсь :-)
Я думаю, что в этом случае лучше всего использовать JS requestAnimationFrame.
Не могли бы вы создать пример, я не знаю, как реализовать это решение.
Чтобы обеспечить плавную прокрутку независимо от размера области просмотра или размера прокручиваемых элементов, имейте вторую копию.
Тогда преобразование происходит на -50%, а не на -100% (поэтому вторая копия попадает в левую часть, затем заменяется первой и так далее, благодаря чему она выглядит непрерывной).
Я не вижу необходимости в JS, если только вы не хотите сделать что-то более интересное и быстрое.
ОБНОВЛЕНИЕ: Хорошо, нам нужна постоянная скорость, независимо от того, что клиент помещает в область выделения.
Для этого вам понадобится пара строк JS, поскольку CSS не «знает» ширину всего текста.
Этот фрагмент позволяет CSS вычислить общую продолжительность одного цикла анимации. Это зависит от скорости, с которой вы хотите перемещать область выделения (постоянная для всех размеров области просмотра и количества текста), а также фактической ширины общей области выделения.
В p.duck установлен набор flex, justify-content, поэтому между всеми элементами имеется одинаковое расстояние и минимальная ширина, поэтому даже если клиент уменьшит количество символов до одного символа в каждом элементе, область выделения будет закрывать область просмотра.
function setUp() {
const duck = document.querySelector('.duck');
duck.style.setProperty('--w', window.getComputedStyle(duck).width.slice(0, -2));
}
window.onresize = setUp;
setUp();
.green {
color: green;
}
.red {
color: red;
}
.blue {
color: blue;
}
.pizza {
line-height: 60px;
font-size: 16px;
overflow: hidden;
position: relative;
white-space: nowrap;
}
p.duck {
display: flex;
justify-content: space-around;
--s: 10s;
/* time taken to travel 1000 px */
animation: scroll-left calc(var(--s) * var(--w) / 2000) linear infinite;
width: fit-content;
min-width: 200vw;
}
@keyframes scroll-left {
0% {
transform: translate(0, 0);
}
100% {
transform: translate(-50%, 0);
}
}
p.duck:hover {
animation-play-state: paused;
}
<div class = "pizza">
<p class = "duck">
<span class = "red">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "green">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "blue">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "red">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "green">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "blue">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
</p>
</div>
Мне нравится это решение, но проблема с этим ответом заключается в длине моего контента, он довольно длинный, поэтому скорость выделения очень высокая. Однако я могу регулировать скорость. Если я изменю содержимое прокрутки, скорость не должна измениться. Я не всегда могу быть рядом, когда область выделения обновляется, если используется небольшой объем текста, скорость области выделения снижается. Если используется большой объем текста, скорость выделения увеличивается.
Вам понадобится пара строк JS, чтобы получить постоянную скорость независимо от ширины текста, размера области просмотра и т. д. Я обновил фрагмент, чтобы показать, как это можно сделать.
Спасибо за это! Мне тоже очень нравится этот вариант :-) спасибо за добавление JS, мне нравится минималистичный подход этого решения!
Могу ли я спросить, почему выделение необходимо повторять или дублировать? Я не понимаю цели этого, кроме добавления большего контента.
Я только что увидел ваш комментарий относительно повторяющихся элементов :-) Извините, я как-то это пропустил.
Я думаю, что в этом случае лучше всего использовать JS requestAnimationFrame. – Мистер Джоджо
Не могли бы вы создать пример, я не знаю, как реализовать это решение.
ну вот оно..
[Редактировать: изменено, чтобы позаботиться о маскировке изменения размера экрана]
[Обновлено: первая версия с уникальным ID
=> кодом только для одного «выделения» на странице]
(()=> // IIFE closure for <marquee> simulation on #pizza element
{
const
pizza = document.querySelector('#pizza')
, pizza_p = document.querySelector('#pizza > p')
, mov = { pos : pizza.offsetWidth
, max : -pizza_p.offsetWidth
, pause : false
};
pizza.addEventListener('mouseenter', ()=>
{
mov.pause = true;
});
pizza.addEventListener('mouseleave', ()=>
{
mov.pause = false;
requestAnimationFrame(MarqueeMov);
});
// auto launch
pizza_p.style.left = `${mov.pos}px`;
requestAnimationFrame(MarqueeMov);
function MarqueeMov()
{
pizza_p.style.left = `${--mov.pos}px`;
if ( mov.pos < mov.max
|| mov.pos > pizza.offsetWidth // added to take care of screen resize
)
mov.pos = pizza.offsetWidth;
if (!mov.pause)
requestAnimationFrame(MarqueeMov);
}
}
)();
.green { color: green; }
.red { color: red; }
.blue { color: blue; }
#pizza {
position : relative;
font-size : 16px;
height : 32px;
padding : 0;
overflow : hidden;
white-space : nowrap;
cursor : pointer;
}
#pizza > p {
margin : 0;
position : absolute;
bottom : 0;
left : 0;
}
<div id = "pizza">
<p>
<span class = "red">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
<span class = "green">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
<span class = "blue">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
</p>
</div>
Вторая версия, позволяющая управлять несколькими полями «горизонтальной рамки» на одной странице.
(()=> // IIFE closure for <marquee> simulation for <div class = "JS-Marquee"> elements
{
const
jsMarquees = [...document.querySelectorAll('.JS-Marquee')].map( jsMx =>
{
let txtP = jsMx.querySelector('p');
return ({ boxElm : jsMx
, boxLen : jsMx.offsetWidth
, txtElm : txtP
, txtPEnd : -txtP.offsetWidth
, txtPos : jsMx.offsetWidth
, pause : false
});
});
jsMarquees.actives = jsMarquees.length;
window.addEventListener('resize', ()=>
{
jsMarquees.forEach( jsM => { jsM.boxLen = jsM.boxElm.offsetWidth });
});
jsMarquees.forEach( jsM =>
{
jsM.boxElm.addEventListener('mouseenter',()=>
{
jsM.pause = true;
--jsMarquees.actives;
});
jsM.boxElm.addEventListener('mouseleave',()=>
{
jsM.pause = false;
++jsMarquees.actives;
if (jsMarquees.actives===1)
requestAnimationFrame(MarqueeMoves);
});
})
// auto launch
jsMarquees.forEach( jsM => { jsM.txtElm.style.left = `${jsM.txtPos}px`; })
requestAnimationFrame(MarqueeMoves);
function MarqueeMoves()
{
jsMarquees.forEach( jsM =>
{
if (jsM.pause) return;
--jsM.txtPos;
if ( jsM.txtPos > jsM.boxLen
|| jsM.txtPos < jsM.txtPEnd
)
jsM.txtPos = jsM.boxLen;
jsM.txtElm.style.left = `${jsM.txtPos}px`;
});
if (jsMarquees.actives)
requestAnimationFrame(MarqueeMoves);
}
})(); // IIFE end of <marquee> JS simulation
.green { color: green; }
.red { color: red; }
.blue { color: blue; }
.JS-Marquee {
position : relative;
font-size : 16px;
height : 32px;
padding : 0;
overflow : hidden;
white-space : nowrap;
cursor : pointer;
}
.JS-Marquee > p {
margin : 0;
position : absolute;
bottom : 0;
left : 0;
}
<div class = "JS-Marquee">
<p>
<span class = "red">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
<span class = "green">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
<span class = "blue">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
</p>
</div>
<div class = "JS-Marquee">
<p>
<span class = "green">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
<span class = "blue">
Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.
</span>
</p>
</div>
Я добавил решение, используя другую библиотеку. Я реализовал ваше решение, однако, когда размер браузера был изменен, мне пришлось ждать, пока прокрутка достигнет определенной позиции, прежде чем она отобразится. Мне удалось найти что-то, что возобновляло прокрутку при изменении размера браузера. Я знаю, что вы можете это сделать, но мне не хотелось просить об этом изменении. Если вы внесете это небольшое изменение, я хотел бы воздать вам должное за ответ :-) Я просто хотел опубликовать что-то, что может помочь кому-то еще, и это действительно решит проблему, с которой я столкнулся.
@JoshRodgers Хорошо, я сделаю это. Но у меня сейчас нет свободного времени, да и выборами здесь заниматься тоже надо (!)..., придется подождать несколько часов...
@JoshRodgers Готово..
Спасибо, я очень ценю, что вы внесли в него изменения, чтобы это работало для моего проекта!
Я провел дополнительное исследование и нашел пример с использованием библиотеки gsap JS.
CSS:
.green { color: green; }
.red { color: red; }
.blue { color: blue; }
#pizza {
align-items: center;
display: flex;
height: 40px;
}
#pizza .wrap {
overflow: hidden;
white-space: nowrap;
width: 100%;
}
#pizza .content {
display: inline-block;
white-space: nowrap;
}
/* Media */
@media screen and (min-width: 1000px) {
#pizza {
justify-content: center;
}
}
HTML:
<div id = "pizza">
<div class = "wrap">
<div class = "content">
<span class = "red">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "green">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>
<span class = "blue">Start Lorem ipsum dolor sit amet consectetur adipisicing elit. Ut sed placeat aperiam quod nostrum itaque blanditiis soluta! Aliquid fuga molestias aut magni, pariatur doloremque, voluptas ipsa nobis ipsum voluptatibus end.</span>.
</div>
</div>
</div>
ЯС:
<script src = "https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.2/gsap.min.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
const marqueeContent = document.querySelector("#pizza .content");
const marqueeContainer = document.querySelector("#pizza .wrap");
let marqueeAnimation;
function updateMarquee() {
const contentWidth = marqueeContent.scrollWidth;
const containerWidth = marqueeContainer.clientWidth;
const totalWidth = contentWidth + containerWidth;
const speedFactor = 100; // Speed factor for faster scrolling
const duration = totalWidth / speedFactor;
// Kill any existing animation
if (marqueeAnimation) {
marqueeAnimation.kill();
}
// Create a new animation
marqueeAnimation = gsap.fromTo(marqueeContent,
{ x: containerWidth },
{ x: -contentWidth, ease: "linear", repeat: -1, duration: duration }
);
}
// Initial call
updateMarquee();
// Update the marquee on resize
window.addEventListener("resize", updateMarquee);
// Pause animation on hover
marqueeContainer.addEventListener("mouseenter", () => gsap.globalTimeline.pause());
marqueeContainer.addEventListener("mouseleave", () => gsap.globalTimeline.resume());
});
</script>
Это дает мне возможность добавлять или уменьшать контент без ущерба для скорости. Этот также отзывчив и перезапускает прокрутку при изменении размера браузера.
Спасибо,
Джош
Я не понимаю, только с CSS и без javascript или jQuery?