re-setting Interval after clearInterval - javascript

So I have an Interval that activates a function function Seifenblasen_blasen() every 100ms. I stop this Interval or function with clear Interval by running function function Bouny_Ball() when clicking the Button Bounce.
Now when I click the Button Bubble again it should start generating Bubbles every 100ms. But it doesn't, as it was cleared AND is not in the function Seifenblasen_blasen() therefore it still is cleared. But neither putting it in the function Seifenblasen_blasen() or making a seperate function and calling it with the same button press makes a difference. This is where I need your Help.
Thanks in advance.
This is not the only problem tho. I will make separate questions for these but if you have time feel free to ask and i'll provide them in a comment. I need to wait 90 minutes after all.
whole code
Function Seifenblasen_blasen() with Interval:
function Seifenblasen_blasen(){
document.getElementById("screen2").style.display = "none";
document.getElementById("screen").style.display = "block";
const section = document.querySelector('#screen')
const createElement = document.createElement('spawn')
var size = Math.random() * 60;
createElement.style.width = 30 + size + 'px';
createElement.style.height = 30 + size + 'px';
createElement.style.left = Math.random() * innerWidth + "px";
section.appendChild(createElement);
setTimeout(() => {
createElement.remove()
},8000)
}
const Blaseninterval = setInterval(Seifenblasen_blasen, 100)
Resulting CSS of function Seifenblasen_blasen()
#screen {
width: 100%;
height: 90vh;
overflow: hidden;
background-image: linear-gradient(#008CBA, #030a19);
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
#screen spawn {
position: absolute;
bottom: -80px;
background: transparent;
border-radius: 50%;
pointer-events: none;
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.5);
animation: animate 4s linear infinite;
}
#screen spawn:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
transform: scale(0.25) translate(-70%, -70%);
background: radial-gradient(#fff, transparent);
opacity: 0.6;
border-radius: 50%;
}
#keyframes animate {
0% {
transform: translateY(0%);
opacity: 1;
}
99% {
opacity: 1;
}
100% {
transform: translateY(-2000%);
opacity: 0;
}
}
#screen span {
margin-top: 700px;
font-size: 1em;
color: #333;
margin: 0 auto;
font-family: consolas;
background-color: #1F69FA;
border: none;
position: absolute;
}
clearence of Interval:
function Bouncy_Ball() {
clearInterval(Blaseninterval);
document.getElementById("screen").style.display = "none";
document.getElementById("screen2").style.display = "block";
}

Related

Hiding/Showing CSS elements does not work?

