CSS Animation Won't Play Per Click - javascript

I built a carousel for some images. I need my 'next' and 'previous' buttons to use the CSS animation that I assigned them in my javascript function for their event listeners.The animation will only play for one click, and when the buttons are clicked again to navigate the carousel the animation doesn't play. I need the buttons to grow and shrink for every click.
Here's the CSS:
.carousel-actions {
position: absolute;
display: flex;
justify-content: space-between;
width: 105%;
top: 30%;
}
.carousel-actions button {
padding: 30px 50px;
background-color: rgba(255, 255, 255, 0.329);
font-weight: 900;
cursor: pointer;
border-radius: 100px;
border: 0;
font-size: 60px;
color: black;
outline: none;
}
#keyframes grow {
0% {
transform: scale(1);
}
50% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
}
Here's the HTML:
<div class="carousel-actions">
<button id="prev" aria-label="Previous Slide"><</button>
<button id="next" aria-label="Next Slide">></button>
</div>
Here's the JS:
const slides = document.querySelectorAll(".carousel-item");
const totalSlides = slides.length;
let slidePosition = 0;
console.log(totalSlides);
const next = document.getElementById("next");
const prev = document.getElementById("prev");
function hideAllSlides() {
for (const slide of slides) {
slide.classList.remove("carousel-item-visible") &&
slide.classList.add("carousel-item-hidden");
}
}
function nextSlide() {
hideAllSlides();
if (slidePosition === totalSlides - 1) {
slidePosition = 0;
} else {
slidePosition++;
}
slides[slidePosition].classList.add("carousel-item-visible");
next.style.animation = "grow 1s";
}
function prevSlide() {
hideAllSlides();
if (slidePosition === 0) {
slidePosition = totalSlides - 1;
} else {
slidePosition--;
}
slides[slidePosition].classList.add("carousel-item-visible");
prev.style.animation = "grow 1s";
}
next.addEventListener("click", nextSlide);
prev.addEventListener("click", prevSlide);

The problem is seen because once the system has played the animation it thinks 'well, I've played it'. Setting it to the same again does not make it play again.
To get round this you can unset the animation when it has finished.
In your code add an event listener for the animationend event.
Here's a simplified example:
const div = document.querySelector('div');
div.addEventListener('click', function() { div.style.animationName='grow';});
div.addEventListener('animationend', function() { div.style.animationName='';});
div {
width: 100px;
height: 100px;
background-color: blue;
animation-duration: 1s;
animation-iteration-count: 1;
}
#keyframes grow {
0% {
transform: scale(1);
}
50% {
transform: scale(1.3);
}
100% {
transform: scale(1);
}
<div></div>

Related

Having a tremendous amount of difficulty getting play buttons to work from inside their own container, separate from the HTML

