Концепции ползунка бесконечности
Интересно, каковы наилучшие (хороший читаемый код, практика вредоносного кода, многократное использование) для создания бесконечного изображения-Loop-Slider для веб-сайта с использованием JavaScript/jQuery? Я не знаю, как закодировать слайд-шоу, но какой чертеж соответствует указанным выше требованиям.
Основное внимание в моем вопросе заключается в том, как упорядочить фотографии, чтобы получить впечатление бесконечного цикла Slider.
Посмотрев код из разных слайдеров, я столкнулся с двумя решениями:
-изменять z-индекс всех изображений каждый раз, когда отображается следующее/предыдущее изображение.
- изменить положение изображения в DOM.
Но изучить и понять код других очень трудоемко - вот почему я задаю этот вопрос: -)
Ответы
Ответ 1
tl; dr - Пример: http://jsbin.com/ufoceq/8/
Простой подход к созданию бесконечного слайдера изображения без особых усилий заключается в следующем: позвольте сказать, для простоты, что у вас есть <n>
изображения для скольжения в цикле, так что после n
th следующий для визуализации - это 1
st (и наоборот).
Идея состоит в том, чтобы создать клон первого и последнего изображений, чтобы
- клон последнего изображения добавляется до первого;
- клон первого изображения добавляется после последнего.
Каким бы ни был объем ваших изображений, вам нужно будет добавить не более 2 клонированных элементов.
Снова для простоты скажем, что все изображения 100px
широкие, и они завернуты в контейнер, который вы перемещаете влево/вправо в обрезанную маску с помощью overflow: hidden
. Затем все изображения можно легко выровнять в строке с display: inline-block
и white-space: nowrap
, установленными в контейнере (с flexbox
теперь это еще проще).
Для n = 4
Структура DOM будет примерно такой:
offset(px) 0 100 200 300 400 500
images | 4c | 1 | 2 | 3 | 4 | 1c
/* ^^ ^^
[ Clone of the last image ] [ Clone of the 1st image ]
*/
В начале ваш контейнер будет располагаться с left: -100px
(или также margin-left: -100px
или даже лучше (в зависимости от производительности) transform: translateX(-100px)
), поэтому ползунок может отображать первое изображение. Чтобы переключиться с изображения на другой, вам необходимо применить анимацию javascript по тому же свойству, которое вы ранее выбрали.
Когда ваш слайдер в настоящее время находится на 4 th изображении, вам нужно переключиться с изображения 4
на 1c
, поэтому идея состоит в том, чтобы выполнить обратный вызов в конце анимации, скоро переместите свою ползунок на реальное смещение изображения 1 st (например, вы установите left: -100px
в контейнер)
Это аналогично, когда ваш слайдер в настоящее время расположен на элементе 1 st: для показа предыдущего изображения вам просто нужно выполнить анимацию с изображения 1
до 4c
, и когда анимация завершен, вы просто перемещаете контейнер, так что слайдер неподвижно расположен на смещении изображения 4 th (например, вы устанавливаете left: -400px
в контейнер).
Вы можете увидеть эффект на приведенном выше скрипте: это минимальный код js/jquery
, который я использовал (конечно, код может быть даже оптимизирован, поэтому ширина элементов не жестко закодирована в script)
$(function() {
var gallery = $('#gallery ul'),
items = gallery.find('li'),
len = items.length,
current = 1, /* the item we're currently looking */
first = items.filter(':first'),
last = items.filter(':last'),
triggers = $('button');
/* 1. Cloning first and last item */
first.before(last.clone(true));
last.after(first.clone(true));
/* 2. Set button handlers */
triggers.on('click', function() {
var cycle, delta;
if (gallery.is(':not(:animated)')) {
cycle = false;
delta = (this.id === "prev")? -1 : 1;
/* in the example buttons have id "prev" or "next" */
gallery.animate({ left: "+=" + (-100 * delta) }, function() {
current += delta;
/**
* we're cycling the slider when the the value of "current"
* variable (after increment/decrement) is 0 or when it exceeds
* the initial gallery length
*/
cycle = !!(current === 0 || current > len);
if (cycle) {
/* we switched from image 1 to 4-cloned or
from image 4 to 1-cloned */
current = (current === 0)? len : 1;
gallery.css({left: -100 * current });
}
});
}
});
});
Как уже упоминалось ранее, это решение не требует особого труда и говорит о производительности, сравнивая этот подход с обычным слайдером без цикла, требуется только сделать две дополнительные вставки DOM при инициализации ползунка и некоторые (довольно тривиальные ) дополнительная логика для управления обратным/прямым контуром.
Я не знаю, существует ли более простой или лучший подход, но надеюсь, что это все равно поможет.
Примечание: если вам нужна также отзывчивая галерея, возможно этот ответ может помочь также
Ответ 2
Я только что создал ползунок элемента: проверьте его:
https://github.com/lingtalfi/jItemSlider/blob/master/README.md
Это 600 строк кода, возможно, вы можете просто просмотреть его.
Идея, стоящая за ней, вдохновлена слайдером netflix (по состоянию на 2016-02-24).
В основном, он использует трансляции трансляции css, потому что это самые быстрые /slickest в браузере.
http://eng.wealthfront.com/2015/05/19/performant-css-animations/
Теперь базовая концепция движения слайдов заключается в том, что вы показываете только текущий видимый срез,
но у вас также есть один невидимый фрагмент слева, а другой невидимый срез справа.
И у вас также есть два дополнительных элемента: по одному с каждой стороны, чтобы ваши объекты выглядели следующим образом:
предыдущие элементы - предыдущий дополнительный элемент - основные предметы - следующий дополнительный элемент - следующие предметы
Только основные элементы видны.
Дополнительные элементы частично видны.
Предыдущий и следующий элементы невидимы.
Подробнее здесь:
https://github.com/lingtalfi/jItemSlider/blob/master/doc/conception.md
Теперь, когда вы скользите вправо (например), вы в основном добавляете больше предметов в нужную сторону,
а затем удалите их с левой стороны.
Этот метод является самым большим, с чем я столкнулся до сих пор, потому что вы не имеете дело с длинным списком элементов (используя
клонирование без удаления невидимых элементов), что может сделать вашу анимацию медленнее.
Примечание: моя первая попытка этого слайдера была фактически клонирована без удаления, она работает, но мне она не нравится:
https://github.com/lingtalfi/jInfiniteSlider
Кроме того, это элемент, основанный (а не на основе пикселей), и, в конце концов, то, что пользователь ожидает, потому что
все всегда выровнено, как и должно быть.
Ответ 3
Большое спасибо этой статье!
У меня было обновление и использование выше кода.
Надеюсь, это поможет всем.
Плохой разработчик.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Directive slider</title>
<style>
/* 四联切换焦点图 */
.slides-wrapper{ position: relative; width: 100%; margin: 10px 0; }
.gallery { position: relative; width: 1200px; height: 180px; overflow:hidden; }
.gallery ul { font-size: 0; white-space: nowrap; position: absolute; top: 0; left: -1200px; margin: 0; padding: 0; }
.gallery li { display: inline-block; vertical-align: top; width: 1200px; height: 180px; white-space: normal; }
.gallery li img{ width: 298px; height:180px; padding: 1px; }
.gallery .arrow { background: url(/shop/templates/default/images/home_bg.png) no-repeat; background-size: 150px 223px; width: 35px; height: 70px; position: absolute; z-index: 2; top: 50px; cursor: pointer; opacity: 0;}
.gallery .prev { background-position: 1px -92px; left: 0;}
.gallery .next { background-position: -30px -92px; right: 0px;}
</style>
<style type="text/css">
.demo_wrapper{
margin: 0 auto;
width: 1200px;
}
.demo_wrapper .title{
text-align: center;
}
</style>
</head>
<body>
<div class="demo_wrapper">
<div class="title">
<h1>Directive slider (Published by fenmingyu)</h1>
</div>
<!-- demo content -->
<div class="slides-wrapper">
<div class="gallery" id="top_sale_gallery">
<ul>
<li>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-1.jpg?234" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-2.jpg?752" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-3.jpg?320" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-4.jpg?365" alt=""></a>
</li>
<li>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-1.jpg?852" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-2.jpg?746" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-3.jpg?525" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-4.jpg?550" alt=""></a>
</li>
</ul>
<div class='arrow prev'></div>
<div class='arrow next'></div>
</div>
<div class="gallery" id="top_goods_gallery">
<ul>
<li>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-1.jpg?793" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-2.jpg?180" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-3.jpg?550" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-3-4.jpg?851" alt=""></a>
</li>
<li>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-1.jpg?234" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-2.jpg?752" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-3.jpg?320" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-1-4.jpg?365" alt=""></a>
</li>
<li>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-1.jpg?852" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-2.jpg?746" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-3.jpg?525" alt=""></a>
<a href="" target="_blank" title="" style="opacity: 1;"><img src="http://imgserv.5thmedia.cn/upload_test/shop/editor/web-102-104-2-4.jpg?550" alt=""></a>
</li>
</ul>
<div class='arrow prev'></div>
<div class='arrow next'></div>
</div>
<div style="clear: both;"></div>
</div>
</div>
</body>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
$(function() {
$.fn.gallery = function(settings) {
var defaults = {
time: 3000,
direction:1
};
var settings = $.extend(defaults, settings);
var gallery_wrapper = $(this),
gallery = gallery_wrapper.find('ul'),
items = gallery.find('li'),
len = items.length,
current = 1, /* the current item we're looking */
first = items.filter(':first'),
last = items.filter(':last'),
w = gallery.find('li').width(),
triggers = gallery_wrapper.find('.arrow');
var show_slide = function(direction,w){
gallery.animate({ left: "+=" + (-w * direction) }, function() {
current += direction;
/**
* we're cycling the slider when the the value of "current"
* variable (after increment/decrement) is 0 or when it exceeds
* the initial gallery length
*/
cycle = !!(current === 0 || current > len);
if (cycle) {
/* we switched from image 1 to 4-cloned or
from image 4 to 1-cloned */
current = (current === 0)? len : 1;
gallery.css({left: -w * current });
}
});
};
var picTimer = setInterval(function() {
show_slide(settings.direction,w);
},
settings.time);
return this.each(function(){
/* 1. Cloning first and last item */
first.before(last.clone(true));
last.after(first.clone(true));
/* 2. Set button handlers */
triggers.on('click', function() {
if (gallery.is(':not(:animated)')) {
var cycle = false;
settings.direction = ($(this).hasClass('prev'))? -1 : 1;
/* in the example buttons have id "prev" or "next" */
show_slide(settings.direction,w);
}
clearInterval(picTimer);
picTimer = setInterval(function() {
show_slide(settings.direction,w);
},
settings.time);
});
/* hover show arrows*/
show_slide(settings.direction,w);
gallery_wrapper.hover(function() {
$(this).find(".arrow").css("opacity", 0.0).stop(true, false).animate({
"opacity": "0.3"
},
300);
},function(){
$(this).find(".arrow").css("opacity", 0.3).stop(true, false).animate({
"opacity": "0"
},
300);
});
});
};
$('#top_goods_gallery.gallery').gallery();
$('#top_sale_gallery.gallery').gallery({
time: 5000,
direction:-1
});
});
</script>
</html>