I have a carousel that I have to hard code and I need some help. I want to make a slide effect for mobile phones but I can't find a replacement for album.scrollBy. If you take a look at the code, you can see that on touchMove I scroll the parent element of the carousel but after the touch is done I transform the carousel and the album remains scrolled. So the only solution I found was to remove the scroll after the transition but is doesn't look good. Any ideas?
This is the carousel index.html
<body>
<div id="album" autoCall="true" class='album'>
<ul id="carousel" class='carousel is-set'>
<li class='container carousel-element'>
<img src="assets/img1.jpeg">
</li>
<li class='container carousel-element'>
<img src="assets/img2.jpeg">
</li>
<li class='container carousel-element'>
<img src="assets/img3.jpeg">
</li>
<li class='container carousel-element is-ref'>
<img src="assets/img4.jpeg">
</li>
</ul>
<div class="left-arrow"></div>
<div class="right-arrow"></div>
</div>
<script src="SLID/js/index.js"></script>
</body>
This is the CSS file that contains the transitions:
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
scroll-behavior: smooth;
}
.album {
overflow: hidden;
width: 100%;
height: 100%;
margin: auto;
position: relative;
}
.carousel {
height: 100%;
width: 100%;
display: flex;
left: -100%;
list-style: none;
margin: 0;
padding: 0;
position: relative;
}
.carousel.toNext {
transform: translateX(100%);
}
.carousel.toPrev {
transform: translateX(-100%);
}
.carousel.is-set {
transform: none;
transition: transform 0.5s cubic-bezier(0.215, 0.610, 0.355, 1);
}
.carousel-element {
background: #ddd;
flex: 1 0 100%;
text-align: center;
order: 2;
position: relative;
height: 100% !important;
max-width: 100% !important;
padding: 0;
}
.carousel-element:nth-child(even) {
background: #d5d5d5;
}
.carousel-element.is-ref {
order: 1;
}
.controls {
padding: 2em;
text-align: center;
}
.container {
margin: 0 auto;
height: 100%;
width: 100%;
}
.carousel-element >img, video {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
max-width: 100%;
max-height: 100%;
margin: auto;
padding: 0 !important;
}
.left-arrow,
.right-arrow {
height: 100%;
position: absolute;
top: 0;
bottom: 0;
z-index: 1;
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
align-items: center;
-ms-flex-pack: center;
justify-content: center;
width: 15%;
color: #fff;
text-align: center;
opacity: .5;
transition: opacity .15s ease
}
.left-arrow {
left: 0;
background: red
}
.right-arrow {
right: 0;
background: blue;
}
And here is the JS file:
let album = document.getElementById("album");
let carousel = document.getElementById("carousel");
let seats = document.querySelectorAll("ul > li");
if (seats.length === 1)
carousel.style.left = 0;
class SLID {
constructor() {
this.nextDisable = false;
this.prevDisable = false;
this.startX = 0;
this.finalX = 0;
this.lastX = 0;
this.didTheTouchMove = false;
}
goToNext() {
this.nextDisable = true;
var el, i, j, new_seat, ref;
el = document.querySelector("ul > li.is-ref");
el.classList.remove('is-ref');
new_seat = el.nextElementSibling || seats[0];
new_seat.classList.add('is-ref');
new_seat.style.order = 1;
for (i = j = 2, ref = seats.length; (2 <= ref ? j <= ref : j >= ref); i = 2 <= ref ? ++j : --j) {
new_seat = new_seat.nextElementSibling || seats[0];
new_seat.style.order = i;
}
carousel.classList.remove('toPrev');
carousel.classList.add('toNext');
carousel.classList.remove('is-set');
document.getElementById('carousel').addEventListener("transitionend", () => {
this.nextDisable = false;
}, {
once: true,
});
return setTimeout((function () {
return carousel.classList.add('is-set');
}), 50);
}
goToPrev() {
this.prevDisable = true;
var el, i, j, new_seat, ref;
el = document.querySelector("ul > li.is-ref");
el.classList.remove('is-ref');
new_seat = el.previousElementSibling || seats[seats.length - 1];
new_seat.classList.add('is-ref');
new_seat.style.order = 1;
for (i = j = 2, ref = seats.length; (2 <= ref ? j <= ref : j >= ref); i = 2 <= ref ? ++j : --j) {
new_seat = new_seat.nextElementSibling || seats[0];
new_seat.style.order = i;
}
carousel.classList.remove('toNext');
carousel.classList.add('toPrev');
carousel.classList.remove('is-set');
document.getElementById('carousel').addEventListener("transitionend", () => {
this.prevDisable = false;
}, {
once: true
});
return setTimeout((function () {
return carousel.classList.add('is-set');
}), 50);
}
}
if (document.getElementById("album").getAttribute('autoCall') === "true") {
let s = new SLID();
document.addEventListener("keydown", (e) => {
if (e.keyCode === 37)
if (s.prevDisable === false)
s.goToPrev();
if (e.keyCode === 39)
if (s.nextDisable === false)
s.goToNext();
})
carousel.addEventListener("touchstart", (e) => {
s.startX = e.touches[0].clientX;
s.lastX = e.touches[0].clientX;
})
carousel.addEventListener("touchmove", (e) => {
album.scrollBy(s.lastX - e.touches[0].clientX, 0);
s.lastX = e.touches[0].clientX;
})
carousel.addEventListener("touchend", (e) => {
album.scrollBy(s.lastX - s.startX, 0);
s.goToNext();
})
}
Related
I'm trying to get to grips with javascript, and have followed a tutorial for a simple image slider. I'm trying to add to it and have the background fade to different colours as the slides move. I've managed to figure it out with the right and left arrows (not sure on best practise), but I can't seem to get it right when selecting the indicators. Can anyone advise on a solution?
Thanks in advance.
const left = document.querySelector('.left');
const right = document.querySelector('.right');
const slider = document.querySelector('.carousel__slider');
const indicatorParent = document.querySelector('.carousel__controls ol');
const indicators = document.querySelectorAll('.carousel__controls li');
index = 0;
var background = 1;
function indicatorBg(val){
var background = val;
changeBg();
}
indicators.forEach((indicator, i) => {
indicator.addEventListener('click', () => {
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicator.classList.add('selected');
slider.style.transform = 'translateX(' + (i) * -25 + '%)';
index = i;
});
});
left.addEventListener('click', function() {
index = (index > 0) ? index -1 : 0;
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicatorParent.children[index].classList.add('selected');
slider.style.transform = 'translateX(' + (index) * -25 + '%)';
if (background <= 1) {
return false;
} else {
background--;
}
changeBg();
});
right.addEventListener('click', function() {
index = (index < 4 - 1) ? index+1 : 3;
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicatorParent.children[index].classList.add('selected');
slider.style.transform = 'translateX(' + (index) * -25 + '%)';
if (background >= 4) {
return false;
} else {
background++;
}
changeBg();
});
function changeBg (){
if (background == 1) {
document.getElementById("carousel__track").className = 'slide-1';
} else if (background == 2) {
document.getElementById("carousel__track").className = 'slide-2';
} else if (background == 3) {
document.getElementById("carousel__track").className = 'slide-3';
} else if (background == 4) {
document.getElementById("carousel__track").className = 'slide-4';
}
}
window.onload = changeBg;
.carousel {
height: 80vh;
width: 100%;
margin: 0 auto;
}
#carousel__track {
height: 100%;
position: relative;
overflow: hidden;
}
.background {
background: red;
}
.carousel__slider {
height: 100%;
display: flex;
width: 400%;
transition: all 0.3s;
}
.carousel__slider div {
flex-basis: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.carousel__controls .carousel__arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
z-index: 8888
}
.carousel__controls .carousel__arrow i {
font-size: 2.6rem;
}
.carousel__arrow.left {
left: 1em;
}
.carousel__arrow.right {
right: 1em;
}
.carousel__controls ol {
position: absolute;
bottom: 15%;
left: 50%;
transform: translateX(-50%);
list-style: none;
display: flex;
margin: 0;
padding: 0;
}
.carousel__controls ol li {
width: 14px;
height: 14px;
border-radius: 50px;
margin: .5em;
padding: 0;
background: white;
transform: scale(.6);
cursor: pointer;
}
.carousel__controls ol li.selected {
background: black;
transform: scale(1);
transition: all .2s;
transition-delay: .3s;
}
.slide-1 {
background: pink;
transition: all 0.4s;
}
.slide-2 {
background: coral;
transition: all 0.4s;
}
.slide-3 {
background: green;
transition: all 0.4s;
}
.slide-4 {
background: orange;
transition: all 0.4s;
}
<section class="carousel">
<div id="carousel__track">
<div class="carousel__slider">
<div>Slide 1</div>
<div>Slide 2</div>
<div>Slide 3</div>
<div>Slide 4</div>
</div>
<div id="left" class="carousel__controls"><span class="carousel__arrow left"><</span> <span id="right" class="carousel__arrow right">></span>
<ol>
<li value="1" onclick="indicatorBg(this.value)" class="selected"></li>
<li value="2" onclick="indicatorBg(this.value)"></li>
<li value="3" onclick="indicatorBg(this.value)"></li>
<li value="4" onclick="indicatorBg(this.value)"></li>
</ol>
</div>
</div>
</section>
You forgot to change the background inside the click event handler of the indicators.
indicators.forEach((indicator, i) => {
indicator.addEventListener('click', () => {
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicator.classList.add('selected');
slider.style.transform = 'translateX(' + (i) * -25 + '%)';
index = i;
background = index + 1;
changeBg();
});
});
As far as best practice goes, I typically use class names for CSS and IDs for JavaScript. Personally, I wouldn't recommend you worry about best practices at this stage, but instead, focus on getting the code working and understanding what's going on line-by-line.
There is a lot of solutions, but the simplest solution that I advice is to use odd and even numbers to style the divs in the carousel (meaning that eg. first is green second is orange third is green and so on...
.carousel__slider div:nth-child(2n) /*Selects even numbered elements*/
.carousel__slider div:nth-child(2n+1) /*Selects odd numbered elements*/
Check out the snippet
const left = document.querySelector('.left');
const right = document.querySelector('.right');
const slider = document.querySelector('.carousel__slider');
const indicatorParent = document.querySelector('.carousel__controls ol');
const indicators = document.querySelectorAll('.carousel__controls li');
index = 0;
//var background = 1;
//function indicatorBg(val){
// var background = val;
// changeBg();
//}
indicators.forEach((indicator, i) => {
indicator.addEventListener('click', () => {
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicator.classList.add('selected');
slider.style.transform = 'translateX(' + (i) * -25 + '%)';
index = i;
});
});
left.addEventListener('click', function() {
index = (index > 0) ? index -1 : 0;
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicatorParent.children[index].classList.add('selected');
slider.style.transform = 'translateX(' + (index) * -25 + '%)';
// if (background <= 1) {
// return false;
// } else {
// background--;
// }
// changeBg();
});
right.addEventListener('click', function() {
index = (index < 4 - 1) ? index+1 : 3;
document.querySelector('.carousel__controls .selected').classList.remove('selected');
indicatorParent.children[index].classList.add('selected');
slider.style.transform = 'translateX(' + (index) * -25 + '%)';
// if (background >= 4) {
// return false;
// } else {
// background++;
// }
// changeBg();
});
//function changeBg (){
// if (background == 1) {
// document.getElementById("carousel__track").className = 'slide-1';
// } else if (background == 2) {
// document.getElementById("carousel__track").className = 'slide-2';
// } else if (background == 3) {
// document.getElementById("carousel__track").className = 'slide-3';
// } else if (background == 4) {
// document.getElementById("carousel__track").className = 'slide-4';
// }
//}
//window.onload = changeBg;
.carousel {
height: 80vh;
width: 100%;
margin: 0 auto;
}
#carousel__track {
height: 100%;
position: relative;
overflow: hidden;
}
.background {
background: red;
}
.carousel__slider {
height: 100%;
display: flex;
width: 400%;
transition: all 0.3s;
}
.carousel__slider div {
flex-basis: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.carousel__controls .carousel__arrow {
position: absolute;
top: 50%;
transform: translateY(-50%);
cursor: pointer;
z-index: 8888
}
.carousel__controls .carousel__arrow i {
font-size: 2.6rem;
}
.carousel__arrow.left {
left: 1em;
}
.carousel__arrow.right {
right: 1em;
}
.carousel__controls ol {
position: absolute;
bottom: 15%;
left: 50%;
transform: translateX(-50%);
list-style: none;
display: flex;
margin: 0;
padding: 0;
}
.carousel__controls ol li {
width: 14px;
height: 14px;
border-radius: 50px;
margin: .5em;
padding: 0;
background: white;
transform: scale(.6);
cursor: pointer;
}
.carousel__controls ol li.selected {
background: black;
transform: scale(1);
transition: all .2s;
transition-delay: .3s;
}
/*.slide-1 {
background: pink;
transition: all 0.4s;
}
.slide-2 {
background: coral;
transition: all 0.4s;
}
.slide-3 {
background: green;
transition: all 0.4s;
}
.slide-4 {
background: orange;
transition: all 0.4s;
}*/
.carousel__slider div:nth-child(2n) {
background-color:orange;
}
.carousel__slider div:nth-child(2n+1) {
background-color:green;
}
<section class="carousel">
<div id="carousel__track">
<div class="carousel__slider">
<div>Slide 1</div>
<div>Slide 2</div>
<div>Slide 3</div>
<div>Slide 4</div>
</div>
<div id="left" class="carousel__controls"><span class="carousel__arrow left"><</span> <span id="right" class="carousel__arrow right">></span>
<ol>
<li value="1" class="selected"></li>
<li value="2" ></li>
<li value="3" ></li>
<li value="4" ></li>
</ol>
</div>
</div>
</section>
We need advice on how to do what would happen with normal scrolling of the page (with a wheel, or in a mob with a finger) after the block has been screwed up to the top of the screen, it began to scroll horizontally and after the edge of the block is reached, the standard scroll continues, respectively, if the scroll goes up, then that's it in reverse order. (There may be several such blocks on a page)
* {
box-sizing: border-box;
margin: 0;
}
body {
overflow-x: hidden;
}
.simple {
height: 100vh;
background: #1f69c0;
border-bottom: 2px solid #777;
}
.simple2 {
height: 400px;
background: #EEAA07;
border-bottom: 2px solid #777;
}
.simple3 {
height: 400px;
background: #07eed9;
border-bottom: 2px solid #777;
}
.outer {
height: 150px;
background: #7b8e39;
overflow-y: hidden;
overflow-x: scroll;
}
.inner {
height: 100%;
margin: 0 100px;
display: flex;
}
.cube {
min-width: 200px;
height: 100px;
background: #f6f6f6;
margin: 10px;
display: flex;
align-items: center;
justify-content: center;
}
<div class="simple"></div>
<div class="outer">
<div class="inner">
<div class="cube">1</div>
<div class="cube">2</div>
<div class="cube">3</div>
<div class="cube">4</div>
<div class="cube">5</div>
<div class="cube">6</div>
<div class="cube">7</div>
<div class="cube">8</div>
<div class="cube">9</div>
<div class="cube">10</div>
</div>
</div>
<div class="simple2"></div>
<div class="simple3"></div>
Here is an approximate structure, until block 2 has scrolled to the end, block 3 should be visible and after 2 has scrolled horizontally to the end, the standard scroll will continue
PS Here is an example (https://horizontalscrolling.wpdemos.net/horizontal-scrolling/) of how scrolling should work, although there can be more than 1 block on one screen
This technique needs to use javascript called "GSAP" which is a high-performance javascript animation library.
I found a similar animation that you were looking for.
Hopefully, this will help :)
//https://codepen.io/osublake/pen/e72106811a34efcccff91a03568cc790.js?v=3
class SmoothScroll {
constructor(options) {
this.endThreshold = 0.05;
this.requestId = null;
this.maxDepth = 10;
this.viewHeight = 0;
this.halfViewHeight = 0;
this.maxDistance = 0;
this.viewWidth = 0;
this.halfViewWidth = 0;
this.maxDistanceWidth = 0;
this.scrollHeight = 0;
this.endScroll = 0;
this.returnCurrentScroll = 0;
this.currentScroll = 0;
this.scrollTransform = 0;
this.horizontalScroll = 0;
this.resizeRequest = 1;
this.scrollRequest = 0;
this.scrollItems = [];
this.lastTime = -1;
this.maxElapsedMS = 100;
this.targetFPMS = 0.06;
// this.scrollBody = options.scrollBody;
// this.scrollSpacer = options.scrollSpacer;
this.target = options.target;
this.scrollEase = options.scrollEase != null ? options.scrollEase : 0.1;
this.maxOffset = options.maxOffset != null ? options.maxOffset : 500;
this.horizontalScrollWrapper = options.horizontalScrollWrapper;
this.horizontalScrollTarget = options.horizontalScrollTarget;
this._horziontalSetHeihgt();
this.childElements = this._childElements();
this.rectHorStart = this.horizontalScrollWrapper.getBoundingClientRect();
this.horzItemStart = {
top: this.rectHorStart.top,
bottom: this.rectHorStart.bottom,
height: this.rectHorStart.height
}
this.addItems();
window.addEventListener("resize", this._onResize);
window.addEventListener("scroll", this._onScroll);
//this.scrollBody.addEventListener("scroll", this._onScroll);
this._update();
}
_childElements = (event) => {
const childElementsNode = this.target.querySelectorAll("*[data-color]");
return childElementsNode;
}
_horizonstalScrollRect = (event) => {
const horzintalRect = this.horizontalScrollTarget.getBoundingClientRect();
return horzintalRect;
}
_lastScrollRect = (event) => {
const lastScrollRect = this.horizontalScrollTarget.lastElementChild.getBoundingClientRect();
return lastScrollRect;
}
_horziontalSetHeihgt = (event) => {
let horScrHeight = 0;
if (
this.horizontalScrollTarget !== null &&
this.horizontalScrollWrapper !== null
) {
const lastScrollRect = this._lastScrollRect();
horScrHeight = this.horizontalScrollTarget.scrollWidth - lastScrollRect.width + this._horizonstalScrollRect().height;
this.horizontalScrollWrapper.style.height = horScrHeight + "px";
}
}
_onResize = (event) => {
this.resizeRequest++;
if (!this.requestId) {
this.lastTime = performance.now();
this.requestId = requestAnimationFrame(this._update);
}
};
_onScroll = (event) => {
this.scrollRequest++;
if (!this.requestId) {
this.lastTime = performance.now();
this.requestId = requestAnimationFrame(this._update);
}
};
_horizonstalScroll = (scrollY,dt) => {
if (this.horizontalScrollWrapper !== null) {
const rectHor = this.horizontalScrollWrapper.getBoundingClientRect();
const lastScrollRect = this._lastScrollRect();
const itemHor = {
target: this.horizontalScrollTarget,
targetRect: this._horizonstalScrollRect(),
top: rectHor.top,
bottom: rectHor.bottom + scrollY,
topScroll: rectHor.top + scrollY,
horizonstalMove: 0,
};
itemHor.horizonstalMove += this.currentScroll - this.horzItemStart.top;
if(scrollY >= this.horzItemStart.top && scrollY <= this.horzItemStart.bottom - itemHor.targetRect.height){
itemHor.target.style.position = 'fixed';
itemHor.target.style.transform = `translate3d(-${itemHor.horizonstalMove}px,0px,0px)`;
//this._paralaxHorizontal(dt);
if(lastScrollRect.x <= (lastScrollRect.width/2)){
this.scrollTransform = this.horzItemStart.bottom - itemHor.targetRect.height;
itemHor.target.style.top = this.horzItemStart.bottom - itemHor.targetRect.height+'px';
}else {
this.scrollTransform = this.horzItemStart.top;
itemHor.target.style.top = this.horzItemStart.top+'px';
}
}
}
};
_changeColorBody = (event) => {
if(this.childElements.length > 0){
this.childElements.forEach(child => {
const wrapper = document.querySelector('.change_color_page');
const childRect = child.getBoundingClientRect();
const childAttr = child.getAttribute('data-color');
if(childRect.y <= this.halfViewHeight && childRect.bottom >= this.halfViewHeight){
if(childAttr == "off_white"){
if(!document.body.classList.contains('white')){
document.body.classList.add('white');
}
if(!wrapper.classList.contains('white')){
wrapper.classList.add('white');
}
}else if(childAttr == "dark"){
if(document.body.classList.contains('white')){
document.body.classList.remove('white');
}
if(wrapper.classList.contains('white')){
wrapper.classList.remove('white');
}
}
}
});
}
}
_update = (currentTime = performance.now()) => {
let elapsedMS = currentTime - this.lastTime;
if (elapsedMS > this.maxElapsedMS) {
elapsedMS = this.maxElapsedMS;
}
const deltaTime = elapsedMS * this.targetFPMS;
const dt = 1 - Math.pow(1 - this.scrollEase, deltaTime);
const resized = this.resizeRequest > 0;
const scrollY = window.pageYOffset;
//const scrollY = this.scrollBody.scrollTop;
if (resized) {
this._horziontalSetHeihgt();
const height = this.target.clientHeight;
document.body.style.height = height + "px";
//this.scrollSpacer.style.height = height + "px";
this.scrollHeight = height;
this.viewHeight = window.innerHeight;
this.halfViewHeight = this.viewHeight / 2;
this.maxDistance = this.viewHeight * 2;
this.resizeRequest = 0;
this.viewWidth = window.innerWidth;
this.halfViewWidth = this.viewWidth / 2;
this.maxDistanceWidth = this.viewWidth * 2;
}
this.endScroll = scrollY;
// this.scrollTransform += (scrollY - this.scrollTransform) * this.scrollEase;
this.scrollTransform += (scrollY - this.scrollTransform) * dt;
this.currentScroll += (scrollY - this.currentScroll) * dt;
if (Math.abs(scrollY - this.currentScroll) < this.endThreshold || resized) {
this.currentScroll = scrollY;
this.scrollRequest = 0;
}
if (
Math.abs(scrollY - this.scrollTransform) < this.endThreshold ||
resized
) {
this.scrollTransform = scrollY;
this.scrollRequest = 0;
}
///change color section
this._changeColorBody();
///horizontal scroll
this._horizonstalScroll(this.currentScroll,dt);
// const scrollOrigin = scrollY + this.halfViewHeight;
const scrollOrigin = this.currentScroll + this.viewHeight;
this.target.style.transform = `translate3d(0px,-${this.scrollTransform}px,0px)`;
//items
for (let i = 0; i < this.scrollItems.length; i++) {
const item = this.scrollItems[i];
const distance = scrollOrigin - item.top;
const offsetRatio = distance / this.maxDistance;
item.endOffset = Math.round(
this.maxOffset * item.depthRatio * offsetRatio
);
if (Math.abs(item.endOffset - item.currentOffset < this.endThreshold)) {
item.currentOffset = item.endOffset;
} else {
// item.currentOffset += (item.endOffset - item.currentOffset) * this.scrollEase;
item.currentOffset += (item.endOffset - item.currentOffset) * dt;
}
if(item.direction == "y"){
item.target.style.transform = `translate3d(0px,${item.currentOffset}px,0px)`;
}else if(item.direction == "x"){
item.target.style.transform = `translate3d(${item.currentOffset}px,0px,0px)`;
}
}
this.lastTime = currentTime;
this.requestId =
this.scrollRequest > 0 ? requestAnimationFrame(this._update) : null;
};
addItems() {
this.scrollItems = [];
const elements = document.querySelectorAll("*[data-depth]");
for (let i = 0; i < elements.length; i++) {
const element = elements[i];
const depth = +element.getAttribute("data-depth");
const direction_item = element.getAttribute("data-direction");
const rect_item = element.getBoundingClientRect();
const item = {
rect: rect_item,
target: element,
top: rect_item.top + window.pageYOffset,
//top: rect_item.top + this.scrollBody.scrollTop,
depth: depth,
depthRatio: depth / this.maxDepth,
currentOffset: 0,
endOffset: 0,
direction: direction_item
};
this.scrollItems.push(item);
}
return this;
}
currentScrollReturn() {
return this.currentScroll;
}
}
document.documentElement.style.setProperty(
"--scrollbar-size",
getScrollbarSize() + "px"
);
var scroller = new SmoothScroll({
// scrollBody: document.querySelector(".scroll-content"),
// scrollSpacer: document.querySelector(".spacer"),
target: document.querySelector(".scroll-container"), // element container to scroll
scrollEase: 0.05,
horizontalScrollWrapper: document.querySelector(".horizontal-scroll-wrapper"),
horizontalScrollTarget: document.querySelector(".horizontal-scroll")
});
function getScrollbarSize() {
var div = document.createElement("div");
div.classList.add("scrollbar-test");
document.body.appendChild(div);
var size = div.offsetWidth - div.scrollWidth;
document.body.removeChild(div);
return size;
}
$white: #fbe8ee;
$black: #0a0a0a;
:root {
--scrollbar-size: 0px;
}
*, :after, :before {
box-sizing: border-box;
}
body {
}
.viewport {
overflow: hidden;
position: fixed;
height: 100%;
width: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
body {
overflow-x: hidden;
overflow-y: scroll;
padding: 0;
margin: 0;
font-family: "Courier New", Courier, monospace;
*:not(.change_color_page) {
color: $white;
transition: color 0.5s ease-in-out, border-color 0.5s ease;
border-color: $white;
}
&.white {
*:not(.change_color_page) {
color: $black;
transition: color 0.5s ease-in-out, border-color 0.5s ease;
border-color: $black;
}
}
}
.change_color_page {
position: fixed;
display: block;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background-color: $black;
transition: background-color 0.5s ease;
backface-visibility: hidden;
transform-style: preserve-3d;
&.white {
background-color: $white;
}
}
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.5s ease-in-out;
background-color: $white;
&.white {
background-color: $black;
}
}
.scrollbar-test {
position: absolute;
visibility: hidden;
overflow: scroll;
width: 100px;
height: 100px;
top: -99999px;
left: -99999px;
pointer-events: none;
user-select: none;
}
.fixed-content {
position: absolute;
display: block;
top: 0;
left: 0;
right: var(--scrollbar-size, 0px);
bottom: 0;
z-index: 2;
pointer-events: none;
}
.scroll-container {
position: absolute;
overflow: hidden;
z-index: 10;
backface-visibility: hidden;
transform-style: preserve-3d;
width: 100%;
}
.content {
overflow: hidden;
position: relative;
width: 100%;
}
.spacer {
background: transparent;
}
.single-item {
flex: 0 0 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
font-size: 70px;
&.left {
justify-content: flex-start;
}
p {
width: 300px;
height: 300px;
display: flex;
align-items: center;
justify-content: center;
border-width: 2px;
border-style: solid;
}
}
.horizontal-scroll-wrapper {
position: relative;
}
.horizontal-scroll {
display: flex;
}
.horizontal-scroll .single-item {
flex: 0 0 100vw;
p {
width: 600px;
height: 600px;
max-width: 80%;
max-height: 80%;
}
}
<div class="change_color_page"></div>
<header></header>
<div class="viewport">
<div class="scroll-container">
<div class="content">
<div class="single-item active" data-color="off_white">
<p>1</p>
</div>
<div class="single-item" data-color="dark">
<p data-depth="-7" data-direction="y">2</p>
</div>
<div class="single-item" data-color="off_white">
<p class="item_to_move">3</p>
</div>
<div class="single-item" data-color="dark">
<p data-depth="-3" data-direction="y">4</p>
</div>
<div class="single-item" data-color="off_white">
<p data-depth="-3" data-direction="y">5</p>
</div>
<div class="horizontal-scroll-wrapper" data-color="dark">
<div class="horizontal-scroll">
<div class="single-item">
<p><span data-depth-hor="-3" data-direction="left">6</span></p>
</div>
<div class="single-item">
<p><span data-depth-hor="-3" data-direction="left">7</span></p>
</div>
<div class="single-item">
<p><span data-depth-hor="-3" data-direction="left">8</span></p>
</div>
<div class="single-item">
<p><span data-depth-hor="-3" data-direction="left">9</span></p>
</div>
<div class="single-item">
<p><span data-depth-hor="-3" data-direction="left">10</span></p>
</div>
</div>
</div>
<div class="single-item" data-color="off_white">
<p data-depth="-3" data-direction="y">11</p>
</div>
<div class="single-item" data-color="dark">
<p data-depth="-3" data-direction="y">12</p>
</div>
<div class="single-item left" data-color="off_white">
<p data-depth="15" data-direction="x">13</p>
</div>
</div>
</div>
</div>
source code from: https://codepen.io/duty47/pen/vYYEgam
The following code looks daunting, but a lot of it is repetitive. Try clicking on the red buttons.
<body>
<ul id="carousel" class="carousel">
<button id="moveSlideLeft" class="moveSlide moveSlideLeft"></button>
<div id="track" class="track">
<li class="slide1" data-shown="true2" title="true2"><img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fblogs-images.forbes.com%2Frajatbhageria%2Ffiles%2F2017%2F09%2Fcode-copy-1200x1200.jpg"></li>
<li class="slide2" data-shown="false3" title="false3"><img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fblogs-images.forbes.com%2Frajatbhageria%2Ffiles%2F2017%2F09%2Fcode-copy-1200x1200.jpg"></li>
<li class="slide3" data-shown="false1" title="false1"><img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fblogs-images.forbes.com%2Frajatbhageria%2Ffiles%2F2017%2F09%2Fcode-copy-1200x1200.jpg"></li>
</div>
<button id="moveSlideRight" class="moveSlide moveSlideRight"></button>
</ul>
</body>
<style>
.carousel {
list-style-type: none;
position: relative;
}
.moveSlideLeft {
left: 0px;
}
.moveSlideLeft>img {
width: 10px;
height: 10px;
transform: rotate(180deg);
}
.moveSlide {
margin: none;
padding: none;
width: 20px;
height: 20px;
background-color: red;
border: none;
float: left;
position: absolute;
z-index: 1;
}
.carousel>.track {
margin: none;
padding: none;
left: 0px;
width: 99px;
height: 100px;
overflow: hidden;
position: absolute;
}
.carousel>.track>li[data-shown="false1"] {
transform: translateX(-99px);
z-index: 0;
transition: transform 1s ease-out;
}
.carousel>.track>li[data-shown="true2"] {
transform: translateX(0px);
z-index: 2;
transition: transform 1s ease-out;
}
.carousel>.track>li[data-shown="false3"] {
transform: translateX(99px);
z-index: 0;
transition: transform 1s ease-out;
}
.carousel>.track>li>img {
float: left;
width: 99px;
height: 100px;
}
.moveSlideRight {
left: 80px;
}
.moveSlideRight>img {
width: 10px;
height: 10px;
}
</style>
<script>
const left = document.getElementById("moveSlideLeft");
const right = document.getElementById("moveSlideRight");
left.onclick = function() {
var carouselValues = [];
var tagReferences = document.getElementById("carousel").getElementsByTagName("li");
for (var i=0; i<=2; i++) {
carouselValues[i] = tagReferences[i].dataset.shown;
}
var placeholder;
for (var i=0; i<=2; i++) {
if (carouselValues[i] == "true2") {
placeholder = i;
break;
}
}
if (placeholder == 0) {
carouselValues[0] = "false3";
carouselValues[1] = "false1";
carouselValues[2] = "true2";
}
else if (placeholder == 1) {
carouselValues[0] = "true2";
carouselValues[1] = "false3";
carouselValues[2] = "false1";
}
else if (placeholder == 2) {
carouselValues[0] = "false1";
carouselValues[1] = "true2";
carouselValues[2] = "false3";
}
for (var i = 0; i<=2; i++) {
tagReferences[i].dataset.shown = carouselValues[i];
tagReferences[i].title = carouselValues[i];
}
}
right.onclick = function() {
var carouselValues = [];
var tagReferences = document.getElementById("carousel").getElementsByTagName("li");
for (var i=0; i<=2; i++) {
carouselValues[i] = tagReferences[i].dataset.shown;
}
var placeholder;
for (var i = 0; i<=2; i++) {
if (carouselValues[i] == "true2") {
placeholder = i;
break;
}
}
if (placeholder == 0) {
carouselValues[0] = "false1";
carouselValues[1] = "true2";
carouselValues[2] = "false3";
}
else if (placeholder == 1) {
carouselValues[0] = "false3";
carouselValues[1] = "false1";
carouselValues[2] = "true2";
}
else if (placeholder == 2) {
carouselValues[0] = "true2";
carouselValues[1] = "false3";
carouselValues[2] = "false1";
}
for (var i = 0; i<=2; i++) {
tagReferences[i].dataset.shown = carouselValues[i];
tagReferences[i].title = carouselValues[i];
}
}
</script>
I don't know why only one image is showing up. I'm trying to make a sliding carousel. Every time a button is clicked, the data-shown attribute is changed. Based on the value of the data-shown attribute, a new slide should slide in. Where is my error?
You just need to add position: absolute to carousel>.track>li>img to list them in one line because you position them floating to left but in top of each other
const left = document.getElementById("moveSlideLeft");
const right = document.getElementById("moveSlideRight");
left.onclick = function() {
var carouselValues = [];
var tagReferences = document.getElementById("carousel").getElementsByTagName("li");
for (var i=0; i<=2; i++) {
carouselValues[i] = tagReferences[i].dataset.shown;
}
var placeholder;
for (var i=0; i<=2; i++) {
if (carouselValues[i] == "true2") {
placeholder = i;
break;
}
}
if (placeholder == 0) {
carouselValues[0] = "false3";
carouselValues[1] = "false1";
carouselValues[2] = "true2";
}
else if (placeholder == 1) {
carouselValues[0] = "true2";
carouselValues[1] = "false3";
carouselValues[2] = "false1";
}
else if (placeholder == 2) {
carouselValues[0] = "false1";
carouselValues[1] = "true2";
carouselValues[2] = "false3";
}
for (var i = 0; i<=2; i++) {
tagReferences[i].dataset.shown = carouselValues[i];
tagReferences[i].title = carouselValues[i];
}
}
right.onclick = function() {
var carouselValues = [];
var tagReferences = document.getElementById("carousel").getElementsByTagName("li");
for (var i=0; i<=2; i++) {
carouselValues[i] = tagReferences[i].dataset.shown;
}
var placeholder;
for (var i = 0; i<=2; i++) {
if (carouselValues[i] == "true2") {
placeholder = i;
break;
}
}
if (placeholder == 0) {
carouselValues[0] = "false1";
carouselValues[1] = "true2";
carouselValues[2] = "false3";
}
else if (placeholder == 1) {
carouselValues[0] = "false3";
carouselValues[1] = "false1";
carouselValues[2] = "true2";
}
else if (placeholder == 2) {
carouselValues[0] = "true2";
carouselValues[1] = "false3";
carouselValues[2] = "false1";
}
for (var i = 0; i<=2; i++) {
tagReferences[i].dataset.shown = carouselValues[i];
tagReferences[i].title = carouselValues[i];
}
}
.carousel {
list-style-type: none;
position: relative;
}
.moveSlideLeft {
left: 0px;
}
.moveSlideLeft>img {
width: 10px;
height: 10px;
transform: rotate(180deg);
}
.moveSlide {
margin: none;
padding: none;
width: 20px;
height: 20px;
background-color: red;
border: none;
float: left;
position: absolute;
z-index: 1;
}
.carousel>.track {
margin: none;
padding: none;
left: 0px;
width: 99px;
height: 100px;
overflow: hidden;
position: absolute;
}
.carousel>.track>li[data-shown="false1"] {
transform: translateX(-99px);
z-index: 0;
transition: transform 1s ease-out;
}
.carousel>.track>li[data-shown="true2"] {
transform: translateX(0px);
z-index: 2;
transition: transform 1s ease-out;
}
.carousel>.track>li[data-shown="false3"] {
transform: translateX(99px);
z-index: 0;
transition: transform 1s ease-out;
}
.carousel>.track>li>img {
float: left;
width: 99px;
height: 100px;
position: absolute;
}
.moveSlideRight {
left: 80px;
}
.moveSlideRight>img {
width: 10px;
height: 10px;
}
<ul id="carousel" class="carousel">
<button id="moveSlideLeft" class="moveSlide moveSlideLeft"></button>
<div id="track" class="track">
<li class="slide1" data-shown="true2" title="true2"><img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fblogs-images.forbes.com%2Frajatbhageria%2Ffiles%2F2017%2F09%2Fcode-copy-1200x1200.jpg"></li>
<li class="slide2" data-shown="false3" title="false3"><img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fblogs-images.forbes.com%2Frajatbhageria%2Ffiles%2F2017%2F09%2Fcode-copy-1200x1200.jpg"></li>
<li class="slide3" data-shown="false1" title="false1"><img src="https://thumbor.forbes.com/thumbor/960x0/https%3A%2F%2Fblogs-images.forbes.com%2Frajatbhageria%2Ffiles%2F2017%2F09%2Fcode-copy-1200x1200.jpg"></li>
</div>
<button id="moveSlideRight" class="moveSlide moveSlideRight"></button>
</ul>
I have a simple image slider, with pagination controls.
I have coded it to add and remove an "active" class on the pagination
buttons on click. I would also like them to have the active class when the corresponding slide is showing.
How can I modify my code to achieve this?
<div id="slideshow">
<ul id="slides">
<li class="slide showing">
<div class="slide-description">
<h1 class="slide-title">All-in-one EV charging solution.</h1>
<p> Easy to use. Connected with smart charging capabilities. Our charging stations can be used at home,
work or in public.</p>
</div>
</li>
<li class="slide">
<div class="slide-description">
<h1 class="slide-title">Charging at work- a case study.</h1>
<p>In this new series of charging case studies, we dive into into the reasons why EV-Box partners are taking the green route.</p>
</div>
</li>
<li class="slide"> <div class="slide-description">
<h1 class="slide-title">Finding the best solution for your charging routine.</h1>
<p>
This whitepaper highlights the key answers that will guide you to acharging solution that best serves your needs.
</p>
</div>
</li>
</ul>
<button class="controls" id="previous"></button>
<button class="controls" id="next"></button>
<div id="pagination"></div>
var slides = document.querySelectorAll('#slides .slide'); // get all the slides
var currentSlide = 0;
var slideInterval = setInterval(nextSlide, 6000);
function nextSlide() {
goToSlide(currentSlide + 1);
}
function previousSlide() {
goToSlide(currentSlide - 1);
}
function goToSlide(n) {
slides[currentSlide].className = 'slide';
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].className = 'slide showing';
}
//Previous and Next controls
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function() {
nextSlide();
};
previous.onclick = function() {
previousSlide();
};
//Pagination controls
var p = document.getElementById('pagination');
var phtml = '';
for(var i = 0; i < slides.length; i++) {
phtml += '<button></button>'; // create the pagination buttons for each slide
}
p.innerHTML = phtml; //insert the html for the buttons
var pbuttons = p.querySelectorAll('button'); // grab all the buttons
var activeButton = null; // reference to active button
for(var i = 0; i < pbuttons.length; i++) {
pbuttons[i].onclick = (function(n) {
return function() {
if(activeButton)
activeButton.classList.remove('active'); // delete class from old active button
activeButton = this;// change ref, this is current button
activeButton.classList.add('active');// add class for new
goToSlide(n);
};
})(i);
}
#slider {
min-height: 400px;
position: relative;
#slides {
min-height: 400px;
padding: 0;
margin: 0;
list-style-type: none;
.slide {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0;
z-index: 1;
min-height: 400px;
box-sizing: border-box;
background: $black;
color: $white;
display: flex;
align-items: center;
-webkit-justify-content: flex-end;
justify-content: flex-end;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
transition: opacity 1s;
&.showing {
opacity: 1;
z-index: 2;
}
&:nth-of-type(1) {
#include backImage('../images/evbox1.jpg');
}
&:nth-of-type(2){
#include backImage('../images/evbox2.jpg');
}
&:nth-of-type(3) {
#include backImage('../images/evbox3.jpg');
}
}
.slide-description {
width: 500px;
.slide-title {
width: 90%;
font-family: 'Open Sans', sans-serif;
font-size: 44px;
text-shadow: 0 2px 3px rgba($black, .2);
line-height: 1.1em;
margin-bottom: 10px;
}
p {
margin-bottom: 15px;
width: 90%;
font-size: 20px;
font-family: 'Open Sans', sans-serif;
font-weight: 300;
text-shadow: 0 2px 3px rgba($black, .2);
}
.btn {
#include button($blue, $font-color, $shadow-color);
}
}
#include respond-to($mobile) {
#media only screen and (max-width: $mobile) {
.slide:nth-of-type(3) {
background-position: left 0;
}
.slide-description {
height: 100%;
width: 100%;
padding: 8em 5em;
position: static;
text-align: center;
.slide-title {
font-size: 30px;
width: 100%;
}
.btn {
padding: 8px 16px;
}
}
p {
display: none;
}
}
}
}
}
/*Previous and Next Controls*/
.controls {
position: absolute;
top: 42%;
z-index: 10;
background: url('http://www.ev-box.com/Evbox-EN/includes/themes/evbox/assets/images/sprites#2x.png') no-repeat;
height: 50px;
width: 30px;
background-size: 369px 240px;
outline: 0;
border: 0;
cursor: pointer;
}
#previous {
right: 10px;
background-position: -50px -121px;
}
#next {
left: 10px;
background-position: -16px -121px;
}
// Pagination
#pagination {
position: absolute;
bottom: 30px;
right: 50%;
z-index: 10;
button {
border-radius: 50%;
border: 1px solid $white;
background-color: $white;
opacity: .8;
width: 14px;
height: 14px;
min-height: 14px;
border-width: 0;
margin-right: 5px;
&.active {
width: 15px;
height: 15px;
min-height: 15px;
border: 1px solid $white;
background-color: $primary;
opacity: 1;
&:focus {
outline: 0;
}
}
}
}
I updated the javascript as shown below. Use this in your code pen. you can see the diffrence. If you click next and previous button the corresponding pagination will be highlighted by using this javascript
document.addEventListener("DOMContentLoaded", function() {
var slides = document.querySelectorAll('#slides .slide'); // get all the slides
const totalSlides = 2 // Total number of slides count
var currentSlide = 0; // current slide
var previousSlide = totalSlides;
// var slideInterval = setInterval(nextSlide, 1000);
function nextSlide() {
previousSlide = currentSlide
if(totalSlides > currentSlide){
currentSlide += 1
}
else currentSlide = 0
goToSlide();
}
function PreviousSlide() {
if(currentSlide == 0){
previousSlide = currentSlide
currentSlide = totalSlides
}
else{
previousSlide = currentSlide
currentSlide -=1
}
goToSlide();
}
function goToSlide() {
slides[previousSlide].className = 'slide';
slides[currentSlide].className = 'slide showing';
var currentSlideButton = "button"+currentSlide
var previousSlideButton = "button"+previousSlide
document.getElementById(currentSlideButton).classList.add('active');
document.getElementById(previousSlideButton).classList.remove('active');
}
//Previous and Next controls
var next = document.getElementById('next');
var previous = document.getElementById('previous');
next.onclick = function() {
PreviousSlide();
};
previous.onclick = function() {
nextSlide();
};
//Pagination controls
var p = document.getElementById('pagination');
var phtml = '';
for(var i = 0; i < slides.length; i++) {
phtml += '<button id=button'+i+'></button>'; // create the pagination buttons for each slide
}
p.innerHTML = phtml; //insert the html for the buttons
var pbuttons = p.querySelectorAll('button'); // grab all the buttons
var activeButton = null; // reference to active button
for(var i = 0; i < pbuttons.length; i++) {
pbuttons[i].onclick = (function(n) {
return function() {
if(activeButton)
activeButton.classList.remove('active'); // delete class from old active button
activeButton = this;// change ref, this is current button
activeButton.classList.add('active');// add class for new
goToSlide(n);
};
})(i);
}
goToSlide();// Initialising goToSlide method
});
I want to fade in div by clicking menu buttons.
I implemented it anyway but when I switch the views very quickly, it sometimes flashes and the behavior is kind of rough or jumpy..or I don't know how to say..it's not smooth anyways.
https://jsfiddle.net/eLbze55d/12/
Any advice would be appreciated.
var m_menu = document.getElementById('m_menu');
var menu = document.getElementById('menu');
var m_staff = document.getElementById('m_staff');
var staff = document.getElementById('staff');
var m_access = document.getElementById('m_access');
var access = document.getElementById('access');
m_menu.addEventListener('click', function() {
menu.style.zIndex = 1;
staff.style.zIndex = 0;
access.style.zIndex = 0;
menu.style.webkitAnimationName = 'fadein';
menu.style.webkitAnimationDuration = "1000ms";
});
menu.addEventListener('webkitAnimationEnd', function() {
menu.style.opacity = 1;
staff.style.opacity = 0;
access.style.opacity = 0;
menu.style.webkitAnimationName = '';
});
m_staff.addEventListener('click', function() {
staff.style.zIndex = 1;
menu.style.zIndex = 0;
access.style.zIndex = 0;
staff.style.webkitAnimationName = 'fadein';
staff.style.webkitAnimationDuration = "1000ms";
});
staff.addEventListener('webkitAnimationEnd', function() {
staff.style.opacity = 1;
menu.style.opacity = 0;
access.style.opacity = 0;
staff.style.webkitAnimationName = '';
});
m_access.addEventListener('click', function() {
access.style.zIndex = 1;
menu.style.zIndex = 0;
staff.style.zIndex = 0;
access.style.webkitAnimationName = 'fadein';
access.style.webkitAnimationDuration = "1000ms";
});
access.addEventListener('webkitAnimationEnd', function() {
access.style.opacity = 1;
menu.style.opacity = 0;
staff.style.opacity = 0;
access.style.webkitAnimationName = '';
});
#-webkit-keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}
html,body { height:100%; }
#main {
height:100%;
color: white;
}
.content{
font-size: 50pt;
}
#menu {
z-index: 1;
opacity: 1;
position: absolute;
top: 0;
left: 0;
background-image: url(https://snap-photos.s3.amazonaws.com/img-thumbs/960w/7B62IKGVF4.jpg);
height: 100%;
width: 100%;
}
#staff {
z-index: 0;
opacity: 0;
position: absolute;
top: 0;
left: 0;
background-image: url(https://snap-photos.s3.amazonaws.com/img-thumbs/960w/FRHYAEUPIN.jpg);
height: 100%;
width: 100%;
}
#access{
z-index: 0;
position: absolute;
top: 0;
left: 0;
background-image: url(https://snap-photos.s3.amazonaws.com/img-thumbs/960w/MGWWJDK49D.jpg);
height: 100%;
width: 100%;
}
#site_menu {
z-index: 2;
position: absolute;
bottom: 2%;
left: 3.5%;
font-size: 20pt;
display: flex;
justify-content: start;
}
#site_menu > div {
cursor: pointer;
margin: 20px;
display: flex;
align-items: center;
justify-content: start;
}
<div id="main">
<div id="menu" class="content">THIS IS MENU</div>
<div id="staff" class="content">THIS IS STAFF</div>
<div id="access" class="content">THIS IS ACCESS</div>
<div id="site_menu">
<div id="m_menu" class="menuelem">Menu</div>
<div id="m_staff" class="menuelem">Staff</div>
<div id="m_access" class="menuelem">Access</div>
</div>
</div>