How to make a 3D carousal Inner rotation view? - javascript

I wanted to make a 3d rotating carousel like in the stack snippet, but required is a view from inside like in the image below. How can i achieve this?
window.addEventListener('load', () => {
var carousels = document.querySelectorAll('.carousel');
for (var i = 0; i < carousels.length; i++) {
carousel(carousels[i]);
}
});
function carousel(root) {
var
figure = root.querySelector('figure'),
nav = root.querySelector('nav'),
images = figure.children,
n = images.length,
gap = root.dataset.gap || 0,
bfc = 'bfc' in root.dataset,
theta = 2 * Math.PI / n,
currImage = 0;
setupCarousel(n, parseFloat(getComputedStyle(images[0]).width));
window.addEventListener('resize', () => {
setupCarousel(n, parseFloat(getComputedStyle(images[0]).width))
});
setupNavigation();
function setupCarousel(n, s) {
var apothem = s / (2 * Math.tan(Math.PI / n));
figure.style.transformOrigin = `50% 50% ${- apothem}px`;
for (var i = 0; i < n; i++) {
images[i].style.padding = `${gap}px`;
}
for (i = 1; i < n; i++) {
images[i].style.transformOrigin = `50% 50% ${- apothem}px`;
images[i].style.transform = `rotateY(${i * theta}rad)`;
}
if (bfc) {
for (i = 0; i < n; i++) {
images[i].style.backfaceVisibility = 'hidden';
}
}
rotateCarousel(currImage);
}
function setupNavigation() {
nav.addEventListener('click', onClick, true);
function onClick(e) {
e.stopPropagation();
var t = e.target;
if (t.tagName.toUpperCase() != 'BUTTON') {
return;
}
if (t.classList.contains('next')) {
currImage++;
}
else {
currImage--;
}
rotateCarousel(currImage);
}
}
function rotateCarousel(imageIndex) {
figure.style.transform = `rotateY(${imageIndex * -theta}rad)`;
}
}
body {
margin: 0;
font-family: 'Roboto', sans-serif;
font-size: 16px;
}
h1 {
text-align: center;
margin-bottom: 1.5em;
}
h2 {
text-align: center;
color: #555;
margin-bottom: 0;
}
.carousel {
padding: 20px;
perspective: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
}
.carousel>* {
flex: 0 0 auto;
}
.carousel figure {
margin: 0;
width: 40%;
transform-style: preserve-3d;
transition: transform 0.5s;
}
.carousel figure img {
width: 100%;
box-sizing: border-box;
padding: 0 0px;
}
.carousel figure img:not(:first-of-type) {
position: absolute;
left: 0;
top: 0;
}
.carousel nav {
display: flex;
justify-content: center;
margin: 20px 0 0;
}
.carousel nav button {
flex: 0 0 auto;
margin: 0 5px;
cursor: pointer;
color: #333;
background: none;
border: 1px solid;
letter-spacing: 1px;
padding: 5px 10px;
}
<h2>Eight images, with 80px gap</h2>
<div class="carousel" data-gap="80">
<figure>
<img src="https://source.unsplash.com/VkwRmha1_tI/800x533" alt="">
<img src="https://source.unsplash.com/EbuaKnSm8Zw/800x533" alt="">
<img src="https://source.unsplash.com/kG38b7CFzTY/800x533" alt="">
<img src="https://source.unsplash.com/nvzvOPQW0gc/800x533" alt="">
<img src="https://source.unsplash.com/mCg0ZgD7BgU/800x533" alt="">
<img src="https://source.unsplash.com/1FWICvPQdkY/800x533" alt="">
<img src="https://source.unsplash.com/bjhrzvzZeq4/800x533" alt="">
<img src="https://source.unsplash.com/7mUXaBBrhoA/800x533" alt="">
</figure>
<nav>
<button class="nav prev">Prev</button>
<button class="nav next">Next</button>
</nav>
</div>

