How to show loader and animation once per session? - javascript

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" >

Related

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>

Transition for Text on reset

I tried to find a solution for this one but I can't. There s something that I keep missing... not sure what.
I have a project that when I click a image, the image will get an translate and also a text description.
The text description has a smooth transition and it looks cool.
Well, the question is.. how to make the reset(click on body or another image) to have the same transition for that text description?
This is how it look right now: https://im3.ezgif.com/tmp/ezgif-3-5150d8ffbf.gif
function resetEnlargeEntityImage() {
if(enlargedEntity != null) {
enlargedEntity.style.transform = null;
enlargedEntity.style.transition = null;
enlargedEntity.classList.add("planet-svg-hover");
document.getElementById("planets-description-paragraph").innerHTML = null;
document.getElementById("planets-description-paragraph").classList.add("entity-description-js");
document.getElementById("planets-description-paragraph").classList.remove("entity-description-appear-js");
}
}
function enlargeEntityImage(clickedImage, clickedImageId) {
let mediaQuery = window.matchMedia('(max-width: 375px)');
if(mediaQuery.matches) {
window.location.href = `./${planetsName[clickedImageId]}.html`;
} else {
resetEnlargeEntityImage();
var xToMove = 260 - 130 * clickedImageId; //260
clickedImage.style.transform = "translate(" + xToMove + "px, 320px) scale(4.0)";
clickedImage.style.transition = "transform 1s ease-in-out";
clickedImage.classList.remove("planet-svg-hover");
document.getElementById("planets-description-paragraph").innerHTML = descriptionSpaceObjects[clickedImageId];
document.getElementById("planets-description-paragraph").classList.remove("entity-description-js");
document.getElementById("planets-description-paragraph").classList.add("entity-description-appear-js");
enlargedEntity = clickedImage;
}
}
.planets-description {
color: white;
font-family: "Barlow";
font-size: 30px;
width: 600px;
position: relative;
top: 100px;
left: 700px;
}
.entity-description-js {
position: absolute;
transition-delay: 1s;
transition: 1s;
width: 600px;
left: 0;
visibility: hidden;
opacity: 0;
}
.entity-description-appear-js {
position: absolute;
transition: 1s;
width: 600px;
left: 100px;
visibility: visible;
opacity: 1;
}
<div class="planets-description">
<p id="planets-description-paragraph" class="entity-description-js"></p>
</div>
The Code you provided isnt showing anything, but maybe you could try uesing the "transition" property in css.

Change z-index of stacked divs when scrolling

