How can I make a Swiper slider like App Store? - javascript

I want make a slider with Swiperjs like Apple App Store carousel (you can see at Games tab).
I tried to make it in Vue Swiper (a package for vue) here:
HTML code:
<div id="app">
<h1>Slider</h1>
<!-- Slider main container -->
<vue-swiper url="http://www.google.com"></vue-swiper>
<div>
CSS:
ody {
background: #f0f0f0;
font-family: Tahoma;
}
#app{
width:400px;
height:700px;
background:white;
margin: auto;
border-radius: 10px;
}
h1 {
padding: 30px 10px 0 10px;
}
.swiper-container {
padding-top: 10px;
width: 100%;
height: 180px;
}
.swiper-slide {
width: 300px;
border-radius: 5px;
text-align: center;
color: #fff;
background: url('https://i.vimeocdn.com/video/376634544.jpg?mw=1920&mh=1080&q=70');
background-size: cover;
}
Javascript code:
ue.component('vue-swiper', {
data: function() {
return {
imageItems:[]
};
},
props:['url'],
mounted: function () {
var mySwiper = new Swiper ('.swiper-container', {
slidesPerView: 'auto',
spaceBetween: 10,
centeredSlides:true,
direction: 'horizontal',
loop: false,
// pagination: '.swiper-pagination',
// paginationType:'bullets',
nextButton: false,
prevButton: false,
});
},
template:`
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide"></div>
<div class="swiper-slide"></div>
<div class="swiper-slide"></div>
</div>
// <div class="swiper-pagination"></div>
</div>
`
});
var app = new Vue({
el: '#app',
data: {
},
})
How can I make the first slide float to left and the last slide float to right, like this:
In my code, the first slide and the last slide are centered.

I think I really resolved my issue.
On mounted, when Swiper initiate, I add custom style
on: {
init: function () {
document.getElementById('wrapper').style.transform = "translate3d(10px, 0px, 0px)"
},
}
On touchend (swiper event)
mySwiper.on('touchEnd', function () {
setTimeout(() => {
if (mySwiper.activeIndex == 0) {
document.getElementById('wrapper').style.transform = "translate3d(10px, 0px, 0px)"
}
if (mySwiper.activeIndex == mySwiper.slides.length - 1) {
var translate_last = mySwiper.snapGrid[mySwiper.activeIndex] + mySwiper.snapGrid[0] + 10;
var translate_style = 'translate3d(-' + translate_last + 'px, 0px, 0px)';
document.getElementById('wrapper').style.transform = translate_style
}
}, 10);
});
Check my new Codepen

u fire the event only at the end.
if u slide back it wouldn't transform slides back to initialtion-part.
change it to mySwiper.on('progress', ...
swiper.on('progress', function(){
setTimeout(() => {
if (swiper.activeIndex == 0) {
$(".swiper-slide").css('transform', 'translate3d(125px, 0px, 0px)');
}
if (swiper.activeIndex == swiper.slides.length - 1) {
var translate_last = swiper.snapGrid[swiper.activeIndex] + swiper.snapGrid[0] + 10;
var translate_style = 'translate3d(-' + translate_last + 'px, 0px, 0px)';
$(".swiper-slide").css('transform', translate_style);
}
}, 10);
swiper.on('reachEnd', function(){
$(".swiper-slide").css('transform', 'translate3d(0px, 0px, 0px)');
});
});

Related

Responsive `slide toggle` to slide from the bottom in website for mobile

I have a function slide toggle slides from right to left to show information in my webside. It works fine on windows but when I open my website on mobile my slide toggle covers the whole website screen. How can I change the slide toggle to slide from the bottom and be responsive for mobile interface or less than 750px.
This is my code for slide toggle:
var easing = 1;
var animation_speed = 200;
var slider_width;
var is_collapsed = true;
function slideToggle() {
is_collapsed = $('#btn').css("margin-right") == slider_width + "px" && !$('#btn').is(':animated');
var sign = (is_collapsed) ? '-' : '+';
if (!$('#btn').is(':animated')) {
if (easing) $('.willSlide').animate({
"margin-right": sign + '=' + slider_width
}, animation_speed);
else $('.willSlide').animate({
"margin-right": sign + '=' + slider_width
}, animation_speed);
}
(is_collapsed) ? $('.willSlide').removeClass('expanded'): $('.willSlide').addClass('expanded');
}
//function to open slide
function slideOpen() {
//if is_collapsed is true, animate div and open slider
if (is_collapsed) {
var sign = '+'
$('.willSlide').animate({
"margin-right": sign + '=' + slider_width
}, animation_speed);
//add expanded class to button when opened
$('.willSlide').addClass('expanded')
//set is_collapsed to false so it won't close slider on additional clicks
is_collapsed = false
}
}
$(document).ready(function() {
slider_width = $('#content').width(); //get width automaticly
$('#btn').click(slideToggle);
});
#content {
position: fixed;
height: 100%;
background: rgb(97, 97, 97);
width: 450px;
right: 0px;
margin-right: -450px;
}
#btn {
position: fixed;
width: 100px;
right: 0px;
background: rgb(117, 231, 117);
top: 100px;
border-radius: 5px 0px 0 5px;
color: #fff;
text-align: center;
padding: 40px 0;
cursor: pointer
}
.expandedTxt {
display: none
}
#btn.expanded .expandedTxt {
display: block
}
#btn.expanded .click {
display: none
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="willSlide" id='content'></div>
<div class="willSlide" id='btn'>
<span class="click">open</span>
<span class="expandedTxt">close</span>
</div>
Here is demo for slide toggle