The carousel needs to be rotated and translated in the opposite direction to make it an inner rotation view.
The transform-origin sets the center of the carousel. The first two numbers are x and y, which just center the carousel on the screen. The third number is z which determines whether the carousel is moved towards the screen or away from the screen. The negative sign on apothem is removed to pull it out of the screen so the center becomes closer to the camera and achieves the inner carousel. backface-visibility needs to be always set to hidden because there might be images behind the camera now. Then to fix the rotation direction with the next button, * -theta is changed to positive.
window.addEventListener('load', () => {
var carousels = document.querySelectorAll('.carousel');
for (var i = 0; i < carousels.length; i++) {
carousel(carousels[i]);
}
});
function carousel(root) {
var
figure = root.querySelector('figure'),
nav = root.querySelector('nav'),
images = figure.children,
n = images.length,
gap = root.dataset.gap || 0,
theta = 2 * Math.PI / n,
currImage = 0;
setupCarousel(n, parseFloat(getComputedStyle(images[0]).width));
window.addEventListener('resize', () => {
setupCarousel(n, parseFloat(getComputedStyle(images[0]).width))
});
setupNavigation();
function setupCarousel(n, s) {
var apothem = s / (2 * Math.tan(Math.PI / n));
figure.style.transformOrigin = `50% 50% ${apothem}px`;
for (var i = 0; i < n; i++) {
images[i].style.padding = `${gap}px`;
}
for (i = 1; i < n; i++) {
images[i].style.transformOrigin = `50% 50% ${apothem}px`;
images[i].style.transform = `rotateY(${i * theta}rad)`;
}
rotateCarousel(currImage);
}
function setupNavigation() {
nav.addEventListener('click', onClick, true);
function onClick(e) {
e.stopPropagation();
var t = e.target;
if (t.tagName.toUpperCase() != 'BUTTON') {
return;
}
if (t.classList.contains('next')) {
currImage++;
}
else {
currImage--;
}
rotateCarousel(currImage);
}
}
function rotateCarousel(imageIndex) {
figure.style.transform = `rotateY(${imageIndex * theta}rad)`;
}
}
body {
margin: 0;
font-family: 'Roboto', sans-serif;
font-size: 16px;
}
h1 {
text-align: center;
margin-bottom: 1.5em;
}
h2 {
text-align: center;
color: #555;
margin-bottom: 0;
}
.carousel {
padding: 20px;
perspective: 500px;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
}
.carousel>* {
flex: 0 0 auto;
}
.carousel figure {
margin: 0;
width: 40%;
transform-style: preserve-3d;
transition: transform 0.5s;
}
.carousel figure img {
width: 100%;
box-sizing: border-box;
padding: 0 0px;
backface-visibility: hidden;
}
.carousel figure img:not(:first-of-type) {
position: absolute;
left: 0;
top: 0;
}
.carousel nav {
display: flex;
justify-content: center;
margin: 20px 0 0;
}
.carousel nav button {
flex: 0 0 auto;
margin: 0 5px;
cursor: pointer;
color: #333;
background: none;
border: 1px solid;
letter-spacing: 1px;
padding: 5px 10px;
}
<h2>Eight images, with 80px gap</h2>
<div class="carousel" data-gap="80">
<figure>
<img src="https://source.unsplash.com/VkwRmha1_tI/800x533" alt="">
<img src="https://source.unsplash.com/EbuaKnSm8Zw/800x533" alt="">
<img src="https://source.unsplash.com/kG38b7CFzTY/800x533" alt="">
<img src="https://source.unsplash.com/nvzvOPQW0gc/800x533" alt="">
<img src="https://source.unsplash.com/mCg0ZgD7BgU/800x533" alt="">
<img src="https://source.unsplash.com/1FWICvPQdkY/800x533" alt="">
<img src="https://source.unsplash.com/bjhrzvzZeq4/800x533" alt="">
<img src="https://source.unsplash.com/7mUXaBBrhoA/800x533" alt="">
</figure>
<nav>
<button class="nav prev">Prev</button>
<button class="nav next">Next</button>
</nav>
</div>

Related

How to rotate and scale cards while swiping