This code I am trying to get working has the play buttons at the bottom inside their own container.
How the code works is, click on a button, and then a video should appear on the screen.
To test jsitor code, press run, not update.
https://jsitor.com/MIYiywN4HC / https://jsfiddle.net/kxhyLdr8/
<div class="playButtonContainer">
<button class="playa cover" type="button"></button>
<button class="playb cover" type="button"></button>
<button class="playc cover" type="button"></button>
<button class="playd cover" type="button"></button>
<button class="playe cover" type="button"></button>
<button class="playf cover" type="button"></button>
<button class="playg cover" type="button"></button>
<button class="playh cover" type="button"></button>
<button class="playi cover" type="button"></button>
</div>
What is weird about the above code is that after clicking on the buttons, no errors are appearing, when there should be.
By errors I mean, in the console log, I was referring to, usually errors will appear in there if something is broken. I am stuck trying to figure out how to get the broken code working.
For comparison, here is a demo code of it working with the play buttons not inside their own container.
The only difference between the demo code and the code I am working on is that in the code I am working on, the play buttons are inside their own container.
To test jsitor code, press run, not update.
https://jsitor.com/qTWoiuHp7z / https://jsfiddle.net/24xf0avp/
The only difference between the working and non working example is just the extra layer of HTML.
Nothing was touched in any other part of the code.
Would anyone be able to check and see if their able that code to work, the code with the play buttons in their own container?
No one has been able to figure out how that would be done, getting the play buttons to work inside their own container.
I was told by my instructor, the code needs to work with the play buttons inside their own container, separate from the HTML.
I have no idea how that would be done, and because there are no errors appearing in the code, that further confuses me.
I was told this:
The problem here is inside the body of the function showCover, which
adds the class active and calls the function show (which removes the
class hide) to and from the parent of the button , instead of the
.container element where it should be.
Could it be that you just need to extend your JS code so that it
reaches the inner html node?
on the button click event it probably captures the parent element
instead of the target element?
Binding of the click of the play button
So you should either wrap them together, put the play button in the
outer, and then go to the closest('.outer') then
querySelector('.video') or whatever you want to do. Or put an
attribute on the .playa button (eg data-player-id="play1") that you
can use to directly find from the click and then use this to call the
.container.play1 element
Here I created a very simple demo with one button.
<div class="playButtonContainer">
<button class="playa cover" type="button"></button>
</div>
Here is the working demo code with only 1 button.
https://jsitor.com/Qer_1Oi9Jv / https://jsfiddle.net/1bmrwuzn/
Here is the broken code with only 1 button.
https://jsitor.com/D38vgjs3g / https://jsfiddle.net/gt57k29h/
What is meant by broken is, is that it is not working or functioning the same way as the demo code I provided.
Smaller, reproducible example code:
const manageCover = (function makeManageCover() {
const config = {};
const body = document.body;
let currentPlayButton = {};
function show(el) {
el.classList.remove("hide");
}
function hide(el) {
el.classList.add("hide");
}
function hideAll(elements) {
elements.forEach(hide);
}
function resetBackground(backgroundSelector) {
const allBackgrounds = document.querySelectorAll(backgroundSelector);
function hideBackground(background) {
background.classList.add("bg1");
}
allBackgrounds.forEach(hideBackground);
}
function resetButtons(buttonSelector) {
const allButtons = document.querySelectorAll(buttonSelector);
function hideButton(button) {
button.classList.add("isOpen");
}
allButtons.forEach(hideButton);
}
function resetPage() {
resetBackground("body");
resetButtons(".outer");
}
function markAsPlayed(played) {
played.classList.add("played");
}
function showCover(playButton) {
hideAll(config.containers);
resetPage();
markAsPlayed(playButton);
const cover = playButton.parentElement;
cover.classList.add("active");
show(cover);
}
function animationEndHandler(evt) {
const animationName = evt.animationName;
if (animationName === "initial-fade") {
body.classList.remove("initial-fade");
showCover(currentPlayButton);
}
}
function coverClickHandler(evt) {
currentPlayButton = evt.currentTarget;
body.classList.add("initial-fade");
}
function addClickToButtons(playButtons) {
playButtons.forEach(function playButtonHandler(playButton) {
playButton.addEventListener("click", coverClickHandler);
});
}
function addCoverHandler(coverSelector, handler) {
const cover = document.querySelector(coverSelector);
cover.addEventListener("click", handler);
}
function init(selectors) {
config.containers = document.querySelectorAll(selectors.container);
const playButtons = document.querySelectorAll(selectors.playButton);
addClickToButtons(playButtons);
body.addEventListener("animationend", animationEndHandler);
}
return {
addCoverHandler,
init
};
}());
const manageUI = (function makeManageUI() {
const body = document.body;
const players = [];
function findPlayers() {
const allCovers = document.querySelectorAll(".cover");
const allWrappers = document.querySelectorAll(".wrap");
allCovers.forEach(function addToPlayers(cover, index) {
players.push({
"cover": cover,
"wrapper": allWrappers[index]
});
});
}
// inline arrow function, direct return
function getWrapper(cover) {
const index = players.findIndex(
(player) => player.cover === cover
);
return players[index].wrapper;
}
function resetBackground(backgroundSelector) {
const allBackgrounds = document.querySelectorAll(backgroundSelector);
function showBackground(background) {
background.classList.remove("bg1");
}
allBackgrounds.forEach(showBackground);
}
function resetCurtains(curtainSelector) {
const allCurtains = document.querySelectorAll(curtainSelector);
function showCurtain(curtain) {
curtain.classList.remove("active");
}
allCurtains.forEach(showCurtain);
}
function showAllButtons(buttonSelector) {
const allButtons = document.querySelectorAll(buttonSelector);
function showButton(button) {
button.classList.remove("hide");
}
allButtons.forEach(showButton);
}
function resetButtons(buttonSelector) {
const allButtons = document.querySelectorAll(buttonSelector);
function showButton(button) {
button.classList.remove("isOpen");
}
allButtons.forEach(showButton);
}
function animationEndHandler(evt) {
const animationName = evt.animationName;
console.log(animationName);
if (animationName === "fadingOut") {
fadeReset();
}
}
function fadeReset() {
body.classList.remove("fadingOut");
resetBackground("body");
resetCurtains(".with-curtain");
showAllButtons(".hide");
resetButtons(".outer");
}
function resetPage() {
body.classList.add("fadingOut");
}
function exitClickHandler() {
resetPage();
}
function addClickToExit(exitButtons) {
exitButtons.forEach(function addExitButtonHandler(exitButtons) {
exitButtons.addEventListener("click", exitClickHandler);
});
}
function addExitHandlers(callback) {
const resetVideo = document.querySelectorAll(".exit");
resetVideo.forEach(function resetVideoHandler(video) {
video.addEventListener("click", callback);
});
}
function init() {
findPlayers();
const exitButtons = document.querySelectorAll(".exit");
addClickToExit(exitButtons);
body.addEventListener("animationend", animationEndHandler);
}
return {
addExitHandlers,
getWrapper,
init
};
}());
const videoPlayer = (function makeVideoPlayer() {
const tag = document.createElement("script");
tag.src = "https://www.youtube.com/player_api";
const firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
function onPlayerReady(event) {
const player = event.target;
player.setVolume(100);
}
function onPlayerStateChange(event) {
const player = event.target;
return player;
}
function addPlayer(video, playerOptions) {
playerOptions.videoId = playerOptions.videoId || video.dataset.id;
playerOptions.events = playerOptions.events || {};
playerOptions.events.onReady = onPlayerReady;
playerOptions.events.onStateChange = onPlayerStateChange;
const player = new YT.Player(video, playerOptions);
return player;
}
return {
addPlayer
};
}());
const managePlayer = (function makeManagePlayer() {
const playerVars = {
autoplay: 0,
controls: 1,
disablekb: 1,
enablejsapi: 1,
fs: 0,
iv_load_policy: 3
};
const defaults = {
height: 360,
host: "https://www.youtube-nocookie.com",
playerVars,
width: 640
};
function show(el) {
el.classList.remove("hide");
}
function combinePlayerOptions(opts1 = {}, opts2 = {}) {
const combined = Object.assign({}, opts1, opts2);
Object.keys(opts1).forEach(function checkObjects(prop) {
if (typeof opts1[prop] === "object") {
combined[prop] = Object.assign({}, opts1[prop], opts2[prop]);
}
});
return combined;
}
function createPlayer(videoWrapper, playerOptions = {}) {
const video = videoWrapper.querySelector(".video");
const options = combinePlayerOptions(defaults, playerOptions);
return videoPlayer.addPlayer(video, options);
}
function playerAdder(wrapper, playerOptions) {
return function addPlayerCallback() {
initPlayer(wrapper, playerOptions);
};
}
function removePlayer(wrapper) {
wrapper.player.destroy();
delete wrapper.player;
console.log("removePlayer");
}
function removePlayerHandler(evt) {
const el = evt.target;
const container = el.closest(".container");
const wrapper = container.querySelector(".wrap");
if (wrapper.player) {
return removePlayer(wrapper);
}
}
function initPlayer(wrapper, playerOptions) {
show(wrapper);
const player = createPlayer(wrapper, playerOptions);
wrapper.player = player;
}
return {
adder: playerAdder,
removePlayerHandler
};
}());
const players = (function coverUIPlayerFacade() {
function addPlayer(coverSelector, playerOptions) {
const cover = document.querySelector(coverSelector);
const wrapper = manageUI.getWrapper(cover);
const callback = managePlayer.adder(wrapper, playerOptions);
manageCover.addCoverHandler(coverSelector, callback);
}
function init() {
manageCover.init({
container: ".container",
playButton: ".cover"
});
manageUI.init({});
manageUI.addExitHandlers(managePlayer.removePlayerHandler);
}
return {
add: addPlayer,
init
};
}());
players.init();
function onYouTubeIframeAPIReady() {
players.add(".playa", {});
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
background: #353198;
}
.initial-fade {
animation: initial-fade 500ms ease forwards;
}
#keyframes initial-fade {
to {
opacity: 0;
}
}
.initial-fade,
.fadingOut {
cursor: default;
}
.initial-fade .cover,
.initial-fade .cover * {
pointer-events: none !important;
}
.container {
display: flex;
justify-content: center;
position: relative;
/*z-index: 2;*/
}
.container.active {
flex: 1 0 0;
}
/*body.*/
.bg1 {
animation: fadeInBody 5s ease 0s forwards;
animation-delay: 0s;
opacity: 0;
}
#keyframes fadeInBody {
100% {
opacity: 1;
}
}
/*body.*/
.bg1 .with-curtain:before {
content: "";
position: fixed;
/*z-index: 1;*/
top: 0;
left: 0;
right: 0;
bottom: 0;
background-size: 165px 165px;
background-image:
}
.playButtonContainer {
display: flex;
flex-wrap: wrap;
min-height: 100%;
margin: auto;
justify-content: center;
align-content: center;
width: 290px;
gap: 10px;
animation: fadeInButtons 3s ease 0s forwards;
}
#keyframes fadeInButtons {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.outer.isOpen {
width: auto;
}
.fadingOut .isOpen {
animation: fadingOut 1s;
animation-delay: 11.3s;
}
#keyframes fadingOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
.inner-container {
display: none;
}
/* when container is active hide the cssPlay and show the inner container*/
.container.active .cover {
display: none;
}
.container.active .inner-container {
display: flex;
}
.container.active .inner-container.curtain {
display: block;
}
.cover {
-webkit-appearance: none;
appearance: none;
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 90px;
height: 90px;
border-radius: 50%;
cursor: pointer;
border: 9px solid blue;
background: transparent;
filter: drop-shadow(3px 3px 3px rgba(0, 0, 0, 0.7));
}
.cover::before {
content: "";
width: 0;
height: 0;
border-top: 20px solid transparent;
border-bottom: 20px solid transparent;
border-left: 27px solid blue;
transform: translateX(4px);
}
.cover:hover {
box-shadow: 0 0 0 5px rgba(43, 179, 20, 0.5);
}
.cover:focus {
outline: 0;
box-shadow: 0 0 0 5px rgba(0, 255, 255, 0.5);
}
.played {
border-color: green;
}
.played::before {
border-left-color: green;
}
.curtain {
flex: 1 0 0;
margin: auto;
max-width: 642px;
/*box-shadow: inset 0 -2px 0px 0px #0a0a0a;*/
border: 20px solid black;
border-radius: 3.2px;
border-color: #000 #101010 #000 #101010;
position: relative;
}
.curtain::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
right: -2px;
bottom: -2px;
background: radial-gradient(circle, transparent 0% 35%, #0a0a0a 35%);
}
.ratio-keeper {
position: relative;
height: 0;
padding-top: 56.25%;
margin: auto;
overflow: hidden;
border: 1px solid #333;
}
.video-frame {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
iframe {
user-select: none;
}
.panel-left,
.panel-right {
position: absolute;
height: 100%;
width: calc(50% + 1px);
/* rounding error fix */
top: 0%;
transition: all ease 10s;
/*background-image: url("https://picsum.photos/600");
background-size: cover;
background-repeat: no-repeat;
background-position: center;*/
overflow: hidden;
}
.panel-left {
left: 0;
/*background-color: rgb(91, 96, 106);*/
}
.panel-right {
right: 0;
/*background-color: rgb(229, 211, 211);*/
}
.panel-left::before,
.panel-right::before {
content: "";
position: absolute;
height: 100%;
width: 200%;
top: 0;
left: 0;
background-size: auto;
background-repeat: no-repeat;
background-position: 0 0;
}
.panel-right::before {
left: -100%;
}
.container.active .curtain .panel-left {
animation: curtain1-open 8s forwards 520ms;
}
#keyframes curtain1-open {
to {
transform: translateX(calc(-100% - 1px));
}
}
.container.active .curtain .panel-right {
animation: curtain2-open 8s forwards 520ms;
}
#keyframes curtain2-open {
to {
transform: translateX(calc(100% + 1px));
}
}
.fadingOut .container.active .curtain .panel-left {
animation: curtain1-close 8s ease forwards;
transform: translateX(calc(-100% - 1px));
animation-delay: 3.3s;
}
#keyframes curtain1-close {
to {
transform: translateX(0);
}
}
.fadingOut .container.active .curtain .panel-right {
animation: curtain2-close 8s ease forwards;
transform: translateX(calc(100% + 1px));
animation-delay: 3.3s;
}
#keyframes curtain2-close {
to {
transform: translateX(0);
}
}
.exit {
position: absolute;
top: auto;
bottom: -47px;
margin: auto;
right: 0;
left: 0;
width: 47px;
height: 47px;
cursor: pointer;
background: black;
border-radius: 50%;
border: 5px solid red;
animation: fadeInExit 1s forwards;
opacity: 0;
pointer-events: none;
}
.exit::before,
.exit::after {
content: "";
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
margin: auto;
width: 100%;
height: 5px;
background: red;
transform: rotate(45deg);
transition: all 1s ease;
}
.exit::after {
transform: rotate(-45deg);
}
#keyframes fadeInExit {
99% {
pointer-events: none;
}
100% {
pointer-events: initial;
opacity: 1;
}
}
.exit:hover::before,
.exit:hover::after,
.fadingOut .exit::before,
.fadingOut .exit::after {
background: green;
}
.fadingOut .exit {
animation: fadeOutExit 8s forwards;
pointer-events: none;
opacity: 1;
}
#keyframes fadeOutExit {
to {
opacity: 0;
}
}
.hide {
display: none;
}
<div class="outer">
<div class="container play1 with-curtain">
<div class="inner-container curtain curtain1">
<div class="ratio-keeper">
<div class="wrap">
<div class="video video-frame" data-id="CHahce95B1g"></div>
</div>
<div class="sliding-panels">
<div class="panel-left"></div>
<div class="panel-right"></div>
</div>
</div>
<button class="exit" type="button" title="Exit" aria-label="Close"></button>
</div>
</div>
</div>
<div class="playButtonContainer">
<button class="playa cover" type="button" aria-label="Open"></button>
</div>