THE WHOLE CODE IN JSFIDDLE
I have been struggling to effectively remove the code and css created in the function Seifenblasen_blasen()
function Seifenblasen_blasen(){
btn1.style.display = 'none';
document.getElementById("text").innerHTML="Bubble"
const section = document.querySelector('section')
const createElement = document.createElement('spawn')
var size = Math.random() * 60;
createElement.style.width = 30 + size + 'px';
createElement.style.height = 30 + size + 'px';
createElement.style.left = Math.random() * innerWidth + "px";
section.appendChild(createElement);
setTimeout(() => {
createElement.remove()
},8000)
}
const Blaseninterval = setInterval(Seifenblasen_blasen, 100)
created CSS:
section {
width: 100%;
height: 100vh;
overflow: hidden;
background: #1F69FA;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
section.text{
font-size: 10em;
color: #333;
margin: 0 auto;
text-align: center;
font-family: consolas;
background-color:#1F69FA;
pointer-events: none;
border: none;
}
section spawn {
position: absolute;
bottom: -80px;
background: transparent;
border-radius: 50%;
pointer-events: none;
box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.5);
animation: animate 4s linear infinite;
}
section spawn:before {
content: '';
position: absolute;
width: 100%;
height: 100%;
transform: scale(0.25) translate(-70%, -70%);
background: radial-gradient(#fff, transparent);
opacity: 0.6;
border-radius: 50%;
}
#keyframes animate {
0% {
transform: translateY(0%);
opacity: 1;
}
99% {
opacity: 1;
}
100% {
transform: translateY(-2000%);
opacity: 0;
}
section span {
margin-top: 700px;
font-size: 1em;
color: #333;
margin: 0 auto;
font-family: consolas;
background-color: #1F69FA;
border: none;
position: absolute;
}
HTML:
<section id="section">
<div class="content">
<button id="btn"></button>
<button id="btn1"></button>
</div>
</section>
to then execute the next function function next(). This removal is needed because when I don't remove the elements from the first function the second wont work. I could just do document.head.innerHTML = "" but that would then also remove the css needed for the button appearing in the next function. So then I tried to make variables with const
const btn = document.getElementById('text');
const btn1 = document.getElementById('text1');
const section = document.querySelector('section')
// in function Seifenblasen_blasen()
btn1.style.display = 'none';
// in function next()
section.style.display = 'none';
btn.style.display = 'none';
btn1.style.display = 'block';
to hide and show only parts of the css without removing the css entirely to keep the styling intact, but now nothing works anymore.(the button on the next Screen doesn't show up at all and the first button does not contain any styling) My endgoal is that I can essentially switch between two screens one showing the bubbles and one the bouncy balls and when I click on the button it goes on. (for example start is bubbles. I click -> Bounce, click again -> back to Bubbles and so on)

Restrict creation of new divs to a specific area

I have a small page. Divas in the form of circles are created here every certain time.
They spawn in random places.
As can be seen even on the buttons and slightly outside the page.
The question is. Is it possible to make a box that does not touch the buttons, and that the circles are created within this box?
This should be done as a border with a certain extension, but specifying everything in pixels is not an option, it will be bad for different screens.
I created such a frame, replaced document.body.appendChild(div);
on the document.getElementById("spawnRadius").appendChild(div);
It seems that they should appear within this frame, but no, all the same throughout the page.
I also tried instead of whole page height and width document.documentElement.clientWidth use the width and height of the desired border spawnRadius.width
But now all my circles do not appear randomly, but at the beginning of this block in one place.
I tried to see these values ​​through console.log
console.log(documentHeight);
console.log(documentWidth);
But getting there undefined
PS. Demo watch in full page
//timer
var minutesLabel = document.getElementById("minutes");
var secondsLabel = document.getElementById("seconds");
var totalSeconds = 0;
setInterval(setTime, 1000);
function setTime() {
++totalSeconds;
secondsLabel.innerHTML = pad(totalSeconds % 60);
minutesLabel.innerHTML = pad(parseInt(totalSeconds / 60));
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
//create circle
var widthHeight = 65;
var margin = 25;
var delta = widthHeight + margin;
var spawnRadius = document.getElementById("spawnRadius");
let clicks = 0;
function createDiv(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = spawnRadius.height;
var documentWidth = spawnRadius.width;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.borderColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.borderColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
const nodes = document.querySelectorAll('.animation');
for(let i = 0; i < nodes.length; i++) {
nodes[i].addEventListener('click', (event) => {
event.target.style.animation = 'Animation 200ms linear';
setTimeout(() => {
event.target.style.animation = '';
}, 220); });
}
$(div).click(function() {
$('#clicks').text(++clicks);
$(this).fadeOut();
});
document.getElementById("spawnRadius").appendChild(div);
}
let i = 0;
const oneSecond = 600;
setInterval(() => {
i += 1;
createDiv(`circle${i}`);
}, oneSecond);
html, body {
width: 100%;
height: 100%;
margin: 0;
background: #0f0f0f;
}
.back {
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 25px;
letter-spacing: 2px;
word-spacing: 2px;
color: #ffffff;
text-shadow: 0 0 5px #ffffff, 0 0 10px #ffffff, 0 0 20px #ffffff, 0 0 40px #ff00de, 0 0 80px #ff00de, 0 0 90px #ff00de, 0 0 100px #ff00de, 0 0 150px #ff00de;
font-weight: 700;
text-decoration: none;
font-style: italic;
font-variant: normal;
text-transform: lowercase;
position: absolute;
top: 25%;
left: 2%;
user-select: none;
z-index: 999;
}
.panel {
color: #0f0f0f;
font-size: 40px;
z-index: 999;
position: absolute;
cursor: default;
user-select: none;
color: #0f0f0f;
}
.score {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.time {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.circle {
width: 60px;
height: 60px;
border-radius: 60px;
background-color: #0f0f0f;
border: 3px solid #000;
margin: 20px;
position: absolute;
}
#keyframes Animation {
0% {
transform: scale(1);
}
50% {
transform: scale(.8);
}
100% {
transform: scale(1);
}
}
#spawnRadius {
top: 55%;
height: 650px;
width: 1000px;
left: 50%;
white-space: nowrap;
position: absolute;
transform: translate(-50%, -50%);
background: #0f0f0f;
border: 2px solid #ebc6df;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="panel">
<span class="score">Score: <a id="clicks">0</a></span>
<span class="time">Time: <label id="minutes">00</label>:<label id="seconds">00</label></span>
</span>
back
<div id="spawnRadius"></div>
To answer your main question, the getBoundingClientRect method can be used to retrieve the current bounding rectangle of an element, using which you can determine where the valid spawn areas are.
When choosing a valid placement, only consider the width and height of the container element, since the coordinates of child elements are relative to its parent. You also need to take into account the size of the elements being spawned, so the valid range of the x position for example is 0 to containerWidth - circleWidth.
The circles also had a CSS margin associated with them, which would offset them past their absolute coordinates.
There are a few other issues with the code though which you may run into later on:
There was an odd mix of jQuery and standard JavaScript calls, so if you're familiar with native JavaScript methods then it's likely simpler to stick with those and remove the dependency on jQuery.
For example, there were two click event handlers on each circle, one to add the CSS animation and another to increment the score. These can be combined into a single function.
The bounce out animation and the jQuery fade out can also be combined by adding opacity values into the animation start and end keyframes.
There was a loop in the createDiv function which added another click event handler to every circle element rather than just to the newly created element. This may have originally necessitated the jQuery click handler outside of that loop, since otherwise the score counter would have been incremented multiple times.
It was also possible to click the circles multiple times before the animation was complete (hence adding multiple points), which was likely not intended. Adding a simple Boolean clicked flag can avoid this.
Once the fade animation completed, the circle element itself was still on the page, it just had a display of none so wouldn't be visible. Over time, this would cause slowdowns on lower end hardware since there would be many DOM elements still sitting in memory that were no longer required. As such, it's best to remove elements from the DOM once they're no longer needed using removeChild. You had the right idea by removing the animation after the animation completed.
Here's the amended code:
var minutesLabel = document.getElementById("minutes");
var secondsLabel = document.getElementById("seconds");
var clickEl = document.getElementById("clicks");
var totalSeconds = 0;
let clicks = 0;
setInterval(setTime, 1000);
function setTime() {
++totalSeconds;
secondsLabel.innerText = pad(totalSeconds % 60);
minutesLabel.innerText = pad(parseInt(totalSeconds / 60));
}
function pad(val) {
var valString = val + "";
if (valString.length < 2) {
return "0" + valString;
} else {
return valString;
}
}
var spawnRadius = document.getElementById("spawnRadius");
var spawnArea = spawnRadius.getBoundingClientRect();
const circleSize = 66; // Including borders
//create circle
function createDiv(id, color) {
let div = document.createElement('div');
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.borderColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.borderColor = color;
}
// Randomly position circle within spawn area
div.style.top = `${Math.floor(Math.random() * (spawnArea.height - circleSize))}px`;
div.style.left = `${Math.floor(Math.random() * (spawnArea.width - circleSize))}px`;
div.classList.add("circle", "animation");
// Add click handler
let clicked = false;
div.addEventListener('click', (event) => {
if (clicked) { return; } // Only allow one click per circle
clicked = true;
div.style.animation = 'Animation 200ms linear forwards';
setTimeout(() => { spawnRadius.removeChild(div); }, 220);
clickEl.innerText = ++clicks
});
spawnRadius.appendChild(div);
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createDiv(`circle${i}`);
}, oneSecond);
html, body {
width: 100%;
height: 100%;
margin: 0;
background: #0f0f0f;
}
.back {
font-family: "Comic Sans MS", cursive, sans-serif;
font-size: 25px;
letter-spacing: 2px;
word-spacing: 2px;
color: #ffffff;
text-shadow: 0 0 5px #ffffff, 0 0 10px #ffffff, 0 0 20px #ffffff, 0 0 40px #ff00de, 0 0 80px #ff00de, 0 0 90px #ff00de, 0 0 100px #ff00de, 0 0 150px #ff00de;
font-weight: 700;
text-decoration: none;
font-style: italic;
font-variant: normal;
text-transform: lowercase;
position: absolute;
top: 25%;
left: 2%;
user-select: none;
z-index: 999;
}
.panel {
color: #0f0f0f;
font-size: 40px;
z-index: 999;
position: absolute;
cursor: default;
user-select: none;
color: #0f0f0f;
}
.score {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.time {
border: 1px solid #ffffff;
padding: 5px;
background-color: #ffffff;
border-radius: 40px 10px;
}
.circle {
width: 60px;
height: 60px;
border-radius: 60px;
background-color: #0f0f0f;
border: 3px solid #000;
position: absolute;
}
#keyframes Animation {
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(.8);
}
100% {
transform: scale(1);
opacity: 0;
}
}
#spawnRadius {
top: 55%;
height: 650px;
width: 1000px;
left: 50%;
white-space: nowrap;
position: absolute;
transform: translate(-50%, -50%);
background: #0f0f0f;
border: 2px solid #ebc6df;
}
<span class="panel">
<span class="score">Score: <a id="clicks">0</a></span>
<span class="time">Time: <label id="minutes">00</label>:<label id="seconds">00</label></span>
</span>
back
<div id="spawnRadius"></div>