As I'm trying to make a carousel that rotates I wonder how to move the cards rotated and it scales from a minimum of 0.8(left and right cards) and a maximum scale of 1(center card) when the user keeps swiping
Scale:
left = 0.8
center = 1
right = 0.8
I'm trying to solve on how to rotate them using transform and z-index properties. The cards will also rotate however I'm still trying to make a formula on how to make a function that makes the cards rotate
Any alternative solutions are accepted The animation is
similar to this carousel from codepen however it doesn't swipe Carousel Rotate
const CONTAINER_FLEX = document.querySelector('.container-flex');
const items = document.querySelectorAll('.item');
let touchStartX = 0;
let touchMoveX = 0;
let count = 0;
let current_translate = 0;
let previous_translate = 0;
CONTAINER_FLEX.addEventListener('touchstart', (event) => {
touchStartX = event.touches[0].pageX;
});
CONTAINER_FLEX.addEventListener('touchmove', (event) => {
touchMoveX = event.touches[0].pageX;
current_translate = previous_translate + (touchMoveX - touchStartX);
console.log(current_translate);
items[1].style.transform = `translateX(${current_translate}px)`;
});
CONTAINER_FLEX.addEventListener('touchend', () => {
current_translate = touchMoveX - touchStartX;
previous_translate = current_translate;
});
*,
::before,
::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.5;
background-color: #131b24;
}
.main-container {
padding: 30px 0;
height: 300px;
width: 900px;
border-top: 1px solid #444;
border-bottom: 1px solid #444;
overflow: hidden;
background-color: white;
}
.container-flex {
height: 100%;
display: flex;
transition: transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1);
}
.item {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-width: 300px;
}
.item h1 {
font-size: 40px;
color: white;
}
/* ITEMS */
.item-1 {
background-color: #2c3e50;
transform: translateX(100px);
z-index: 1;
}
.item-2 {
background-color: #3498db;
z-index: 2;
}
.item-3 {
background-color: #1abc9c;
transform: translateX(-100px);
z-index: 1;
}
<div class="main-container">
<div class="container-flex" id="container-flex">
<div class="item item-1">
<h1>1</h1>
</div>
<div class="item item-2">
<h1>2</h1>
</div>
<div class="item item-3">
<h1>3</h1>
</div>
</div>
</div>
Here is a working example https://jsfiddle.net/4ue5sgm9/3/
I wonder how to move the cards when it goes from 0 to 200 however
Have all your cards in an array.
var cards = [ thing1, thing2, thing3];
Use % - modulus operator, it's the secret for cycling back to the beginning
cardIndex = (cardIndex + 1) % cards.length
Copied from the chat. I made it verbose for clarity
scrollLeft() {
nextIndex = items.indexOf(displayed[2])
nextIndex = ++nextIndex % items.length-1
displayed = items[nextIndex]
nextIndex = ++nextIndex % items.length-1;
displayed.push( items[nextIndex] );
nextIndex = ++nextIndex % items.length-1;
displayed.push( items[nextIndex] )
}
P.S. Write and iterator for items array. An iterator stops after the last item. An iterator is why "for (x in thisArray)" works. BUT write the next() function to return "% this.length-1" instead => now you have a never-ending looper. All that code just above goes away.

Problem with creating loop for carousel - back to first element

