I trying to do equalizer animation. I did function for start animation, but i cant do function for stop animation, becouse clearInterval not working.
my codepen
https://codepen.io/naraxiss/pen/qyMamy
var spans = document.querySelectorAll('span');
function getRandom() {
return Math.random();
}
function scale(el){
el.style.transform = 'scaleY(' + getRandom() +')';
}
var myInterval = null;
function startMusic (spans){
var el = spans;
for(var i = 0; i < el.length; i++){
(function(i) {
myInterval = setInterval(function(){
scale(el[i]);
}, 100);
})(i);
}
}
function stopMusic (interval,els){
clearInterval(interval);
//console.log(els)
for(var i = 0; i < els.length; i++){
els[i].style.stransform = 'scaleY(0.05)'
}
}
document.querySelector('.start').addEventListener('click', function(){
startMusic(spans);
})
document.querySelector('.finish').addEventListener('click', function(){
stopMusic(myInterval,spans);
})
body{
margin: 0;
}
span{
display: inline-block;
width: 50px;
height: 300px;
background-color: #000;
margin-right: 10px;
transition: 0.1s linear;
transform: scaleY(0.005);
transform-origin: bottom;
}
.equalizer{
position: absolute;
top: 50%;
left: 40%;
transform: translate(-50%,-50%);
}
<div class="equalizer">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<button class="start">START</button>
<button class="finish">FINISH</button>
Thanks!
You need to save reference of each interval in an array like this
var myInterval = [];
function startMusic (spans){
var el = spans;
for(var i = 0; i < el.length; i++){
(function(i) {
let interval = setInterval(function(){
scale(el[i]);
}, 100);
myInterval.push(interval);
})(i);
}
}
and then in stopMusic function clear all of those intervals like this one.
function stopMusic (interval,els){
interval.forEach(inter => clearInterval(inter));
console.log(els)
for(var i = 0; i < els.length; i++){
els[i].style.stransform = 'scaleY(0.05)'
}
}
Because you create 5 intervals inside your for loop you need to stop them seperately.
var spans = document.querySelectorAll('span');
function getRandom() {
return Math.random();
}
function scale(el) {
el.style.transform = 'scaleY(' + getRandom() + ')';
}
var myInterval = []; // <------------------------ Make it an array
function startMusic(spans) {
var el = spans;
for (var i = 0; i < el.length; i++) {
(function(i) {
myInterval.push(setInterval(function() { // <------------- push every item
scale(el[i]);
}, 100));
console.log(myInterval)
})(i);
}
}
function stopMusic(els) {
for (var x = 0; x < myInterval.length; x++) {
clearInterval(myInterval[x]); // <--------------------- Access every item to clear
}
console.log(els)
for (var i = 0; i < els.length; i++) {
els[i].style.stransform = 'scaleY(0.05)'
}
}
The reason it doesn't work is because you start 5 intervals but only stop 1. Put the intervals in a array so you can loop them and stop them all. See change below.
var spans = document.querySelectorAll('span');
function getRandom() {
return Math.random();
}
function scale(el){
el.style.transform = 'scaleY(' + getRandom() +')';
}
var myIntervals = [];
function startMusic (spans){
var el = spans;
for(var i = 0; i < el.length; i++){
(function(i) {
myIntervals[i] = setInterval(function(){
scale(el[i]);
}, 100);
})(i);
}
}
function stopMusic (intervals,els){
//clearInterval(interval);
//console.log(els)
for(var i = 0; i < els.length; i++){
clearInterval(intervals[i]);
els[i].style.stransform = 'scaleY(0.05)'
}
}
document.querySelector('.start').addEventListener('click', function(){
startMusic(spans);
})
document.querySelector('.finish').addEventListener('click', function(){
stopMusic(myIntervals,spans);
})
body{
margin: 0;
}
span{
display: inline-block;
width: 50px;
height: 300px;
background-color: #000;
margin-right: 10px;
transition: 0.1s linear;
transform: scaleY(0.005);
transform-origin: bottom;
}
.equalizer{
position: absolute;
top: 50%;
left: 40%;
transform: translate(-50%,-50%);
}
<div class="equalizer">
<span></span>
<span></span>
<span></span>
<span></span>
<span></span>
</div>
<button class="start">START</button>
<button class="finish">FINISH</button>
Related
I'm trying to create a number of divs and iterate through them on click.
The iteration only works on every other click.
Strangely, I'm getting no errors.
I tried moving the divs variable declaration outside of the for loop.
for (let i = 0; i <= 5; i++) {
let div = document.body.insertAdjacentHTML('beforeend', `<div class="div">${i}</div>`)
let divs = document.getElementsByClassName('div');
divs[i].style.backgroundColor = randomColor();
divs[i].onclick = () => {
close(divs[i])
open(divs[i + 1])
}
}
function randomColor() {
let e = Math.floor(Math.random() * 16777215).toString(16);
return `#${e}`;
}
function close(t) {
t.style.transform = 'scale(0.5)'
t.style.opacity = '0'
setTimeout(function() {
t.style.display = 'none'
}, 500)
}
function open(t) {
t.style.display = 'block'
setTimeout(function() {
t.style.transform = 'scale(1)'
t.style.opacity = '1'
}, 5)
}
div {
height: 100%;
width: 100%;
position: fixed;
top: 0;
bottom: 0;
right: 0;
transition: 0.5s;
opacity: 0;
transform: scale(0.5);
}
you need to
open(divs[(i + 1) % 6]) so it loop correctly
hide all divs at initial (except one)
there still some minor issue with the initial state (need to add opacity and transform, I leave it for simplicity), I think you should use proper class instead of inline css to make it easier.
for (let i = 0; i <= 5; i++) {
let div = document.body.insertAdjacentHTML('beforeend',
`<div class="div" style="display:${i==0?'block':'none'}">${i}</div>`
)
}
let divs = document.getElementsByClassName('div');
for (let i = 0; i <= 5; i++) {
divs[i].style.backgroundColor = randomColor();
divs[i].onclick = () => {
close(divs[i])
open(divs[(i + 1) % 6])
}
}
function randomColor() {
let e = Math.floor(Math.random() * 16777215).toString(16);
return `#${e}`;
}
function close(t) {
t.style.transform = 'scale(0.5)'
t.style.opacity = '0'
setTimeout(function() {
t.style.display = 'none'
}, 500)
}
function open(t) {
t.style.display = 'block'
setTimeout(function() {
t.style.transform = 'scale(1)'
t.style.opacity = '1'
}, 5)
}
div {
height: 100%;
width: 100%;
position: fixed;
top: 0;
bottom: 0;
right: 0;
transition: 0.5s;
opacity: 0;
transform: scale(0.5);
}
I've built a small balloon game , trying to learn the foundations,
anyways I've successfully rendered balloons, i can see them both on the page however the move functions doesn't work,it should do so on page load that I've set in the index.html body(the startGame func) , code looks fine,however nothing happens.
var gNextId = 100
var gBaloons = createBalloons()
var gInterval = null
function startGame() {
renderBaloons();
gInterval = setInterval(() => {
moveBalloons();
}, 500);
}
function renderBaloons() {
var strHtml = ''
for (var i = 0; i < gBaloons.length; i++) {
var balloon = gBaloons[i]
strHtml += `
${balloon.txt}
`
}
document.querySelector('.balloon-container').innerHTML = strHtml
}
function moveballoons() {
var elballoons = document.querySelectorAll('.balloon')
for (var i = 0; i > gBaloons.length; i++) {
var balloon = gBaloons[i]
var elballoon = elballoons[i]
balloon.bottom += balloon.speed
elballoon.style.bottom = balloon.bottom + 'px'
}
if (balloon.bottom >= 800) clearInterval(gInterval)
}
function createBalloons() {
var ballons = [
createBalloon('A'),
createBalloon('B'),
createBalloon('C')
];
return ballons
}
function createBalloon(txt) {
return {
id: gNextId++,
bottom: 0,
speed: 45,
txt: txt
}
}
body {
background-color: lightblue;
}
.balloon {
position: absolute;
width: 170px;
height: 200px;
border-radius: 40%;
bottom: 0;
transition: 3s;
background-color: yellow;
text-align: center;
font-weight: bold;
}
.balloon1 {
left: 200px;
background-color: rgb(3, 61, 23);
}
.balloon2 {
left: 600px;
background-color: rgb(182, 24, 50);
}
.fade {
opacity: 0;
}
In the moveballoons() function the following line:
for (var i = 0; i > gBaloons.length; i++) {
Should be
for (var i = 0; i < gBaloons.length; i++) {
Note: I've swapped > with <
I couldn't the get example running, so there could well be other reasons as to why this is not working but that is definitely an issue.
I recently started learning how to use JavaScript in my webpage. My exercise today is to make a button that can give me a V shape.
The code to create the V shape is fine, but it doesn't work when I try to put it in a click handler (i.e. oBtn.click = function (){};).
In the HTML document I have the following code:
<style>
div{
width: 50px;
height: 50px;
border: 1px red solid;
position: absolute;
line-height: 50px;
text-align: center;
margin: 5px;
}
</style>
<script type="text/javascript">
window.onload = function (){
var oBody = document.getElementById('body');
var aDiv = document.getElementsByTagName('div');
var oBtn1 = document.getElementById('btn1');
for (var i = 0; i < 9; i++) {
oBody.innerHTML += '<div>'+ i +'</div>';
}
for (var i = 0; i < aDiv.length; i++) {
aDiv[i].style.left =i*50+'px';
}
oBtn1.onclick = function (){
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
var x = aDiv.length;
for (var i = 4; i < x; i++) {
aDiv[i].style.top =x*50-i*50-50+40+'px';
}
};
};
</script>
I believe this is close to what you wanted. Runs in chrome, but may not in other browsers (notably IE). Doesn't work as a snippet, sorry. I suspect trying to modify all divs in the body is going to cause you trouble in the long term. A couple of things to notice:
You don't need to get the body by name, you can just use document.body (I'm making an assumption here - however giving an element the id "body" could easily cause confusion)
Your divs must be created before you try to get the array from the DOM
Event handlers are done using the commonly preferred method.
<html>
<head>
<style>
div{
width: 50px;
height: 50px;
border: 1px red solid;
position: absolute;
line-height: 50px;
text-align: center;
margin: 5px;
}
</style><script>
window.addEventListener("DOMContentLoaded", function () {
for (var i = 0; i < 9; i++) {
document.body.innerHTML += '<div>'+ i +'</div>';
}
var aDiv = document.getElementsByTagName('div');
for (var i = 0; i < aDiv.length; i++) {
aDiv[i].style.left =i*50+'px';
}
document.getElementById('btn1').addEventListener("click", function () {
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
var x = aDiv.length;
for (var i = 4; i < x; i++) {
aDiv[i].style.top =x*50-i*50-50+40+'px';
}
});
}, false);
</script>
</head>
<body>
<input type="button" id="btn1"><br />
</body>
</html>
If I understand this right, you want to execute 'oBtn1.onclick' as a click event? If so, do something like this
function buttonClick (){
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
oBtn1.addEventListener('click', buttonClick);
what that will do is as soon as the element that contains the id 'oBtn1' is clicked it will execute your for loop.
What does your html look like? If it looks kind of like the below snippet then it should be working, though you should look at using addEventListener for this kind of thing.
window.onload = function (){
var oBody = document.getElementById('body');
var aDiv = document.getElementsByTagName('div');
var oBtn1 = document.getElementById('btn1');
for (var i = 0; i < 9; i++) {
oBody.innerHTML += '<div>'+ i +'</div>';
}
for (var i = 0; i < aDiv.length; i++) {
aDiv[i].style.left =i*50+'px';
}
oBtn1.onclick = function (){
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
var x = aDiv.length;
for (var i = 4; i < x; i++) {
aDiv[i].style.top =x*50-i*50-50+40+'px';
}
};
};
div{
width: 50px;
height: 50px;
border: 1px red solid;
position: absolute;
line-height: 50px;
text-align: center;
margin: 5px;
}
<button id="btn1">press</button>
<div id="body"></div>
I am trying to repeatedly display some sentences letter by letter using some fade in/fade out effect.However, when trying to do that, it seems that words break in the middle as shown below. How can I avoid word breaking?
var quotes = document.getElementsByClassName('quote');
var quoteArray = [];
var currentQuote = 0;
quotes[currentQuote].style.opacity = 0;
for (var i = 0; i < quotes.length; i++) {
splitLetters(quotes[i]);
}
function changeQuote() {
var cw = quoteArray[currentQuote];
var nw = currentQuote == quotes.length-1 ? quoteArray[0] : quoteArray[currentQuote+1];
for (var i = 0; i < cw.length; i++) {
animateLetterOut(cw, i);
}
for (var i = 0; i < nw.length; i++) {
nw[i].className = 'letter behind';
nw[0].parentElement.style.opacity = 1;
animateLetterIn(nw, i);
}
currentQuote = (currentQuote == quoteArray.length-1) ? 0 : currentQuote+1;
}
function animateLetterOut(cw, i) {
setTimeout(function() {
cw[i].className = 'letter out';
}, 0);
}
function animateLetterIn(nw, i) {
setTimeout(function() {
nw[i].className = 'letter in';
}, 340+(i*30));
}
function splitLetters(quote) {
var content = quote.innerHTML;
console.log(quote.innerHTML);
quote.innerHTML = '';
var letters = [];
for (var i = 0; i < content.length; i++) {
var letter = document.createElement('span');
letter.className = 'letter';
letter.innerHTML = content.charAt(i)==' '?' ':content.charAt(i);
quote.appendChild(letter);
letters.push(letter);
}
quoteArray.push(letters);
}
changeQuote();
setInterval(changeQuote, 10000);
body {
font-weight: 600;
font-size: 40px;
}
.text {
position: relative;
}
.quote {
position: absolute;
opacity: 0;
}
.letter {
display: inline-block;
position: relative;
float: left;
-webkit-transform: translateZ(25px);
transform: translateZ(25px);
-webkit-transform-origin: 50% 50% 25px;
transform-origin: 50% 50% 25px;
}
.letter.out {
visibility: hidden;
opacity: 0;
transition: visibility 0s 0.7s, opacity 0.7s linear;
}
.letter.behind {
visibility: hidden;
opacity: 0;
}
.letter.in {
visibility: visible;
opacity: 1;
transition: opacity 0.7s linear;
}
<body>
<div class="text">
<p>
<span class="quote">TEXT ONE(1): For example, if you are designing a brand new website for someone, most times you will have to make sure the prototype looks finished by inserting text or photos or what have you. </span>
<span class="quote">TEXT TWO(2): The purpose of this is so the person viewing the prototype has a chance to actually feel and understand the idea behind what you have created.</span>
</p>
</div>
Your setInterval(changeQuote, 5000) is the source of the effect you have cleverly developed finishing short. Initially I began to play with the 5000ms and changing it to 15000ms down to around 8000~10000ms is what seemed to make it work best.
Change it to setInterval(changeQuote, 9000) and see the difference.
However, thinking of scalability, you will need to figure out a way to make it so that the setInterval waits until the quoteArray has finished pushing the letters.
EDIT
Based on the feedback in the comments, I determined the following:
On the JavaScript side of things, each letter is a <span> meaning that each served as an individual element. What was lacking was to create a word to wrap around each sentence. This is would ensure that each word would wrap around according to its parent container.
On the CSS side of things, the container of the letters meaning quote needed styling which would allow it to better represent its contents. By adding white-space: nowrap, display: block I managed to give its children a container which would adapt depending on the screen width.
See the below snippet fixed from the provided one for reference.
var quotes = document.getElementsByClassName('quote'),
quoteArray = [],
currentQuote = 0;
quotes[currentQuote].style.opacity = 0;
for (var i = 0; i < quotes.length; i++) {
splitLetters(quotes[i]);
}
function changeQuote() {
var cw = quoteArray[currentQuote];
var nw = currentQuote == quotes.length - 1 ? quoteArray[0] : quoteArray[currentQuote + 1];
for (var i = 0; i < cw.length; i++) {
animateLetterOut(cw, i);
}
for (var i = 0; i < nw.length; i++) {
nw[i].className = 'letter behind';
nw[0].parentElement.style.opacity = 1;
animateLetterIn(nw, i);
}
currentQuote = (currentQuote == quoteArray.length - 1) ? 0 : currentQuote + 1;
}
function animateLetterOut(cw, i) {
setTimeout(function() {
cw[i].className = 'letter out';
}, 0);
}
function animateLetterIn(nw, i) {
setTimeout(function() {
nw[i].className = 'letter in';
}, 340 + (i * 30));
}
function splitLetters(quote) {
var content = quote.innerHTML,
words = [],
word = document.createElement('span');
word.className = "word";
word.innerHTML = "";
quote.innerHTML = "";
for (var i = 0; i < content.length; i++) {
var letter = document.createElement('span');
letter.className = 'letter';
if(content.charAt(i) !== " "){
letter.innerHTML = content.charAt(i);
word.innerHTML = word.innerHTML.concat(letter.innerHTML);
}
else {
letter.innerHTML = " ";
word.innerHTML = word.innerHTML.concat(letter.innerHTML);
quote.appendChild(word);
words.push(word);
word = document.createElement('span');
word.className = "word";
}
}
quoteArray.push(words);
}
changeQuote();
setInterval(changeQuote, 10000);
body {
font-weight: 600;
font-size: 40px;
}
.text {
position: relative;
}
.quote {
position: absolute;
display: block;
opacity: 0;
white-space: nowrap;
}
.letter {
display: inline-block;
position: relative;
float: left;
-webkit-transform: translateZ(25px);
transform: translateZ(25px);
-webkit-transform-origin: 50% 50% 25px;
transform-origin: 50% 50% 25px;
}
.letter.out {
visibility: hidden;
opacity: 0;
transition: visibility 0s 0.7s, opacity 0.7s linear;
}
.letter.behind {
visibility: hidden;
opacity: 0;
}
.letter.in {
visibility: visible;
opacity: 1;
transition: opacity 0.7s linear;
}
<div class="text">
<p>
<span class="quote">TEXT ONE(1): For example, if you are designing a brand new website for someone, most times you will have to make sure the prototype looks finished by inserting text or photos or what have you. </span>
<span class="quote">TEXT TWO(2): The purpose of this is so the person viewing the prototype has a chance to actually feel and understand the idea behind what you have created.</span>
</p>
</div>
When I click in the automatic button (auto) more than once, which handles the setInterval method, the color Divs go crazy fast, now the reason is what I'm here for to know. This is the DEMO in jsfiddleDEMO OF COLOR DIVS WITH SETINTERVAL METHOD
Body:
<div id="placeDiv1">ok</div>
<button id="b1" onclick="forward()">Forward</button>
<button id="b2" onclick="backward()">Backward</button>
<button id="b3" onclick="skip2()">skip2</button>
<button id="b4" onclick="automatic()">auto</button>
<button id="b5" onclick="stop()">stop</button>
<script>
var myArray = ["black", "yellow", "green", "red", "blue", "blue", "black", "gray"];
var myArray1 = ["yellow", "blue", "green", "red", "green", "blue", "black", "gray"];
var i = 0;
document.getElementById("placeDiv").style.backgroundColor = myArray[i];
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
forward = function () {
if (i == myArray.length - 1) {
i = 0;
} else {
i = i + 1;
}
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
document.getElementById("placeDiv").style.backgroundColor = myArray[i];
};
skip2 = function () {
if (i == myArray.length - 4) {
i += 2;
alert("This is the iterator " + i)
} else if (i == 7) {
i = 0
} else {
i = i + 1;
};
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
document.getElementById("placeDiv").style.backgroundColor = myArray[i];
};
backward = function () {
if (i == 0) {
i = myArray.length - 1;
i = myArray1.length - 1;
} else {
i = i - 1;
}
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
document.getElementById("placeDiv").style.backgroundColor = myArray[i];
//
}
automatic = function () {
var m = setInterval(function () {
if (i == myArray.length - 1) {
i = 0;
} else {
i = i + 1;
}
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
document.getElementById("placeDiv").style.backgroundColor = myArray[i];
}, 100);
stop = function () {
clearInterval(m)
};
};
</script>
CSS:
#placeDiv {
position: absolute;
left: 0px;
width: 100px;
height: 100px;
}
#placeDiv1 {
position: absolute;
left: 100px;
width: 100px;
height: 100px;
}
#b1 {
position: absolute;
top: 100px;
left: 0px
}
#b2 {
position: absolute;
top: 100px;
left: 80px
}
#b3 {
position: absolute;
top: 100px;
left: 170px
}
#b4 {
position: absolute;
top: 100px;
left: 270px
}
#b5 {
position: absolute;
top: 100px;
left: 320px
}
Just update the script like
var m=null;
automatic=function(){
clearInterval(m);
m = setInterval(function(){
if(i == myArray.length-1)
{i=0;}
else
{i=i+1;}
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
document.getElementById("placeDiv").style.backgroundColor = myArray[i];
},100);
stop=function(){
clearInterval(m);
};
Check Fiddle
You need to Kill the setinterval when you call the function automatic and also need to define var m outside the function
I'm finding your code a bit confusing, but the way i see it, you are setting the interval multiple times. Each time you click the button, it creates another timer.
What you can do is set a variable to check if the timer is running, like so:
var running = false;
In your automatic() function, set running to true; and in stop(), set running to false.
Also in automatic(), only create the timer if it's not already running.
All together, we now have:
running = false;
automatic=function(){
if (!running) {
running = true;
var m = setInterval(function(){if(i == myArray.length-1)
{i=0;}
else
{i=i+1;}
document.getElementById("placeDiv1").style.backgroundColor = myArray1[i];
document.getElementById("placeDiv").style.backgroundColor = myArray[i];},100);
}
stop=function(){
clearInterval(m);
running = false};
Is it just me, or are you not closing the function properly as well?