Why the z-index value does upset the functioning of my animation?

I'm trying recoding the https://www.orizon.co/ following dot. The code I've written to asure the dot rising effect when the pointer fly over some elements seems correct, but when the dot's z-index is higher than the flew over element's one, there is a kind of bug than make me crazy.
class CursorFollower {
constructor() {
this.follower = document.getElementById("cursor-follower");
this.topGap = 12;
this.leftGap = 4;
window.addEventListener("mousemove", this.follow.bind(this));
this.eventsSet();
}
// The function doing the dot follows the pointer
follow() {
setTimeout(function () {
cursorFollower.follower.style.left = (this.clientX - cursorFollower.topGap) + "px";
cursorFollower.follower.style.top = (this.clientY - cursorFollower.leftGap) + "px";
}.bind(window.event), 100);
}
eventsSet() {
// Adding events to button
var button = document.querySelector(".follower-over");
button.addEventListener("pointerenter", this.overOn.bind(this));
button.addEventListener("pointerleave", this.overOff.bind(this));
}
overOn() {
// The effects to apply when the pointer flies over the button
this.follower.style.opacity = 0.3;
this.follower.style.width = "50px";
this.follower.style.height = "50px";
this.follower.style.backgroundColor = "black";
this.topGap = 25;
this.leftGap = 25;
}
overOff() {
// The effects to apply when the pointer leave the button
this.follower.style.opacity = 1;
this.follower.style.width = "7px";
this.follower.style.height = "7px";
this.follower.style.backgroundColor = "rgba(42, 0, 212, 1)";
this.topGap = 12;
this.leftGap = 4;
}
}
let cursorFollower = new CursorFollower();
/* Some styling */
.contact-us{
padding: 25px 40px;
width: 200px;
display: flex;
align-items: center;
color: white;
background-color: #2b00d4 ;
height: 60px;
position: relative;
z-index: 1;
}
#cursor-follower{
z-index: 999;
position: fixed;
background-color: #2b00d4;
height: 7px;
width: 7px;
border-radius: 50%;
transition: opacity 0.3s , width 0.3s , height 0.3s, background-color 0.3s;
}
<div id="cursor-follower"></div>
<div class="contact-us follower-over">
<p>CONTACT US</p>
</div>
When the button's z-index is higher than the dot's one, the effects works. Else, it bugs
This is because your follower element is getting under cursor, triggering overOff than when its shrinks it triggers overOn and so on.
The simplest solution is to add pointer-events: none; into the follower so it doesn't trigger overOn/overOff:
class CursorFollower {
constructor() {
this.follower = document.getElementById("cursor-follower");
this.topGap = 12;
this.leftGap = 4;
window.addEventListener("mousemove", this.follow.bind(this));
this.eventsSet();
}
// The function doing the dot follows the pointer
follow() {
setTimeout(function() {
cursorFollower.follower.style.left = (this.clientX - cursorFollower.topGap) + "px";
cursorFollower.follower.style.top = (this.clientY - cursorFollower.leftGap) + "px";
}.bind(window.event), 100);
}
eventsSet() {
// Adding events to button
var button = document.querySelector(".follower-over");
button.addEventListener("pointerenter", this.overOn.bind(this));
button.addEventListener("pointerleave", this.overOff.bind(this));
}
overOn() {
// The effects to apply when the pointer flies over the button
this.follower.style.opacity = 0.3;
this.follower.style.width = "50px";
this.follower.style.height = "50px";
this.follower.style.backgroundColor = "black";
this.topGap = 25;
this.leftGap = 25;
}
overOff() {
// The effects to apply when the pointer leave the button
this.follower.style.opacity = 1;
this.follower.style.width = "7px";
this.follower.style.height = "7px";
this.follower.style.backgroundColor = "rgba(42, 0, 212, 1)";
this.topGap = 12;
this.leftGap = 4;
}
}
let cursorFollower = new CursorFollower();
/* Some styling */
.contact-us {
padding: 25px 40px;
width: 200px;
display: flex;
align-items: center;
color: white;
background-color: #2b00d4;
height: 60px;
position: relative;
z-index: 1;
}
#cursor-follower {
pointer-events: none; /* added */
z-index: 999;
position: fixed;
background-color: #2b00d4;
height: 7px;
width: 7px;
border-radius: 50%;
transition: opacity 0.3s, width 0.3s, height 0.3s, background-color 0.3s;
}
<div id="cursor-follower"></div>
<div class="contact-us follower-over">
<p>CONTACT US</p>
</div>
However there is even simpler solution with much less javascript:
window.addEventListener("mousemove", e => {
setTimeout(s => {
document.documentElement.style.setProperty("--cursorX", e.clientX + "px");
document.documentElement.style.setProperty("--cursorY", e.clientY + "px");
}, 100);
});
/* Some styling */
:root
{
--cursorX: -100px;
--cursorY: -100px;
}
.contact-us {
padding: 25px 40px;
width: 100px;
display: flex;
align-items: center;
color: white;
background-color: #2b00d4;
height: 40px;
position: relative;
z-index: 1;
}
.cursor-follower {
--size: 7px;
--gapLeft: 12px;
--gapTop: 4px;
pointer-events: none;
position: fixed;
background-color: #2b00d4;
width: var(--size);
height: var(--size);
border-radius: 50%;
transition: opacity 0.3s, width 0.3s, height 0.3s, background-color 0.3s;
top: calc(var(--cursorY) - var(--gapTop));
left: calc(var(--cursorX) - var(--gapLeft));
}
.follower-over:hover~.cursor-follower {
--size: 50px;
--gapLeft: 25px;
--gapTop: 25px;
opacity: 0.3;
background-color: black;
z-index: 2;
}
/* extra */
.follower-over.green:hover~.cursor-follower {
background-color: green;
opacity: 0.7;
--size: 80px;
--gapLeft: 40px;
--gapTop: 40px;
}
.contact-us:not(.follower-over) {
background-color: pink;
}
.contact-us {
display: inline-block;
margin: 1em;
}
<div class="contact-us follower-over">
<p>CONTACT US</p>
</div>
<div class="contact-us follower-over">
<p>Another button</p>
</div>
<div class="contact-us">
<p>No follower</p>
</div>
<div class="contact-us follower-over green">
<p>Large green</p>
</div>
<div class="cursor-follower"></div>
The only caveat with this method is the .cursor-follower must be last element and has the same parent as all .follower-over elements