Customize the Slider Swiper

Made a slider "Swiper". To the right of it is the tag "h1", the text of which needs to be changed depending on what the current picture is.
If you press the right button, then the indexes are 2, 3, 4, and if the left one is 0, 1, 2.
It is unclear why this is happening.
I tried to use the "document.getElementsByClassName("left-element")" class for searching, but it doesn't work that way.
Works only with "document.getElementById("box")".
Also, at initial loading, the picture tries to be drawn at 100% in width, but then collapses to the 50% I need. How to remove this effect?
var swiper = new Swiper('.swiper-container', {
effect: 'cube',
grabCursor: true,
slidesPerView: 'auto',
cubeEffect: {
shadow: true,
slideShadows: true,
shadowOffset: 50,
shadowScale: 0.3,
centerSlidesBounds: true,
},
direction: 'horizontal',
loop: true,
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
pagination: {
el: '.swiper-pagination',
},
on: {
init: function () {
},
},
});
swiper.on('slideChange', function () {
let name = swiper.activeIndex;
/*
let element = document.getElementsByClassName("left-element");
alert(name);
*/
let element = document.getElementById("box");
element.innerHTML = (name) + " " + "Index";
});
.main {
position: fixed;
padding: 16px;
margin-top:40px;
width: 50%;
}
.swiper-button-prev{
left: 2%;
}
.swiper-button-next{
left: 92%;
}
.swiper-pagination-bullets.swiper-pagination-horizontal {
width: 100%;
bottom: -25%;
}
.left-element {
background: silver;
display: inline-block;
position: absolute;
left: 100%;
width: 80%;
margin-top: 0;
}
h1.left-element {
width: 80%;
height: 90%
}
img{
width: 100%;
height: 100%;
}
<link rel="stylesheet" href="https://unpkg.com/swiper#7/swiper-bundle.min.css">
<script src="https://unpkg.com/swiper#7/swiper-bundle.min.js"></script>
<div class="main">
<h1 class="left-element" id="box">Empty index</h1>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">
<img src="https://www.fonstola.ru/large/201309/119067.jpg">
</div>
<div class="swiper-slide">
<img src="https://www.fonstola.ru/large/201408/148243.jpg">
</div>
<div class="swiper-slide">
<img src="https://www.fonstola.ru/large/201111/50599.jpg">
</div>
</div>
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-pagination"></div>
</div>
</div>
I've removed some of your effect on the Swiper, but feel free to add it back (cause I tried to set up the default Swiper again on the Swiper Docs :D ).
And remember to change the <div class="swiper-container"> to <div class="swiper">
Here's the code in Javascript:
const swiper = new Swiper(".swiper-container", {
// Install modules,
direction: 'horizontal',
initialSlide: 0,
loop: true,
speed: 500,
navigation: {
nextEl: ".swiper-button-next",
prevEl: ".swiper-button-prev",
},
// ...
});
swiper.on('slideChange', () => {
let swiperIndex = swiper.realIndex
console.log('Swiper index right now: ', swiperIndex)
let element = document.getElementById("box")
element.innerHTML = (swiperIndex) + " " + "Index";
})
Whenever the slide change, it'll assign the realIndex to swiperIndex
Here's the fiddle for you to have a clearer look: Fiddle