slowly scrolling bug, div stay on page but shouldn't

I have three div boxes in a row, and on scroll, they should show slowly from the side, but when I scroll up slowly and a little after they show up, the left and right boxes for some reason stay on the page.
My function showBox3 writes in console "false" and classList where is "show" class, but this class shouldn't be there.
Actually, my code works when I scroll normally but when I stop scrolling slightly above the limit, the left and right boxes stay on page.
And one more problem is when "topBox" is a little below the limit, and I scroll up just a little more, but still below the limit, boxes quickly remove from the page and show up again.
const box21 = document.querySelector(".box21");
const box22 = document.querySelector(".box22");
const box23 = document.querySelector(".box23");
var trigger = window.innerHeight * 0.8;
window.addEventListener("scroll", showBox2);
function showBox2() {
var check;
const topBox = box22.getBoundingClientRect().top;
if (trigger > topBox) {
box22.classList.add("show");
check = true;
} else {
box22.classList.remove("show");
check = false;
}
showBox1(check);
showBox3(check);
}
function showBox1(ch) {
if (ch == true) {
setTimeout(() => {
box21.classList.add("show");
}, 400);
} else {
box21.classList.remove("show");
}
}
function showBox3(ch) {
if (ch == true) {
setTimeout(function () {
box23.classList.add("show");
}, 700);
} else {
box23.classList.remove("show");
console.log(box23.classList);
console.log(ch);
}
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.box1 {
height: 110vh;
background-color: aqua;
display: flex;
align-items: center;
justify-content: center;
}
/* I have a bug in box 2 */
.box2 {
height: 60vh;
width: 100%;
background-color: #ddd;
display: flex;
align-items: center;
justify-content: space-around;
}
.box2>div {
height: 70%;
width: 27%;
background-color: black;
}
.box21 {
transform: translateX(-140%) rotate(-45deg);
transition: transform 1.4s ease;
}
.box21.show {
transform: translateX(0%) rotate(0deg);
}
.box22 {
transform: translateX(340%) rotate(+45deg);
transition: transform 0.8s ease;
}
.box22.show {
transform: translateX(0%) rotate(0deg);
}
.box23 {
transform: translateX(340%) rotate(-45deg);
transition: transform 1.8s ease;
}
.box23.show {
transform: translateX(0%) rotate(0deg);
}
/* this part below is not important */
.box3 {
height: 60vh;
width: 100%;
background-color: cornflowerblue;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="css.css" />
</head>
<body>
<div class="box1">
<h1>Scroll down</h1>
</div>
<div class="box2">
<div class="box21"></div>
<div class="box22"></div>
<div class="box23"></div>
</div>
<div class="box3"></div>
</body>
<script src="js.js"></script>
</html>

How to show loader and animation once per session?

I've coded a personal portfolio website and added all the things I've wanted to add. Now, I am just cleaning it up and working on the UX/ IX stuff to make it more pleasant to navigate and interact with.
With that said, I am trying to make my loader/ loader animation (the spinning bubbles AND the "fade in" aspect) only occur once, when you FIRST enter the website! This is what I have so far, and it works rather nicely. HOWEVER, when you refresh the page or try to navigate back to the homepage from my projects page, there is a rather long waiting screen and then the "fade in" animation comes back.
If anyone could help me, I am trying to make it so that when you refresh or nav back to the home page AFTER you've already seen the loader/ animation, the home page instantly loads without delay, loader, or animation/
Thank you
const navToggle = document.querySelector('.nav-toggle');
const navLinks = document.querySelectorAll('.nav__link')
const loader = document.querySelector('.loader');
const main = document.querySelector('.main');
function init() {
setTimeout(() => {
loader.style.opacity = 0;
loader.style.display = 'none';
main.style.display = 'block';
setTimeout(() => (main.style.opacity = 1), 50);
},2000);
}
init();
navToggle.addEventListener('click', () => {
document.body.classList.toggle('nav-open');
});
navLinks.forEach(link => {
link.addEventListener('click', () => {
document.body.classList.remove('nav-open');
})
})
window.addEventListener("load", function () {
if (!sessionStorage.viewed){
const loader = document.querySelector(".loader");
loader.className += " hidden";
sessionStorage.viewed = 1;
}else{
const loader = document.querySelector(".loader");
loader.style.display = "none";
}
})
.loader {
position: fixed;
z-index: 999;
overflow: show;
margin: auto;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 50px;
height: 50px;
text-align: center;
transform-origin: bottom center;
animation: rotate 3s linear infinite;
}
.circle {
display: inline-block;
background-color: #16e0bd;
height: 50px;
width: 50px;
border-radius: 50%;
transform: scale(0);
animation: grow 1.5s linear infinite;
margin: -10px;
}
.circle:nth-child(2) {
background-color: #303030;
animation-delay: 0.75s;
}
#keyframes rotate {
to {
transform: rotate(360deg);
}
}
#keyframes grow {
50% {
transform: scale(1);
}
}
<div class="loader">
<div class="circle"></div>
<div class="circle"></div>
</div>
<div class="main" >