I'm having issue with creating loop inside carousel so it will go back to first card after reaching last one on a click event - rightButton.
So far carousel stops when reach last card.
const carousel = document.querySelector("[data-target='carousel']");
const card = carousel.querySelector("[data-target='card']");
const leftButton = document.querySelector("[data-action='slideLeft']");
const rightButton = document.querySelector("[data-action='slideRight']");
const carouselWidth = carousel.offsetWidth;
const cardStyle = card.currentStyle || window.getComputedStyle(card)
const cardMarginRight = Number(cardStyle.marginRight.match(/\d+/g)[0]);
const cardCount = carousel.querySelectorAll("[data-target='card']").length;
let offset = 0;
const maxX = -((cardCount / 3) * carouselWidth +
(cardMarginRight * (cardCount / 3)) -
carouselWidth - cardMarginRight);
leftButton.addEventListener("click", function() {
if (offset !== 0) {
offset += carouselWidth + cardMarginRight;
carousel.style.transform = `translateX(${offset}px)`;
}
})
rightButton.addEventListener("click", function() {
if (offset !== maxX) {
offset -= carouselWidth + cardMarginRight;
carousel.style.transform = `translateX(${offset}px)`;
}
})
.wrapper {
height: 100px;
width: 432px;
position: relative;
overflow: hidden;
margin: 0 auto;
}
.button-wrapper {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
}
.carousel {
margin: 0;
padding: 0;
list-style: none;
width: 100%;
display: flex;
position: absolute;
left: 0;
transition: all 1s ease;
}
.card {
background: black;
min-width: 100px;
height: 100px;
margin-right: 1rem;
display: inline-block;
}
span {
color:#ffffff;
}
<div class="wrapper">
<ul class="carousel" data-target="carousel">
<li class="card" data-target="card"><span>1</span></li>
<li class="card" data-target="card"><span>2</span></li>
<li class="card" data-target="card"><span>3</span></li>
<li class="card" data-target="card"><span>4</span></li>
<li class="card" data-target="card"><span>5</span></li>
<li class="card" data-target="card"><span>6</span></li>
<li class="card" data-target="card"><span>7</span></li>
<li class="card" data-target="card"><span>8</span></li>
<li class="card" data-target="card"><span>9</span></li>
</ul>
<div class="button-wrapper">
<button data-action="slideLeft">L</button>
<button data-action="slideRight">R</button>
</div>
</div>
Code available on jsfiddle:
https://jsfiddle.net/2qv6mpb1/
Is there a chance that someone could point me in a proper direction on how to achieve that? I
You need to handle when your offset is equal to the maxX, and reset the offset back to zero.
rightButton.addEventListener("click", function() {
if (offset !== maxX) {
offset -= carouselWidth + cardMarginRight;
carousel.style.transform = `translateX(${offset}px)`;
} else {
offset = 0;
carousel.style.transform = `translateX(${offset}px)`;
}
})
This will use fixed widths with a gap of 10px (see CSS) - (to make it responsive you should modify the px used in JS to translate in % steps).
Also, it will work for any number of .Carousel elements on the page.
Also, simplify the HTML markup as per below, which is more consistent with the CSS for a better modular methodology
const Carousel = (EL) => {
const CARDS = EL.querySelector(".Carousel-cards");
const PREV = EL.querySelector(".Carousel-prev");
const NEXT = EL.querySelector(".Carousel-next");
const w = EL.offsetWidth;
const d = CARDS.offsetWidth - w; // widths diff
let x = 0;
const anim = (dir) => {
x += w * dir;
x = Math.min(d, Math.max(0, x));
CARDS.style.transform = `translateX(-${x}px)`;
};
PREV.addEventListener("click", () => anim(-1))
NEXT.addEventListener("click", () => anim(+1))
};
document.querySelectorAll(".Carousel").forEach(Carousel);
.Carousel {
height: 100px;
width: 430px; /* (100px * 4) + (10px * 3gap) */
position: relative;
overflow: hidden;
margin: 0 auto;
}
.Carousel-nav {
width: 100%;
height: 100%;
display: flex;
justify-content: space-between;
align-items: center;
position: absolute;
}
.Carousel-cards {
position: absolute;
left: 0;
margin: 0;
padding: 0;
list-style: none;
display: flex;
transition: transform 1s ease;
gap: 10px;
}
.Carousel-cards > * {
background: black;
min-width: 100px;
height: 100px;
}
span {
color: #ffffff;
}
<div class="Carousel">
<ul class="Carousel-cards">
<li><span>1</span></li>
<li><span>2</span></li>
<li><span>3</span></li>
<li><span>4</span></li>
<li><span>5</span></li>
<li><span>6</span></li>
<li><span>7</span></li>
<li><span>8</span></li>
<li><span>9</span></li>
</ul>
<div class="Carousel-nav">
<button class="Carousel-prev">L</button>
<button class="Carousel-next">R</button>
</div>
</div>
There's more to improve, i.e: makes no sense to have buttons if the content does not require animating, or one of the buttons depending if a direction is completed.

How to make an image slider using JavaScript with user generated images?