I have 2 divs with position:fixed, top:0, left: 0 and 100% in height and width on top of each other.
I'm trying to be able to scroll through the divs by changing the z-index, as I scroll. I have no idea how to achieve this.
In other words, trying to create a scrollable page without having to visually scroll vertically or horizontally. Instead staying on the same spot and reveal the content by changing z-index, if that makes sense.
Thank you in advance.
You can do it as you asked:
const sections = document.querySelectorAll('section');
let active = 0,
delayTimer = null;
addEventListener('wheel', e => {
// If we just scrolled, don't do anything
if (delayTimer !== null) return;
// Apply the section change
const upwards = e.deltaY < 0;
if ((upwards && active > 0) || (!upwards && active < sections.length - 1)) {
// Make the current one go one level below
const previous = sections[active];
previous.classList.add('previous');
previous.classList.remove('active');
// In 500ms, the animation will be over, hide it
setTimeout(() => previous.classList.remove('previous'), 500);
// Move the new current one to the front
active += upwards ? -1 : 1;
sections[active].classList.add('active');
}
// Prevent that from happening again during the next 500ms
// so that we don't scroll multiple sections at once
delayTimer = setTimeout(() => { delayTimer = null; }, 500);
});
body { background: #222; }
section {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: #555; color: #fff;
font-family: Arial, Helvetica, sans-serif;
text-align: center;
display: none;
}
section:nth-child(1) { background: #6A46F2; }
section:nth-child(2) { background: #F28B77; }
section:nth-child(3) { background: #A1BA44; }
section:nth-child(4) { background: #52bc93; }
section.previous, section.active {
display: block;
z-index: 1;
}
section.active {
z-index: 2;
animation: fadeIn .4s ease;
}
#keyframes fadeIn {
from { opacity: 0; transform: scale(.6); }
to { opacity: 1; transform: scale(1); }
}
<section class="active"><h1>Section A</h1><p>Some content A</p></section>
<section><h1>Section B</h1><p>Some content B</p></section>
<section><h1>Section C</h1><p>Some content C</p></section>
<section><h1>Section D</h1><p>Some content D</p></section>

CSS Animation Won't Play Per Click

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>

CSS slide in from left animation

I'm working on a slideshow and it works, except for the animations. The animation for sliding out works fine but the animation for sliding in from the left does not. The left margin gets set to 0% but there is no animation, even though it is set to -100% at first.
Javascript:
var images = [
'http://i.imgur.com/ByyUANz.png',
'http://i.imgur.com/S5FfOOB.png',
'http://i.imgur.com/EuefPdv.png',
'http://i.imgur.com/Ucvm4pJ.png',
'http://i.imgur.com/pK5WBHN.png',
'http://i.imgur.com/nuOLVpy.png'
]
function slideShow(startAt){
var holder = document.getElementById("currentImage");
var img = document.createElement("img");
img.src = images[startAt];
holder.appendChild(img);
nextPicture(startAt, img);
}
function nextPicture(current, currentElement){
var holder = document.getElementById("currentImage");
setTimeout(function(){
currentElement.className = "translateLeft";
current += 1;
var img = document.createElement("img");
img.src = images[current];
img.style.marginLeft = "-100%";
holder.appendChild(img);
img.className = "translateIn";
if (current == 5){
current = -1;
nextPicture(current, img);
} else {
nextPicture(current, img);
}
}, 5000)
}
slideShow(0);
CSS:
.translateLeft {
transition: 3s;
margin-left: 100% !important;
}
.translateIn {
transition: 3s;
margin-left: 0% !important;
}
Here is a solution for you.
https://jsfiddle.net/smaefwrp/2/
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
html,
body,
img {
position: absolute;
top:0;
left: 0;
margin: 0;
padding: 0;
height: 100%;
overflow-x: hidden;
}
#currentImage {
height: 100%;
width: 1920px;
}
.translateOrigin {
transition: none;
transform: translate3d(-100%, 0, 0) !important;
}
.translateLeft {
transition: transform 3s;
transform: translate3d(100%, 0, 0) !important;
}
.translateIn {
transition: transform 3s;
transform: translate3d(0, 0, 0) !important;
}
</style>
</head>
<body>
<div id="currentImage">
</div>
<div id="buttons">
</div>
<script type="text/javascript">
var images = [
'http://i.imgur.com/ByyUANz.png',
'http://i.imgur.com/S5FfOOB.png',
'http://i.imgur.com/EuefPdv.png',
'http://i.imgur.com/Ucvm4pJ.png',
'http://i.imgur.com/pK5WBHN.png',
'http://i.imgur.com/nuOLVpy.png'
];
var imageEle = [];
var currImage = 0;
var holder = document.getElementById("currentImage");
function imagesPreload() {
for (var i = 0; i < images.length; i++) {
var img = new Image();
img.src = images[i];
img.className = "translateOrigin";
holder.appendChild(img);
imageEle.push(img);
}
}
imagesPreload();
document.onkeydown = function(event){
if(event.keyCode === 13) {
nextPicture();
}
};
function slideShow(startAt) {
var holder = document.getElementById("currentImage");
imageEle[currImage].className = "translateIn";
nextPicture();
}
function nextPicture() {
setTimeout(function () {
var img = imageEle[currImage];
img.addEventListener("transitionend", transitionEnd, false);
img.className = "translateLeft";
if (currImage == 5) {
currImage = 0;
} else {
currImage++;
}
imageEle[currImage].className = "translateIn";
/* Reset the image to original position */
function transitionEnd() {
img.className = "translateOrigin";
img.removeEventListener("transitionend", transitionEnd, false);
nextPicture();
}
}, 5000)
}
slideShow(currImage);
</script>
</body>
</html>
To create a nice slideshow I suggest to use css transform property rather than the margin. The idea is to create the placeholder element currentImage with relative position, and then create all images inside it with position set to absolute. Then by default all images are translated out of the placeholder element, and adding/removing classes show and hide you can place them inside the view and then outside of it, like this:
var images = [
'http://i.imgur.com/ByyUANz.png',
'http://i.imgur.com/S5FfOOB.png',
'http://i.imgur.com/EuefPdv.png',
'http://i.imgur.com/Ucvm4pJ.png',
'http://i.imgur.com/pK5WBHN.png',
'http://i.imgur.com/nuOLVpy.png'
];
// Get the holder
var holder = document.getElementById("currentImage");
// Create the images
images.forEach(function(url) {
var img = document.createElement("img");
img.src = url;
holder.appendChild(img);
});
// Image counter
var counter = 0;
// Slide show interval
var slideshow = setInterval(function() {
// When we reach the end of images we shut down the slide show
// or you can reset the counter to start over
if(counter === images.length) {
clearInterval(slideshow);
return;
}
// Get all images
var nodes = holder.getElementsByTagName("img");
// Hide previous image
if(nodes[counter - 1]) {
nodes[counter - 1].className = "hide";
}
// Show next image
nodes[counter].className = "show";
counter++;
}, 2500);
#currentImage {
background: gray;
width: 300px;
height: 300px;
margin: 0 auto;
position: relative;
overflow: hidden;
}
#currentImage img {
width: 100%;
position: absolute;
transform: translateX(-110%);
-webkit-transition: -webkit-transform 1.0s ease 0s;
-moz-transition: -moz-transform 1.0s ease 0s;
-o-transition: -o-transform 1.0s ease 0s;
transition: transform 1.0s ease 0s;
}
#currentImage img.show {
transform: translateX(0%);
}
#currentImage img.hide {
transform: translateX(110%);
}
<div id="currentImage">
</div>
You can try something like:
// HTML
<div id="currentImage">
<div class="window">
<div class="image-list">
<div>
<img src="http://i.imgur.com/ByyUANz.png" />
</div>
<div>
<img src="http://i.imgur.com/S5FfOOB.png" />
</div>
<div>
<img src="http://i.imgur.com/EuefPdv.png" />
</div>
<div>
<img src="http://i.imgur.com/Ucvm4pJ.png" />
</div>
<div>
<img src="http://i.imgur.com/pK5WBHN.png" />
</div>
<div>
<img src="http://i.imgur.com/nuOLVpy.png" />
</div>
</div>
</div>
</div>
And CSS
// CSS
img {
height: 50px;
width: 50px
}
.window {
position: absolute;
height: 50px;
width: 50px;
border: 2px solid red;
overflow: hidden
}
div {
display: inline-block
}
.image-list {
list-style-type: none;
display: inline-block;
padding-left: 0px;
margin: 0px;
width: 350px;
animation: slidingli 30s ;
}
#keyframes slidingli {
0% {
transform: translateX(0px)
}
16% {
transform: translateX(-50px)
}
32% {
transform: translateX(-100px)
}
48% {
transform: translateX(-150px)
}
64% {
transform: translateX(-200px)
}
80% {
transform: translateX(-250px)
}
100% {
transform: translateX(-300px)
}
}
Checkout this fiddle. Also there are many libraries out there which provide what need For example: http://fotorama.io/customize/autoplay/

Categories

Resources