Why add and remove function is not working at the same time in a function in JavaScript?

I have started learning JS recently and am stuck here. I have created a dice game where images change themselves randomly when a button is clicked.
The images just get changed from one to another. I want to give a rolling effect to them. So, I have added animation for them that they change angles in both X-axis and Y-axis. It works on the first click but later doesn't.
So I had added classList.add() to give the animation and classList.remove() to remove but the remove function doesn't work.
This is HTML code:
function roll() {
document.querySelectorAll("img")[0].classList.add("rollEffect");
document.querySelectorAll("img")[1].classList.add("rollEffect");
var randomNumber1 = Math.floor(Math.random() * 6 + 1);
var randomNumber2 = Math.floor(Math.random() * 6 + 1);
var randomImage1 = "dice" + randomNumber1 + ".png";
var randomImage2 = "dice" + randomNumber2 + ".png";
document.querySelectorAll("img")[0].setAttribute("src", randomImage1);
document.querySelectorAll("img")[1].setAttribute("src", randomImage2);
if (randomNumber1 > randomNumber2)
document.querySelector("h1").innerHTML = "Player1 wins!!!";
else
if (randomNumber2 > randomNumber1)
document.querySelector("h1").innerHTML = "Player2 wins!!!";
else
document.querySelector("h1").innerHTML = "DRAW!!!";
document.querySelectorAll("img")[0].classList.remove("rollEffect");
document.querySelectorAll("img")[1].classList.remove("rollEffect");
}
.btn {
background-color: #8843F2;
border: 0;
border-radius: 20px;
color: #ffffff;
font-family: 'Indie Flower', cursive;
margin: 0 50px;
padding: 1% 2%;
}
.container {
width: 70%;
margin: auto;
text-align: center;
}
.dice {
text-align: center;
display: inline-block;
}
#keyframes rollClick {
9% {
transform: rotateX(30deg) rotateY(30deg)
}
18% {
transform: rotateX(60deg) rotateY(60deg)
}
28% {
transform: rotateX(90deg) rotateY(90deg)
}
37% {
transform: rotateX(120deg) rotateY(120deg)
}
46% {
transform: rotateX(150deg) rotateY(150deg)
}
55% {
transform: rotateX(180deg) rotateY(180deg)
}
65% {
transform: rotateX(210deg) rotateY(210deg)
}
76% {
transform: rotateX(240deg) rotateY(240deg)
}
85% {
transform: rotateX(270deg) rotateY(270deg)
}
90% {
transform: rotateX(300deg) rotateY(300deg)
}
95% {
transform: rotateX(330deg) rotateY(330deg)
}
100% {
transform: rotateX(360deg) rotateY(360deg)
}
}
.rollEffect {
animation-name: rollClick;
animation-duration: 0.1s;
}
body {
background-color: #F9D371;
}
img {
width: 80%;
}
<div class="container">
<h1>Roll us</h1>
<div class="dice">
<p>Player 1</p>
<img class="img1" src="dice6.png">
</div>
<div class="dice">
<p>Player 2</p>
<img class="img2" src="dice6.png">
</div>
<button class="btn" onclick="roll()">Roll</button>
</div>
The javascript code that adds the rolling animation class runs separate from any animation durations.
It will run as quickly as the performance of the device allows.
In your js code it will:
add the .rollEffect class to both images.
set a new image url.
set text with the result of the game
remove the .rollEffect class from both images.
This all happens as fast as possible, we're talking micro/nano seconds.
So the animation does get applied, each time, and gets removed each time. so fast you can't even see the animation.
You have to wait a bit before removing the animation class. so the animation has time to run before it's removed.
This can be achived with setTimeout
For example:
setTimeout(() => {
document.querySelectorAll("img")[0].classList.remove("rollEffect");
document.querySelectorAll("img")[1].classList.remove("rollEffect");
}, 100); // <--- 100 here will execute the code in the callback after 100ms, the same as the animation time.
function roll() {
document.querySelectorAll("img")[0].classList.add("rollEffect");
document.querySelectorAll("img")[1].classList.add("rollEffect");
var randomNumber1 = Math.floor(Math.random() * 6 + 1);
var randomNumber2 = Math.floor(Math.random() * 6 + 1);
var randomImage1 = `http://placekitten.com/g/${50*randomNumber1}/300`;
var randomImage2 = `http://placekitten.com/g/200/${50*randomNumber2}`;
document.querySelectorAll("img")[0].setAttribute("src", randomImage1);
document.querySelectorAll("img")[1].setAttribute("src", randomImage2);
if (randomNumber1 > randomNumber2)
document.querySelector("h1").innerHTML = "Player1 wins!!!";
else
if (randomNumber2 > randomNumber1)
document.querySelector("h1").innerHTML = "Player2 wins!!!";
else
document.querySelector("h1").innerHTML = "DRAW!!!";
setTimeout(() => {
document.querySelectorAll("img")[0].classList.remove("rollEffect");
document.querySelectorAll("img")[1].classList.remove("rollEffect");
}, 100);
}
.btn {
background-color: #8843F2;
border: 0;
border-radius: 20px;
color: #ffffff;
font-family: 'Indie Flower', cursive;
margin: 0 50px;
padding: 1% 2%;
}
.container {
width: 70%;
margin: auto;
text-align: center;
}
.dice {
text-align: center;
display: inline-block;
}
#keyframes rollClick {
9% {
transform: rotateX(30deg) rotateY(30deg)
}
18% {
transform: rotateX(60deg) rotateY(60deg)
}
28% {
transform: rotateX(90deg) rotateY(90deg)
}
37% {
transform: rotateX(120deg) rotateY(120deg)
}
46% {
transform: rotateX(150deg) rotateY(150deg)
}
55% {
transform: rotateX(180deg) rotateY(180deg)
}
65% {
transform: rotateX(210deg) rotateY(210deg)
}
76% {
transform: rotateX(240deg) rotateY(240deg)
}
85% {
transform: rotateX(270deg) rotateY(270deg)
}
90% {
transform: rotateX(300deg) rotateY(300deg)
}
95% {
transform: rotateX(330deg) rotateY(330deg)
}
100% {
transform: rotateX(360deg) rotateY(360deg)
}
}
.rollEffect {
animation-name: rollClick;
animation-duration: 0.1s;
}
body {
background-color: #F9D371;
}
img {
width: 150px;
height: 150px;
}
<div class="container">
<h1>Roll us</h1>
<div class="dice">
<p>Player 1</p>
<img class="img1" src="http://placekitten.com/g/200/300">
</div>
<div class="dice">
<p>Player 2</p>
<img class="img2" src="http://placekitten.com/g/300/200">
</div>
<button class="btn" onclick="roll()">Roll</button>
</div>