How to change swipe direction in swiper.js?

I'm struggling with changing swipe direction when I rotate my swiper on 90deg. So in the beginning by default it has horizontal direction. When clicking on slide I'm rotating "swiper-container" making it full screen . So it still has swiping direction from left to right , but I need to change from top to bottom without changing in params direction to vertical .
const topSwiper = new Swiper(this.DOMTopSwiper.current, {
spaceBetween: 0,
observer: true,
observeParents: true,
observeSlideChildren: true,
direction: "vertical",
navigation: {
nextEl: ".top-swiper-button-next",
prevEl: ".top-swiper-button-prev",
},
pagination: {
el: ".zoom-amount-slides",
type: "fraction",
},
})
Destroy previous Swiper and reinitialize Swiper giving the direction value. Here is doc
DEMO
let isVertical = true,
direction = 'vertical';
let swiper = initSwiper(direction);
function initSwiper(direction) {
return new Swiper('.swiper-container', {
spaceBetween: 50,
pagination: {
el: '.swiper-pagination',
clickable: true,
},
direction: direction
});
}
function changeDirection() {
isVertical = !isVertical;
direction = isVertical ? 'vertical' : 'horizontal';
let slideIndex = swiper.activeIndex;
swiper.destroy(true, true);
swiper = initSwiper(direction);
swiper.slideTo(slideIndex,0);
}
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: 400px;
height: 400px;
}
.swiper-slide {
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;
}
<!-- Link Swiper's CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/css/swiper.min.css">
<!-- Swiper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/4.4.6/js/swiper.js"></script>
<button onclick='changeDirection()'>Change Direction</button>
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
For who's searching this in 2022, now is possible to update direction using swiper.changeDirection('vertical'); // or horizontal
complete example here:
https://stackblitz.com/edit/swiper-demo-43-change-direction
Try my solution.
//Tested in Swiper 7.2.0
/**
* Insert to your page
*/
var rotate90Swiper = (function (swiper, optIsRotate90) {
var isRoate90 = !!optIsRotate90
swiper.___touches = {}
swiper.___touches.currentX = swiper.touches.currentX
Object.defineProperty(swiper.touches, 'currentX', {
set: function (v) {
if (!isRoate90) {
swiper.___touches.currentX = v
} else {
swiper.___touches.currentY = v
}
},
get: function () {
return swiper.___touches.currentX
}
})
swiper.___touches.currentY = swiper.touches.currentY
Object.defineProperty(swiper.touches, 'currentY', {
set: function (v) {
if (!isRoate90) {
swiper.___touches.currentY = v
} else {
swiper.___touches.currentX = v
}
},
get: function () {
return swiper.___touches.currentY
}
})
return function (b) {
isRoate90 = b
}
})
/**
* How to use
*/
var setRotate90 = rotate90Swiper(YourSwiperInstance, defaultIsRotate90)
setRotate90(false) // swiper rotate 90deg
setRotate90(true) //normal swiper
Quick edit if you need to rotate at 180 your swiperjs
var rotate180Swiper = (function (swiper, optIsRotate180) {
var isRoate180 = !!optIsRotate180
swiper.___touches = {}
swiper.___touches.currentX = swiper.touches.currentX
Object.defineProperty(swiper.touches, 'currentX', {
set: function (v) {
if (!isRoate180) {
swiper.___touches.currentX = -v
} else {
swiper.___touches.currentX = v
}
},
get: function () {
return swiper.___touches.currentX
}
})
return function (b) {
isRoate180 = b
}
})
Just simply add reverseDirection: true, in the autoplay
autoplay: {
delay: 0,
disableOnInteraction: true,
reverseDirection: true,
},