I am working on a project which:
Asks the user to choose images from their device
The selected images would show up in the image slider
const slider = document.querySelector('.slider');
// load user chosen files
fileInp.addEventListener('input', (e) =>
{
const files = e.target.files;
for (let file of files) {
const img = new Image();
const reader = new FileReader();
reader.addEventListener('load', (e) =>
{
img.src = e.target.result;
slider.appendChild(img);
img.classList.add('slide');
})
reader.readAsDataURL(file);
}
})
// slider
const slides = document.querySelectorAll('.slide');
let counter = 0;
slides.forEach((slide, index) =>
{
slide.style.left =
`${index * 100}%`
})
nextBtn.onclick = () => {
counter++;
move();
}
prevBtn.onclick = () => {
counter--;
move();
}
function move() {
if (counter <= 0) {
counter = slides.length - 1;
}
if (counter === slides.length) {
counter = 0;
}
slides.forEach((slide, index) => {
slide.style.transform =
`translateX(-${counter * 100}%)`
})
}
#import url("https://fonts.googleapis.com/css2?family=Nunito:wght#400;900");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Nunito", sans-serif;
}
body {
display: grid;
place-items: center;
height: 100vh;
}
.box {
display: flex;
flex-direction: column;
padding: 1rem;
gap: 1rem;
}
.slider {
min-width: 300px;
min-height: 70px;
display: flex;
overflow: hidden;
position: relative;
}
.slide {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
object-position: center;
transition: transform 250ms ease;
}
h1 {
margin-bottom: 0.25rem;
}
.controls {
display: flex;
gap: 0.5rem;
width: 100%;
align-items: center;
}
.btn {
background-color: #333;
border: 0;
padding: 0.5rem 0.75em;
width: 12ch;
text-transform: uppercase;
letter-spacing: 1px;
color: #fff;
}
.ph {
background-color: #08b;
width: max-content;
}
.btn:hover {
border: 2px solid #000;
border-radius: .25rem;
}
<div class="box">
<h1>Gallery</h1>
<div class="slider"></div>
<div class="controls">
<button class="btn" id="prevBtn">previous</button>
<input hidden type="file" id="fileInp" multiple />
<!-- Just a placeholder to easily style the file input -->
<button onclick="fileInp.click()" class="ph btn">choose files</button>
<button class="btn" id="nextBtn">next</button>
</div>
</div>
i am adding a snippet so you can understand it clearly,
When using static HTML tags, the slider works properly but when I generate images from file input using JavaScript it gives unwanted results. Where am I going wrong?
it because on page load const slides = document.querySelectorAll('.slide'); is empty, move it to file load event
const slider = document.querySelector('.slider');
let slides = [];
// load user chosen files
fileInp.addEventListener('input', (e) => {
const files = e.target.files;
for (let file of files) {
const img = new Image();
const reader = new FileReader();
reader.addEventListener('load', (e) => {
img.src = e.target.result;
slider.appendChild(img);
img.classList.add('slide');
slides = document.querySelectorAll('.slide');
slides.forEach((slide, index) => {
slide.style.left =
`${index * 100}%`
})
})
reader.readAsDataURL(file);
}
})
// slider
let counter = 0;
nextBtn.onclick = () => {
counter++;
move();
}
prevBtn.onclick = () => {
counter--;
move();
}
function move() {
if (counter <= 0) {
counter = slides.length - 1;
}
if (counter === slides.length) {
counter = 0;
}
slides.forEach((slide, index) => {
slide.style.transform =
`translateX(-${counter * 100}%)`
})
}
.slide {
position: absolute;
height: 100%;
width: 100%;
top: 110px;
object-fit: cover;
object-position: center;
transition: transform 250ms ease;
}
h1 {
margin-bottom: 0.25rem;
}
.controls {
display: flex;
gap: 0.5rem;
width: 100%;
align-items: center;
}
.btn {
background-color: #333;
border: 0;
padding: 0.5rem 0.75em;
width: 12ch;
text-transform: uppercase;
letter-spacing: 1px;
color: #fff;
}
.ph {
background-color: #08b;
width: max-content;
}
.btn:hover {
background-color: #222;
}
<div class="box">
<h1>Gallery</h1>
<div class="slider"></div>
<div class="controls">
<button class="btn" id="prevBtn">previous</button>
<input hidden type="file" id="fileInp" multiple />
<!-- Just a placeholder to easily style the file input -->
<button onclick="fileInp.click()" class="ph btn">choose files</button>
<button class="btn" id="nextBtn">next</button>
</div>

Custom jQuery carousel transition bug

