I'm using the Swiper by iDangero.us and I'm having difficulty creating an infinite loop of multi-row slides. I have 30 images which I need to group into 3 rows of 5 over 2 slides. Setting loop renders the slides in the grid that I want to achieve and clicking the arrows slides between each one correctly. But I need the slides to be infinite, going back to the original 15 images on the first slide once I reach the end. Setting loop to true breaks this.
What am I doing wrong? Is it possible to do this with this plugin?
Snippet and JSFiddle below.
Any help would be appreciated.
Thanks :)
var swiper = new Swiper('.swiper-container', {
// loop: true,
prevButton: '.swiper-button-prev',
nextButton: '.swiper-button-next',
slidesPerView: 5,
spaceBetween: 15,
slidesPerColumn: 3,
slidesPerColumnFill: 'row',
slidesPerGroup: 15
});
* {
box-sizing: border-box;
}
html,
body {
margin: 20px 0;
padding: 0;
font-family: Arial, sans-serif;
}
.container {
width: 100%;
max-width: 1170px;
padding: 0 15px;
margin: 0 auto;
}
.img-responsive {
display: block;
max-width: 100%;
height: auto;
}
.swiper-slide span {
position: absolute;
top: 15px;
left: 15px;
background-color: black;
color: white;
padding: 6px;
display: block;
font-size: 20px;
width: 35px;
height: 35px;
text-align: center;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/css/swiper.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.1/js/swiper.min.js"></script>
<div class="container">
<div class="swiper-container">
<div class="swiper-wrapper">
<script>
for (i = 1; i <= 30; i++) {
document.write('<div class="swiper-slide"><img src="http://placehold.it/240x240" class="img-responsive"><span>' + i + '</span></div>');
}
</script>
</div>
<div class="swiper-button-prev swiper-button-white"></div>
<div class="swiper-button-next swiper-button-white"></div>
</div>
</div>
JS Fiddle: http://codepen.io/aethyrion/pen/mRVwzE
What you want is called Recursion. Create a function that re-instantiates your slides and then loops through your slides, and then at the end of the function call your function again. This will recursively call your loop of the same slides.
However you'll want to have some stopping point I would think. If you don't you'll run out of memory eventually.
Create a function, that does this loop and then add it to the script tag in your html.
Related
I'm using Swiper API to create a mobile-friendly slider but I need to find a way to make the swiper.update() method reposition the slides smoothly and not instantly placing them upon removing a slide.
Right now when removing a slide and calling swiper.update to reposition the remaining slides, it just reposition the remaining slides instantly. How can I make it run the same way but with a smoother reposition of the slides?
Link for Swiper API: https://swiperjs.com/swiper-api
Initialization of Swiper
swiper = new Swiper(".mySwiper", {
slidesPerView: 3,
allowTouchMove: true,
allowSlideNext: true,
allowSlidePrev: true,
spaceBetween: 5,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
pagination: {
el: ".swiper-pagination",
clickable: true,
},
});
swiper.setTransition(this, 0.3);
EDIT: As requested I created an example code to run and reproduce the issue. As you can see with the code provided below when you remove a slide the transition that repositions the remaining slides is instant. I need to find a way to make it smoother. To position the remaining slides slower and not instantly. Is there a way to do that?
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css"/>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
<style>
html, body {
padding: 0;
margin: 0;
}
body {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.swiper {
width: 100%;
height: 500px;
margin-left: 10px !important;
margin-right: 10px !important;
box-sizing: border-box;
}
.swiper-slide {
background-size: cover !important;
border: 2px solid darkgray;
box-sizing: border-box;
text-align: center;
font-size: 18px;
background: #fff;
/* Center slide text vertically */
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
transition: 0.3s all ease;
}
.swiper-slide img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.removeSlideBtn {
margin-top: 50px;
line-height: 30px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="swiper">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
<div class="swiper-slide">Slide 5</div>
...
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
</div>
<button class="removeSlideBtn" onclick="RemoveSlide();">Remove Slide</button>
</body>
<script>
var swiper = new Swiper(".swiper", {
slidesPerView: 3,
allowTouchMove: true,
allowSlideNext: true,
allowSlidePrev: true,
spaceBetween: 5,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
pagination: {
el: ".swiper-pagination",
clickable: true,
},
});
swiper.setTransition(this, 300);
function RemoveSlide() {
var slide = Math.floor(Math.random() * swiper.slides.length);
swiper.removeSlide(slide);
}
</script>
</html>
Turns out, it could be achieved without using any of the API's methods and properties. The way the swiper is displaying the slides is by using flex display.
So I managed to achieve a smooth transition upon removing slides by using the following jsfiddle code.
Link for JsFiddle: https://jsfiddle.net/MadLittleMods/EM4xL/
<style>
.remove-item {
flex: 1;
-webkit-animation: flexShrink 500ms ease forwards;
-o-animation: flexShrink 500ms ease forwards;
animation: flexShrink 500ms ease forwards;
}
#keyframes flexShrink {
to {
flex: .01;
flex: .00001;
}
}
#keyframes flexGrow {
to {
flex: 1;
}
}
</style>
<script>
swiper.slides[i].classList.add('remove-item');
swiper.slides[i].addEventListener('animationend', function () {
swiper.removeSlide(i);
});
</script>
Everything works fine if the slider is the only element in the page, but add an extra one after the swiper element and the active slide is always the first one. Adding height: 100% to .swiper-container makes it work fine, but then when you go to the end of the page and back to top, footer is fixed. Anyone has a workaround?
Example:
https://stackblitz.com/edit/swiper-demo-15-free-mode-no-fixed-positions-losg12?file=style.css
Your issue only looks like a bug (But it's not).
The footer is not fixed but when you hover A area you scroll the swiper mousewheel: true (not the page).
One Solution/Idea:
[1]Disable/Enable scroll [2] if footer is visible.
Part 1: Use mousewheel API methods:
mySwiper.mousewheel.disable();
mySwiper.mousewheel.enable();
Part 2: Use Intersection Observer API (If the footer is visible disable mousewheel).Read more: How to Know when an Element Gets Visible in the Screen During Scrolling
var observer = new IntersectionObserver(function(entries) {
// isIntersecting is true when element and viewport are overlapping
// isIntersecting is false when element and viewport don't overlap
if(entries[0].isIntersecting === true){
console.log('Element has just become visible in screen');
swiper.mousewheel.disable();
}
else{
swiper.mousewheel.enable();
}
}, { threshold: [0] });
observer.observe(document.querySelector("#footer"));
Snippet
var swiper = new Swiper('.swiper-container', {
freeMode: true,
mousewheel: {
invert: false,
},
// If we need pagination
pagination: {
el: '.swiper-pagination',
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
scrollbar: {
el: '.swiper-scrollbar',
draggable: true,
}
});
var observer = new IntersectionObserver(function(entries) {
// isIntersecting is true when element and viewport are overlapping
// isIntersecting is false when element and viewport don't overlap
if(entries[0].isIntersecting === true){
console.log('Element has just become visible in screen');
swiper.mousewheel.disable();
document.getElementById("status").innerHTML = "mousewheel.disable!";
}
else{
swiper.mousewheel.enable();
document.getElementById("status").innerHTML = "mousewheel.enable!";
}
}, { threshold: [0.1] });
/* threshold is a number between 0 and 1, that represents the viewable area of the target element in the screen. For example, 0 represents no area of element is visible. A value of 0.10 represents about 10% area is viewable in screen. Value of 1 means element is fully viewable in screen.*/
observer.observe(document.querySelector("#footer"));
html,
body {
position: relative;
height: 100%;
}
body {
background: #eee;
font-family: Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 14px;
color: #000;
margin: 0;
padding: 0;
}
.swiper-container {
width: 100%;
height: 100%;
}
.swiper-slide {
text-align: center;
font-size: 18px;
background: #fff;
/* Center slide text vertically */
display: flex;
justify-content: center;
align-items: center;
}
nav{
min-height: 50px;
display: flex;
justify-content: center;
align-items: center;
background: lightgray;
}
footer{
min-height: 500px;
display: flex;
justify-content: center;
align-items: center;
background: brown;
color: white;
}
#message{
position: fixed;
z-index: 100;
padding: 10px;
background: brown;
color: white;
border: 2px solid gray;
}
#status{
background: yellow;
color: red;
padding: 5px;
}
<span id="message">Status: <b id="status">True</b></span>
<link rel="stylesheet" href="https://unpkg.com/swiper/swiper-bundle.min.css">
<nav>Navbar</nav>
<!-- Slider main container -->
<main class="swiper-container">
<!-- Additional required wrapper -->
<div class="swiper-wrapper">
<!-- Slides -->
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
<!-- If we need navigation buttons -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- If we need scrollbar -->
<div class="swiper-scrollbar"></div>
</main>
<footer id="footer">Footer</footer>
<script src="https://unpkg.com/swiper/swiper-bundle.min.js"></script>
Codepen: https://codepen.io/ezra_siton/pen/JjRbrJM
Fullpage.js
One more idea is to use a full-page scroll plugin (More control):
https://alvarotrigo.com/fullPage/
https://alvarotrigo.com/pagePiling/
Related: fullpage.js: normal scroll for particular sections?
Hi I have made a slider using slick. I cant for the life of me figure out how to change the background colour of my header when the slides change (which is positioned over the top of the slider).
I am wanting to change the header background to black and text color to white when the second slide becomes visible.
I have gone round in circles all morning trying to figure out a way to do this, I have even tried to duplicate the header and use inside each slide but that brought me many more problems.
Is this at all possible? And if so how? I am hoping somebody can point me in the right direction! thanks
My code as follows:
HTML
<header>hi this is the vavigation</header>
<div class="sliderlastvid">
<div class="videocontainer">
<div class="video">
<div class="video-titre">slide1</div>
</div>
</div>
<div class="videocontainer" style="background: white;">
<div class="video">
<div class="video-titre">slide2</div>
</div>
</div>
<div class="videocontainer" style="background: yellow;">
<div class="video">
<img src="" alt=""></img>
<div class="video-titre">Slide3</div>
</div>
</div>
CSS
body {background: navy; margin: 0; }
header { width: 100%; height: 30px; color: pink; position: absolute; top: 0; left: 0; border-bottom: 1px solid; z-index: 99; }
.slider {
width: auto;
margin: 30px 50px 50px;
}
.slick-slide {
background: #081449;
color: white;
padding: 20px 0;
font-size: 30px;
font-family: "Arial", "Helvetica";
text-align: center;
img { display: inline-block; }
}
JQUERY
$(document).ready(function () {
$('.sliderlastvid').slick({
infinite: true,
slidesToShow: 1,
slidesToScroll: 1
});
});
Please see my fiddle: jsfiddle
<div class="video-titre" id="secondSlide">slide2</div>
#secondSlide {
background: black;
color: white;
}
Works, but is not a very pretty solution.
The .slick-slide class is overwriting all your other classes somehow, can't figure out how to make the secondSlide class overwrite it except with an id.
You need to use before slide change, this is a slick slider function that you can use, here is a little code snippet:
$('.sliderlastvid').on('beforeChange', function(event, slick, currentSlide, nextSlide){
console.log(currentSlide);
});
As you can see from the console log, it will drop out the current slide, you can then use jQuery to target your header and drop a class on to it.
Then use css to target the header & change the colour quick sort of example:
$('.sliderlastvid').on('beforeChange', function(event, slick, currentSlide, nextSlide){
$('header').addClass('slide-' + currentSlide);
});
Target with css
header {
background: white;
}
header.slide-1 {
background: red;
}
Hope this helps.
I've been playing with "marginLeft: "100%"" but that only moves the div off the screen entirely. I want the div, onClick, to float:right against the edge of the right side of the screen.
JSFiddle:
https://jsfiddle.net/487r8qza/
HTML
<div id="footer">
<one id="one">
</one>
<two id="two">
</two>
<three id="three">
</three>
</div>
JavaScript
$("#footer").click(function(){
$("#one").animate({
marginLeft: "+=900px",
}, 2000 );
$("#two").animate({
marginLeft: "+=900px",
}, 800 );
$("#three").animate({
marginLeft: "+=900px",
}, 333 );
});
$("#three").click(function() {
$("#three").animate({
marginLeft: "100%"} , 1000
);
});
CSS
#footer {
margin: 0;
padding: 0;
float: left;
width: 100%;
max-width: 100%;
height: 115px;
background-color: #4a4a4a;
}
one {
margin: 0;
padding: 0;
float: left;
width: 300px;
background-color: #070707;
height: 115px;
margin-left: -900px;
}
one,two,three {
text-align: center;
color: white;
font-family: "Raleway", Arial, Helvetica, Trebuchet MS, Tahoma, sans-serif;
font-weight: bold;
font-size: 16px;
line-height: 115px;
}
one:hover {
background: black;
margin: 0;
padding: 0;
width: 300px;
height: 115px;
float: left;
transition: all 0.3s ease-out;
cursor: pointer;
}
two:hover {
background: black;
margin: 0;
padding: 0;
width: 300px;
height: 115px;
float: left;
transition: all 0.3s ease-out;
cursor: pointer;
}
three:hover {
background: black;
margin: 0;
padding: 0;
width: 300px;
height: 115px;
float: left;
transition: all 0.3s ease-out;
cursor: pointer;
}
two {
margin: 0;
padding: 0;
float: left;
width: 300px;
background-color: #1a1a1a;
height: 115px;
margin-left: -900px;
}
three {
margin: 0;
padding: 0;
float: left;
width: 300px;
background-color: #2c2c2c;
height: 115px;
margin-left: -900px;
}
Sorry if it took this long, something came up. Right, so I got it working. Hope this helps
JSFIDDLE
As for CSS, I kept it as simple as possible. The trick here is to make your DIVs display inline-block, so that at the very start, they are neatly stacked next to each other. You will also want to have them all be float right.
CSS:
.box-container{
width: 100%;
height: 115px;
position: relative;
overflow: hidden;
}
.box-item{
width: 300px;
height: 115px;
position: relative;
display: inline-block;
float: right;
cursor: pointer;
}
.b0{
background: #7888D9;
}
.b1{
background: #76D54E;
}
.b2{
background: #DF7B41;
}
Next, in your HTML, you need to give each DIVs the same classname, which will simplify the Jquery click event. Finally, we will also give our first DIV a classname of "current". This will control which DIV must move and which DIV must wait and stay idle as long as the one beside him hasn't moved. You'll understand soon enough.
HTML:
<div class="box-container">
<div class="box-item b0 current">
Box 1
</div>
<div class="box-item b1">
Box 2
</div>
<div class="box-item b2">
Box 3
</div>
</div>
Finally, as for the Jquery, this is where it gets a bit complicated, I'll try to explain the best I can. Bare in mind that math is not quite my forte. Since our DIVS all float right in the CSS, well, they will all be stacked to the right (of course). To counter that and position them to the left, we need to give each DIV a right position. This position will be some kind of offset. To get this number, we need to multiply the width of a DIV by the total number of DIVs. After that, we must subtract this number to the total width of our DIVs' container (basically the browser width).
As for the click event, we must first check if the DIV we clicked has our "current" classname. If it does, we move it, if not, we don't. The easy part is moving them. By resetting a DIV's right value to 0, each one will slide accordingly to the right with our animate event. Once this is done, we switch the "current" classname to the next DIV. We then increment a counter. This will help to see if all DIVs has been moved.
Once all DIVs have been moved to the right, there is an IF statement that will check our counter and see if it is greater than our total number of DIVs. If it is, the sliding motion is inverted and all DIV's will return to the left. In the same manner, if the clicked element is not the current DIV, it will not move. if it is, it will move back to the left. When all DIV's have been move back in default position, ou counter is reset and our "current" classname is reassigned to the very first DIV.
The resize function is not optimal, but it deals with any responsive issue you could face. It will reset all DIVs to the left and recalculate the offset, so that each DIV never slide offscreen. Needs a little work, but it's better than nothing for now.
JQUERY:
var $boxWidth;
var $screenWidth;
var $offsetRight;
var $count = 0;
$(function () {
$boxWidth = $('.box-item').width();
$screenWidth = $('.box-container').width();
$offsetRight = $screenWidth - ($boxWidth*$('.box-item').length);
$('.box-item').css('right',$offsetRight);
$('.box-item').click(function(event) {
if($(this).hasClass('current')){
if($count < $('.box-item').length){
$(this).animate({
right: "0px",
}, 2000, function(){
$count++;
$(this).removeClass('current');
if($count < $('.box-item').length){
$(this).next().addClass('current');
}
else{
$(this).addClass('current');
}
});
}
else{
$(this).animate({
right: $offsetRight,
}, 2000, function(){
$count++;
$(this).removeClass('current');
console.log($count);
if($count < ($('.box-item').length*2)){
$(this).prev().addClass('current');
}
else{
$(this).addClass('current');
$count = 0;
}
});
}
}
});
window.onresize = myResize;
myResize();
});
function myResize(){
$screenWidth = $('.box-container').width();
$offsetRight = $screenWidth - ($boxWidth*$('.box-item').length);
$('.box-item').each(function(){
$(this).css('right',$offsetRight);
});
$('.box-item').eq(0).addClass('current');
$count = 0;
}
I am totally new to jssor, and a less than novice coder. I just discovered the jssor carousel slider today, and I have been fooling around with it for probably 10 hours.
I have managed to solve most of my issues by reviewing other questions on this site, but I have been running around is circles for the past several hours.
First off to clarify, I love the Slider and it's ability to scale, but I need it to be more basic, and somewhat stay where I put it. :) I think after many hours I have got it to stay in one place just under my navigation, and it seems to be good there (although I probably did the the worse way possible.
My main issue now is that it seems to work perfect in IE, and on my native android cell browser, but on Chrome and Safari, the carousel won't keep its height. My photos are # 200x180, and in IE11, they appear to be the proper size. In the other browsers, the slider is only showing to be about 1/2" high.
My pages are PHP, and I call the slider page onto my home page with an "Include" statement (sorry, I seriously green). Now the code I pulled off of jssor.com does have some html references, so that could be giving me some issues, as well.
You can check it out live at (SilverScreenCollectibles.com). I've also pasted the code below (that I am using on my PHP page) so that you can see how bad I am at this.
I would really appreciate any assistance that anyone out there could offer.
Thanks,
Bill
<!DOCTYPE html>
<html>
<head>
<div class="span9">
<script src="assets/js/jquery-1.8.2.min.js" type="text/javascript"> </script>
<script src="assets/js/jquery.carouFredSel-6.0.4-packed.js" type="text/javascript"></script>
<script type="text/javascript">
$(function() {
// create carousel
$('#carousel').carouFredSel({
responsive: false,
items: {
width: 200,
height: '90%',
visible: 8
},
auto: {
items: 1
},
prev: '#prev',
next: '#next'
});
// re-position the carousel, vertically centered
var $elems = $('#wrapper, #prev, #next'),
$image = $('#carousel img:first')
$(window).bind( 'resize.example', function() {
var height = $image.outerHeight( true );
$elems
.height( height )
// .css( 'marginTop', -( height/2 ) );
}).trigger( 'resize.example' );
});
</script>
<style type="text/css">
html, body {
height: 100%;
padding: 0;
margin: 0;
}
body {
min-height: 50px;
position: relative;
}
body h3 {
font-family: Arial, Geneva, SunSans-Regular, sans-serif;
font-size: 20px;
text-align: center;
color: #999;
margin: 0;
padding-top: 50px;
}
body * {
font-family: Arial, Geneva, SunSans-Regular, sans-serif;
font-size: 14px;
color: #333;
line-height: 22px;
}
#wrapper, #prev, #next {
border-top: 1px solid #999;
border-bottom: 1px solid #999;
height: 170px;
position: absolute;
/* top: 35%;*/
margin-top: 0px;
}
#wrapper {
width: 80%;
left: 10%;
overflow: hidden;
box-shadow: 0 0 10px #ccc;
}
#carousel img {
margin: 10px 5px;
border: none;
display: block;
float: left;
}
#prev, #next {
background: center center no-repeat #ccc;
width: 5%;
}
#prev:hover, #next:hover {
background-color: #bbb;
}
#prev {
background-image: url( assets/slide-imgs/form/gui-prev.png );
left: 0;
}
#next {
background-image: url( assets/slide-imgs/form/gui-next.png );
right: 0;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="carousel">
<img src="cw4/images/product_full/LC-ChainedFrt.jpg" alt="Image1" width="212" height="180" onclick="window.location.replace('http://silverscreencollectibles.com/product.php?product=110');" />
</div>
</div>
<a id="prev" href="#"></a>
<a id="next" href="#"></a>
</div>
</body>