How do I add a scrolling animation to my slideshow?

I've built a pretty basic HTML/CSS/JS slideshow. When I click the button on the right, the slide switches to the next slide, and when I click the button on the left, the slide switches to the previous slide.
However, I would like to add in a scrolling animation to make the slideshow feel less rigid; when I press the button on the right, I want the slide to 'slide' in from the right, and when I press the button on the left I want it to slide in from the left.
I've been researching possible ways to do this and came across CSS animations, specifically the w3.css framework (https://www.w3schools.com/w3css/w3css_animate.asp), but am not sure how I would implement this given that my slideshow already makes use of classes in order to switch between slides.
Here is my code:
var content = ["Slide 1", "Slide 2", "Slide 3"];
var style = ["background-color: blue;", "background-color: red;", "background-color: green;"];
var index = 0;
function next() {
if (index == (content.length - 1)) {
index = 0
} else {
index = index + 1
}
document.getElementById("slide").innerHTML = content[index];
document.getElementById("slideshow").style = style[index];
}
function back() {
if (index == 0) {
index = (content.length - 1)
} else {
index = index - 1
}
document.getElementById("slide").innerHTML = content[index];
document.getElementById("slideshow").style = style[index];
}
.slideshow {
position: relative;
height: 170px;
color: white;
background-color: blue;
}
.slideshow p {
position: absolute;
width: 100%;
margin-top: 0;
margin-bottom: 0;
text-align: center;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
}
.slideshow button {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 25px;
}
<!DOCTYPE html>
<html lang="en">
<body>
<div class="slideshow" id="slideshow">
<p id="slide">Slide 1</p>
<button onclick="back()" style="left: 0">❮</button>
<button onclick="next()" style="right: 0">❯</button>
</div>
</body>
</html>
Thanks in advance.
you can style a next and prev classes with CSS and then toggle them with js like this snippet
var content = ["Slide 1", "Slide 2", "Slide 3"];
var style = ["background-color: blue;", "background-color: red;", "background-color: green;"];
var index = 0;
function next() {
const slide = document.getElementById("slide");
if (index == (content.length - 1)) {
index = 0;
} else {
index = index + 1;
}
// wipe out class
slide.className = '';
// add next class
setTimeout(() => slide.classList.add('next'), 0);
slide.innerHTML = content[index];
slide.style = style[index];
}
function back() {
const slide = document.getElementById("slide");
if (index == 0) {
index = (content.length - 1);
} else {
index = index - 1;
}
// wipe out class
slide.className = '';
// add prev class
setTimeout(() => slide.classList.add('prev'), 0);
slide.innerHTML = content[index];
slide.style = style[index];
}
.slideshow {
position: relative;
height: 170px;
color: white;
overflow: hidden;
}
.slideshow p {
position: absolute;
width: 100%;
height: 100%;
line-height: 170px;
margin-top: 0;
margin-bottom: 0;
text-align: center;
top: 50%;
transform: translate(-50%, -50%);
font-size: 20px;
background-color: blue;
}
.slideshow button {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 25px;
}
.prev {
animation: prev 1s ease-in-out forwards;
}
.next {
animation: next 1s ease-in-out forwards;
}
#keyframes prev {
from {
left: -150%;
}
to {
left: 50%;
}
}
#keyframes next {
from {
right: -150%;
}
to {
right: -50%;
}
}
<div class="slideshow" id="slideshow">
<p id="slide" class="next">Slide 1</p>
<button onclick="back()" style="left: 0">❮</button>
<button onclick="next()" style="right: 0">❯</button>
</div>

Categories

Resources