I am working on a custom image carousel, with jQuery and CSS. I am trying to avoid using a multiple-features carousel plugin download from Github, for performance reasons.
My aim is to obtain a vertical transition, like the one on www.pcgarage.ro, but without using the plugin they (might) have used. For this purpose, I have written:
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
for (var i = 0; i < slidesCount; i++) {
var bullets = '' + i + '';
if (i == 0) {
// active bullet
var bullets = '' + i + '';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
// Set (initial) z-index for each slide
var setZindex = function() {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
}
setZindex();
$('.slider-nav a').on('click', function() {
activeIdx = $(this).text();
$('.slider-nav a').removeClass('activeSlide');
$(this).addClass('activeSlide');
setActiveSlide();
slideUpDown();
});
var setActiveSlide = function() {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
}
var slideUpDown = function() {
// set top property for all the slides
$(slides).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
});
}
body {
margin: 0;
padding: 0;
}
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
position: absolute;
left: 10px;
bottom: 10px;
z-index: 30;
}
.slider .slider-nav a {
display: block;
float: left;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 3px;
text-indent: -9999px;
background: #fff;
}
.slider .slider-nav a.activeSlide {
background: transparent;
border: 2px solid #fff;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-nav"></div>
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=north" alt="">
</a>
</div>
</div>
</div>
The problem with my code is the (obvious) white screen that accompanies every transition, whose cause I do not understand.
Where is my mistake?
I have added some variable and function to fix this issue kindly check the script.
var $elm = $('.slider'),
$slidesContainer = $elm.find('.slider-container'),
slides = $slidesContainer.children('a'),
slidesCount = slides.length,
slideHeight = $(slides[0]).find('img').outerHeight(false);
//Set slide height
$(slides).css('height', slideHeight);
// Append bullets
for (var i = 0; i < slidesCount; i++) {
var bullets = '' + i + '';
if (i == 0) {
// active bullet
var bullets = '' + i + '';
// active slide
$(slides[0]).addClass('active');
}
$('.slider-nav').append(bullets);
}
// Set (initial) z-index for each slide
var setZindex = function () {
for (var i = 0; i < slidesCount; i++) {
$(slides[i]).css('z-index', slidesCount - i);
}
}
setZindex();
var displayImageBeforeClick = null;
$('.slider-nav a').on('click', function () {
displayImageBeforeClick = $(".slider-container .active");
activeIdx = $(this).text();
if($(slides[activeIdx]).hasClass("active")){ return false; }
$('.slider-nav a').removeClass('activeSlide');
$(this).addClass('activeSlide');
setActiveSlide();
slideUpDown();
});
var setActiveSlide = function () {
$(slides).removeClass('active');
$(slides[activeIdx]).addClass('active');
}
var slideUpDown = function () {
// set top property for all the slides
$(slides).not(displayImageBeforeClick).css('top', slideHeight);
// then animate to the next slide
$(slides[activeIdx]).animate({
'top': 0
});
$(displayImageBeforeClick).animate({
'top': "-100%"
});
}
body {
margin: 0;
padding: 0;
}
body * {
box-sizing: border-box;
}
.container {
max-width: 1200px;
margin: 0 auto;
}
.slider {
width: 100%;
height: 300px;
position: relative;
overflow: hidden;
}
.slider .slider-nav {
position: absolute;
left: 10px;
bottom: 10px;
z-index: 30;
}
.slider .slider-nav a {
display: block;
float: left;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 3px;
text-indent: -9999px;
background: #fff;
}
.slider .slider-nav a.activeSlide {
background: transparent;
border: 2px solid #fff;
}
.slider .slider-container {
width: 100%;
text-align: center;
}
.slider .slider-container a {
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
}
.slider .slider-container img {
transform: translateX(-50%);
margin-left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<div class="container">
<div class="slider slider-homepage">
<div class="slider-nav"></div>
<div class="slider-container">
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=east" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=south" alt="">
</a>
<a href="#">
<img src="https://picsum.photos/1200/300/?gravity=north" alt="">
</a>
</div>
</div>
</div>
Add Transition to your ".slider .slider-container a" with a transition-duration and transition-timing-function.... for reference you can see https://www.w3schools.com/css/css3_transitions.asp

Javascript Slideshow Functions Not Working

I would please like an explanation to why the slideshow is not working. Below I have used an interval to perpetually change the slideshow, if userClick is false. The white and squared buttons (made of divs) are set to call upon two functions; slideRight() or slideLeft() and clicked(). When the buttons are clicked however, the clicked() function does not seem to change the variable, based on the data on top of the page.
<body>
<div class="page-wrapper">
<header>
<div class="headContent">
<h1 class="titleText">Slideshow</h1>
<h2 class="subTitleText">A slideshow made with JavaScript.</h2>
<p>userClick <span id="uc"></span></p>
</div>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Gallery</li>
</ul>
</nav>
</header>
<div class="body-wrapper">
<h1 class="titleText">Slideshow</h1>
<div id="slideshow">
<div id="leftSlide" onclick="leftSlide(); clicked()"></div>
<div id="rightSlide" onclick="rightSlide(); clicked()"></div>
</div>
<p>The image is not invoked by a tag, but invoked by the background property using Javascript.</p>
</div>
<footer>
<p id="footerText">© 2017 <br>Designed by JastineRay</p>
</footer>
</div>
<script language="javascript">
// Slide function
var slide = ["minivan", "lifeinthecity", "sunsetbodyoflove"];
var slideTo = 1;
window.onload = getSlide();
// Previous Image
function leftSlide() {
if (slideTo != 0) {
slideTo = slideTo - 1;
} else if (slideTo == 0) {
slideTo = slide.length - 1;
} else {
alert('SLIDE ERROR');
}
getSlide();
}
// Next Image
function rightSlide() {
if (slideTo != (slide.length - 1)) {
slideTo = slideTo + 1;
} else if (slideTo == (slide.length - 1)) {
slideTo = 0;
} else {
alert('SLIDE ERROR');
}
getSlide();
}
function getSlide() {
imageURL = 'url(images/' + slide[slideTo] + '.jpg)';
document.getElementById("slideshow").style.backgroundImage = imageURL;
}
// Interval Slideshow & Check if user clicked (timeout)
var userClick = false;
window.onload = slideInterval(5000);
// Start Slideshow
function slideInterval(interval) {
while (userClick = false) {
setInterval(function() {
rightSlide();
}, interval)
}
}
// Stop Slideshow and start timeout
function clicked() {
userClick = true;
setTimeout(function() {
userClick = false;
slideInterval();
}, 2000)
}
window.onload = function() {
setInterval(document.getElementById("uc").innerHTML = userClick), 100
}
</script>
</body>
CSS coding below.
* {
margin: 0;
padding: 0;
}
.page-wrapper {
width: 100%;
}
// Class Styling
.titleText {
font-family: monospace;
font-size: 40px;
}
.subTitleText {
font-family: monospace;
font-size: 20px;
font-weight: normal;
}
// Header Styling
header {
height: 500px;
}
.headContent {
margin: 30px 7%;
}
// Navigation Styling
nav {
overflow: hidden;
}
nav ul {
background: black;
background: linear-gradient(#595959, black);
list-style-type: none;
font-size: 0;
padding-left: 13.33%;
margin: 40px 0;
}
nav ul li {
padding: 15px 20px;
border-right: 1px solid #595959;
border-left: 1px solid #595959;
color: white;
display: inline-block;
font-size: 20px;
font-family: sans-serif;
}
// Body Styling
.body-wrapper {
}
.body-wrapper > .titleText {
text-align: center;
font-size: 50px;
}
#slideshow {
overflow: hidden;
margin: 20px auto;
border: 2px solid blue;
height: 350px;
max-width: 800px;
background-size: cover;
background-position: center;
position: relative;
}
#leftSlide {
position: absolute;
left: 40px;
top: 175px;
background-color: white;
height: 40px;
width: 40px;
}
#rightSlide {
position: absolute;
left: 100px;
top: 175px;
background-color: white;
height: 40px;
width: 40px;
}
// Footer Styling
Try changing the checking part to:
window.onload = function() {
setInterval(function () {
document.getElementById("uc").innerHTML = userClick;
}, 100);
}
The first argument of setInterval has to be a function (something that can be called), not a generic piece of code.

Categories

Resources