Wordpress Divi - problem with inserting code for Animated Cursor

This is my new clear site: www.talas.me
And this is what i want to copy: Awesome Link Hover Effect / Animated Cursor
(function () {
const link = document.querySelectorAll('nav > .hover-this');
const cursor = document.querySelector('.cursor');
const animateit = function (e) {
const span = this.querySelector('span');
const { offsetX: x, offsetY: y } = e,
{ offsetWidth: width, offsetHeight: height } = this,
move = 25,
xMove = x / width * (move * 2) - move,
yMove = y / height * (move * 2) - move;
span.style.transform = `translate(${xMove}px, ${yMove}px)`;
if (e.type === 'mouseleave') span.style.transform = '';
};
const editCursor = e => {
const { clientX: x, clientY: y } = e;
cursor.style.left = x + 'px';
cursor.style.top = y + 'px';
};
link.forEach(b => b.addEventListener('mousemove', animateit));
link.forEach(b => b.addEventListener('mouseleave', animateit));
window.addEventListener('mousemove', editCursor);
})();
html, body {
margin: 0;
padding: 0;
cursor: none;
}
.nav-wrapper {
width: 100%;
height: 100vh;
background: #161616;
}
nav {
width: 100%;
margin: 0 auto;
text-align: center;
position: absolute;
top: 50%;
}
.hover-this {
transition: all 0.3s ease;
}
span {
display: inline-block;
font-family: "Monument Extended";
font-weight: 300;
color: #fff;
font-size: 36px;
text-transform: uppercase;
pointer-events: none;
transition: transform 0.1s linear;
}
.cursor {
pointer-events: none;
position: fixed;
padding: 0.3rem;
background-color: #fff;
border-radius: 50%;
mix-blend-mode: difference;
transition: transform 0.3s ease;
}
.hover-this:hover ~ .cursor {
transform: translate(-50%, -50%) scale(8);
}
#media(min-width: 900px) {
nav {
display: flex;
justify-content: space-around;
}
}
#media(max-width: 900px) {
nav {
top: 30%;
}
.hover-this {
width: 100%;
padding: 20px 0;
display: inline-block;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="nav-wrapper">
<nav>
<span>Home</span>
<span>Our Story</span>
<span>Studio</span>
<span>Contact</span>
<div class="cursor"></div>
</nav>
</div>
There is problem somewhere and i can't figure out where. As you can see now (when i copy this code correctly) we can't see the cursor on my site.
Can someone tell me what is the problem and how to fix it?
This is very important for my site because the site will be black and white, and this cursor effect is so important to me.
Thank you!
as far as i know that Divi theme provide a option in theme settings where we can add custom jQuery or javascript so you can directly add over there
this below link may help you to resolve issue
https://divi.space/tutorials/how-to-add-javascript-and-jquery-to-divi/

Compounding Value within an object used to slide dot across the page incrementally

I am unable to get a variable to function properly as the translateX value within my object. I am wanting to make the dot scroll across the page each time the next button is clicked. My code is only able to move it back and forth for the first step.
I am new to the animation API, and I have already made this work with CSS transitions but I am trying to get a good handle on the API.
html:
<div class="progress__container">
<div class="progress__bar">
<div id="progress__fill" class="step1"></div>
<div class="circ" id="circ__1"></div>
<div class="circ" id="circ__2"></div>
<div class="circ" id="circ__3"></div>
<div class="circ" id="circ__4"></div>
<div id="progress__dot" class="prog__1"></div>
</div>
<div class="backBar"></div>
<div class="flexrow">
<span class="stepName">Account</span>
<span class="stepName">Frequency</span>
<span class="stepName">Amount</span>
<span class="stepName">Taxes</span>
</div>
<div class="button__container">
<button class="buttonStep" id="back">Back</button>
<button class="buttonStep is-active" id="next">Next</button>
</div>
</div>
js:
// give a starting value for the transformation
var startVal = 0;
// define the keyframes
var moveDot = [
{ transform: `translateX(${startVal}px)`},
{ transform: `translateX(${startVal + 190}px)`}
];
// definte the timing
var dotTiming = {
duration: 400,
fill: "forwards",
easing: 'ease-in',
}
// make the animation happen
var movingDot = document.getElementById("progress__dot").animate(
moveDot,
dotTiming
);
// pause the animation until called
movingDot.pause();
// on click fire the animation
document.getElementById('next').addEventListener('click', function() {
movingDot.playbackRate = 1;
if (startVal <= 380) {
movingDot.play();
startVal += 190;
}
});
document.getElementById('back').addEventListener('click', function() {
movingDot.playbackRate = -1;
if (startVal >= 0) {
movingDot.play();
startVal -= 190;
}
});
css:
#progress__fill {
height:2px;
position: absolute;
top: 7px;
left: 0;
background-color: darkred;
}
#progress__dot {
background-color: darkred;
color: #fff;
border-radius: 50%;
height: 8px;
width: 8px;
position: absolute;
text-align:center;
line-height: 8px;
padding: 6px;
top: 0;
font-size: 12px;
}
/* Static Bar Elements */
.progress__container {
width: 600px;
margin: 20px auto;
position: relative;
}
.backBar {
height:2px;
width:96%;
position: absolute;
top: 7px;
left: 2%;
background-color: lightgrey;
}
.progress__bar {
z-index: 100;
position: relative;
width: 96%;
margin: 0 auto;
}
.circ {
background-color: #fff;
border: 2px solid lightgrey;
border-radius: 50%;
height: 12px;
width: 12px;
display: inline-block;
}
#circ__2, #circ__3 {
margin-left: 30%
}
#circ__4 {
float: right;
}
.passed {
background-color: darkred;
border: 2px solid darkred;
}
.hide {
visibility: hidden
}
.flexrow {
display: flex;
flex-direction: row;
justify-content: space-between;
}
/* Buttons */
.buttonStep {
background: grey;
color: #fff;
padding: 10px 25px;
border-radius: 10px;
font-size: 16px;
}
#back {
float: left;
}
#next {
float: right;
}
.is-active {
background: darkred;
}
The way I have it set up, I expect for the translateX values to increment or decrement depending on the click event listeners which would make the circle slide across the page. What is actually happening is that only the first step works. it will not go past the first stop point. If I log moveDot in the console it gives me the values that I am expecting, but it will only start/stop at 0 and 190. the back button functions the same way. link to fiddle
It is animated from and to the same place every time. Move the definition of moveDot into the event listener:
// give a starting value for the transformation
var startVal = 0;
// definte the timing
var dotTiming = {
duration: 400,
fill: "forwards",
easing: 'ease-in',
}
// on click fire the animation
document.getElementById('next').addEventListener('click', function() {
if (startVal > 380){return;}
// define the keyframes
var moveDot = [{transform: `translateX(${startVal}px)`},
{transform: `translateX(${startVal + 190}px)`}];
// make the animation happen
var movingDot = document.getElementById("progress__dot").animate(
moveDot,
dotTiming
);
movingDot.playbackRate = 1;
movingDot.play();
startVal += 190;
});
document.getElementById('back').addEventListener('click', function() {
movingDot.playbackRate = -1;
if (startVal >= 0) {
movingDot.play();
startVal -= 190;
}
});

Categories

Resources