Clear a GSAP TimelineMax animation after reversing it

Basically I have a structure like this, my goal is to animate 4 divs so that when you click on one the other slide out and when you click on the container they return to their initial positions.
var TL = new TimelineMax;
$('.quater').on('click', function () {
$faders = $('.container').find('.quater').not(this),
$faders.each(function () {
TL.to($(this), 1, {autoAlpha:0, x:50}, 0);
});
});
$('.container').on('click', function () {
TL.reverse();
TL.clear();
});
The problem is that if I omit the "TL.clear();" it will work just for the first ".quater" div clicked, if i put in the "TL.clear();" the animation will not reverse anymore.
jsFiddle.
Snippet:
var container = document.querySelector('.container');
var items = document.querySelectorAll('.item');
var duration = 0.6;
var ease = Expo.easeOut;
var numItems = items.length;
var i;
container.addEventListener('click', onContainerClicked, false);
for (i = 0; i < numItems; i += 1) {
(function(index){
items[index].timeline = new TimelineMax({ paused: true });
items[index].timeline.fromTo(items[index], duration, { y: 0, autoAlpha: 0.4 }, { y: -104, autoAlpha: 1, ease: ease });
items[index].addEventListener('click', onItemClicked, false);
}(i));
}
function onContainerClicked() { reverseAll(); }
function onItemClicked(e) {
reverseAll();
e.target.timeline.play();
}
function reverseAll() {
for (i = 0; i < numItems; i += 1) { items[i].timeline.reverse(); }
}
html, body {
margin: 0;
padding: 0;
}
.container {
background: #444;
width: 512px;
height: 104px;
}
.item {
float: left;
margin: 2px 0 0 2px;
width: 100px;
height: 100px;
}
.item:nth-child(odd) { background: #0cc; }
.item:nth-child(even) { background: #cc0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<div class="container"></div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>
<div class="item"> </div>

jQuery: Div elements are not showing up

I am adapting the Coverflow technique to work with a div. Following is the html:
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<style type="text/css" media="screen">
body,html {
margin: 0;
padding: 0;
background: #000;
height: 100%;
color: #eee;
font-family: Arial;
font-size: 10px;
}
div.magnifyme {
height: 80px;
padding: 80px;
position: absolute;
top: 0px;
left: 0px;
width: 2000px;
}
div.wrapper {
margin: 0px;
height: 470px;
/*border: 2px solid #999;*/
overflow: hidden;
padding-left: 40px;
right: 1px;
width: 824px;
position: relative;
}
div.container {position: relative; width: 854px; height: 480px; background: #000; margin: auto;}
div.nav {position: absolute; top: 10px; width: 20%; height: 10%; right: 1px; }
div.magnifyme div {
position: absolute;
width: 300px;
height: 280px;
float: left;
margin: 5px;
position: relative;
border: 2px solid #999;
background: #500;
}
</style>
<script type="text/javascript" src="jquery-1.3.2.js"></script>
<script type="text/javascript" src="ui.coverflow.js"></script>
<script type="text/javascript" src="ui.core.js"></script>
<script type="text/javascript">
$(function() {
$("div.magnifyme").coverflow();
$("#add").click(function() {
$(".magnifyme").append("<div id=\"div5\">hello world</div>");
$("div.magnifyme").coverflow();
});
});
</script>
</head>
<body>
<div class="container">
<div class="wrapper">
<div class="magnifyme">
<div id="div0">This is div 0</div>
<div id="div1">This is div 1</div>
<div id="div2">This is div 2</div>
<div id="div3">This is div 3</div>
<div id="div4">This is div 4</div>
</div>
</div>
<div class="nav">
<button type="button" id="add">Add to Deck</button>
</div>
</div>
</body>
</html>
The coverflow function (included as a js file in the head section) is here. When I click the button, I was expecting it to add a DIV to the already present deck. For some reason, it doesn't show the newly added DIV. I tried calling the coverflow() function after I added the new element but that didn't work either. The modified coverflow function is given here:
;(function($){
$.widget("ui.coverflow", {
init: function() {
var self = this;
this.items = $(this.options.items, this.element).bind("click", function() {
self.moveTo(this);
//$("div.slider").slider("moveTo", self.current, null, true);
});
this.itemWidth = this.items.outerWidth(true);
this.current = 0; //Start item
this.refresh(1, 0, this.current);
this.element.css("left",
(-this.current * this.itemWidth/2)
+ (this.element.parent()[0].offsetWidth/2 - this.itemWidth/2) //Center the items container
- (parseInt(this.element.css("paddingLeft")) || 0) //Subtract the padding of the items container
);
},
moveTo: function(item) {
this.previous = this.current;
this.current = !isNaN(parseInt(item)) ? parseInt(item) : this.items.index(item);
if(this.previous == this.current) return false; //Don't animate when clicking on the same item
var self = this, to = Math.abs(self.previous-self.current) <=1 ? self.previous : self.current+(self.previous < self.current ? -1 : 1);
$.fx.step.coverflow = function(fx) {
self.refresh(fx.now, to, self.current);
};
this.element.stop().animate({
coverflow: 1,
left: (
(-this.current * this.itemWidth/2)
+ (this.element.parent()[0].offsetWidth/2 - this.itemWidth/2) //Center the items container
- (parseInt(this.element.css("paddingLeft")) || 0) //Subtract the padding of the items container
)
}, {
duration: 1000,
easing: "easeOutQuint"
});
/*current = this.current;
$("[id^=div]").each(function() {
if(this.id != "div"+current) {
console.info(this.id + " Current: " + current);
$(this).fadeTo( 'slow', 0.1);
}
});*/
},
refresh: function(state,from,to) {
var self = this, offset = null;
this.items.each(function(i) {
var side = (i == to && from-to < 0 ) || i-to > 0 ? "left" : "right";
var mod = i == to ? (1-state) : ( i == from ? state : 1 );
var before = (i > from && i != to);
$(this).css({
webkitTransform: "matrix(1,"+(mod * (side == "right" ? -0.5 : 0.5))+",0,1,0,0) scale("+(1+((1-mod)*0.5))+")",
left: (
(-i * (self.itemWidth/2))
+ (side == "right"? -self.itemWidth/2 : self.itemWidth/2) * mod //For the space in the middle
),
zIndex: self.items.length + (side == "left" ? to-i : i-to)
});
if(!$.browser.msie)
$(this).css("opacity", 1 - Math.abs((side == "left" ? to-i : i-to))/2);
});
}
});
$.extend($.ui.coverflow, {
defaults: {
items: "> *"
}
});
})(jQuery);
One thing I did notice is that after clicking the button for about 5-10 times, the elements show up but not along with the already present divs but rather below them. I am guessing that this has something to do with the CSS of the magnifyme class (2000px), but I am not sure what it is. Is there any way I can make this work?
You need to write an additional function for the coverflow widget:
add: function(el) {
var self = this;
this.element.append(el)
this.options.items = $('> *', this.element);
this.items = $(this.options.items, this.element).bind("click", function() {
self.moveTo(this);
});
this.itemWidth = this.items.outerWidth(true);
this.moveTo(this.items.length-1);
},
and then call it like so:
$("#add").click(function() {
$("div.magnifyme").coverflow('add', "<div></div>");
});
First, you need to add a references to the jQuery UI core, and it also appears that it requires the jQuery slider plugin.
Second, in your click event you're doing a location.reload, which is refreshing the page from the server, resetting any changes you had made to the page. (if you make the DIVs much smaller you can see one flash in before the page is reloaded).
You are getting a js error on the page -- "$.widget is not a function" because you didn't include the jqueryUI library. http://jqueryui.com/
Also if you remove the location.reload line, your code will work, however, I would rewrite that script block like this, so that everything clearly runs when the document is ready:
<script type="text/javascript">
$(document).ready(function() {
$("div.magnifyme").coverflow();
$("#add").click(function() {
$(".magnifyme").append("<div id=\"div5\">hello world</div>");
$("div.magnifyme").coverflow();
});
});
</script>

Categories