Add transition to dynamic DOM element - javascript

I am trying to add transition to div element. Transition is applied successfully to first added div element. When I add more divs by clicking on .container then these new divs do not have this animation. How can I add transitions to dynamic divs?
Below is my code
var transition = 1;
var x = 0;
var left = 0;
draw('white');
var $rect = $('.rect');
var $container = $('.container');
var arr = ['red', 'green', 'black'];
var count = 0;
$('body').on('click', function () {
draw(arr[count]);
count++;
});
function init () {
setInterval(onEachStep, 1000/60);
}
function onEachStep () {
x += transition;
left = left + transition;
$rect.css('left', left + 'px');
if (x > $container.outerWidth() - $rect.outerWidth()) {
transition = -10;
}
if (x < 0) {
transition = 1;
}
}
function draw (color) {
var rect = $('<div />', {
'class': 'rect'
});
rect.css('background', color);
rect.appendTo('.container');
}
init();
.container {
background: lightblue;
height: 300px;
}
.rect {
width: 50px;
height: 20px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="container"></div>

You need to store left, x and transition for each rectangle. Having the same left, x and transition for all of them would mean they all will be at the same position on any point in time.
draw('white');
var $container = $('.container');
var arr = ['red', 'green', 'black'];
var count = 0;
$('body').on('click', function () {
draw(arr[count%arr.length]);
count++;
});
function init () {
setInterval(onEachStep, 1000/60);
}
function onEachStep () {
$rect = $('.rect');
for(var i = 0; i < $rect.length; i++) {
var thisrect = $rect[i];
thisrect.x += thisrect.transition;
thisrect.left += thisrect.transition;
$(thisrect).css('left', thisrect.left + 'px');
if (thisrect.x > $container.outerWidth() - $(thisrect).outerWidth()) {
thisrect.transition = -10;
}
if (thisrect.x < 0) {
thisrect.transition = 1;
}
}
}
function draw (color) {
var rect = $('<div />', {
'class': 'rect'
});
rect.css('background', color);
rect[0].x = 0;
rect[0].left = 0;
rect[0].transition = 1;
rect.appendTo('.container');
}
init();
.container {
background: lightblue;
height: 300px;
}
.rect {
width: 50px;
height: 20px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="container"></div>

You have to update the $rect variable for that. find the code below
var transition = 1;
var x = 0;
var left = 0;
draw('white');
var $rect = $('.rect');
var $container = $('.container');
var arr = ['red', 'green', 'black'];
var count = 0;
$('body').on('click', function () {
draw(arr[count]);
count++;
$rect = $('.rect');
});
function init () {
setInterval(onEachStep, 1000/60);
}
function onEachStep () {
x += transition;
left = left + transition;
$rect.css('left', left + 'px');
if (x > $container.outerWidth() - $rect.outerWidth()) {
transition = -10;
}
if (x < 0) {
transition = 1;
}
}
function draw (color) {
var rect = $('<div />', {
'class': 'rect'
});
rect.css('background', color);
rect.appendTo('.container');
}
init();
.container {
background: lightblue;
height: 300px;
}
.rect {
width: 50px;
height: 20px;
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="container"></div>

Related

How to wait for the function to end before start the function again

How to wait for my first function to end before I can click "Click me" button again. I have been searching for a way to let my function end first before I can let the new function run again.
document.getElementById("myBtn").addEventListener("click", myFunction);
setTimeout(function() {
myFunction();
}, 3000);
var id = null;
function myFunction() {
var elem = document.getElementById("myAnimation");
var pos = 0;
clearInterval(id);
id = setInterval(frame, 10);
function frame() {
if (pos == 350) {
clearInterval(id);
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
#myContainer {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#myAnimation {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<h2>JavaScript addEventListener()</h2>
<button id="myBtn">Click Me</button>
<div id="myContainer">
<div id="myAnimation"></div>
If we disable and enable the button in the correct place, it will work quite nicely
I also cleaned up the code a bit to make it more contained.
window.addEventListener('DOMContentLoaded', () => {
const myBtn = document.getElementById("myBtn");
const elem = document.getElementById("myAnimation");
let id = null;
let pos = 0;
const frame = () => {
if (pos == 350) {
clearInterval(id);
myBtn.disabled = false;
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
const myFunction = () => {
pos = 0;
clearInterval(id);
id = setInterval(frame, 10);
myBtn.disabled = true;
}
id = setTimeout(myFunction, 3000);
myBtn.addEventListener("click", myFunction);
});
#myContainer {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#myAnimation {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<h2>JavaScript addEventListener()</h2>
<button id="myBtn">Click Me</button>
<div id="myContainer">
<div id="myAnimation"></div>
</div>
As a first implementation you could disable the button before you start the animation, and you only enable it after you are done
var myBtn = document.getElementById("myBtn")
myBtn.addEventListener("click", myFunction);
setTimeout(function() {
myFunction();
}, 3000);
var id = null;
function myFunction() {
var elem = document.getElementById("myAnimation");
var pos = 0;
clearInterval(id);
id = setInterval(frame, 10);
// disable the button
myBtn.disabled = true;
function frame() {
if (pos == 350) {
clearInterval(id);
// enable the button again
myBtn.disabled = false;
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
#myContainer {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#myAnimation {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<h2>JavaScript addEventListener()</h2>
<button id="myBtn">Click Me</button>
<div id="myContainer">
<div id="myAnimation"></div>
You should disable your button during your function.
edited: If you don't want to disable maybe with a lock.
document.getElementById("myBtn").addEventListener("click", myFunction);
setTimeout(function() {
myFunction();
}, 3000);
var id = null;
var lock = false;
function myFunction() {
if(!lock){
lock = true;
var elem = document.getElementById("myAnimation");
var pos = 0;
clearInterval(id);
id = setInterval(frame, 10);
function frame() {
if (pos == 350) {
clearInterval(id);
lock = false;
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.left = pos + 'px';
}
}
}
}
#myContainer {
width: 400px;
height: 400px;
position: relative;
background: yellow;
}
#myAnimation {
width: 50px;
height: 50px;
position: absolute;
background-color: red;
}
<h2>JavaScript addEventListener()</h2>
<button id="myBtn">Click Me</button>
<div id="myContainer">
<div id="myAnimation"></div>
edited: Try making your animation with CSS it's a better practice.
let sum = 0;
const x = 10;
async function firstFunction() {
for (i = 0; i < x; i++) {
sum = sum + i;
}
return sum;
}
async function secondFunction() {
await firstFunction();
console.log('After firstFunction executed sum is', sum);
}
secondFunction();

Div creation and styling not working as expected

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);
}

Javascript Adding pixels to current position of div

When the right arrow key is pressed I would like to increment the left position of a div by 10px using the style property. Here is my script and what I've tried so far:
document.onkeydown = KeyPressed;
function KeyPressed(k) {
var LeftBtn = 37;
var RightBtn = 39;
var UpBtn = 38;
var DownBtn = 40;
if (k.keyCode == RightBtn) {
document.getElementById("test").style.left = document.getElementById("test").style.left + 10px;
}
}
#test {
position: relative;
left: 0px;
width: 25px;
height: 80px;
background-color: black;
}
<div id="test"></div>
The style property of a DOM element is essentially a dictionary with string key-value pairs. It expects a CSS key, and a proper string value.
Your current code comes out as left: 10px10px and that doesn't make much sense for CSS.
In order for this to work, you'd have to regard the px.
document.onkeydown = KeyPressed;
function KeyPressed(k) {
var LeftBtn = 37;
var RightBtn = 39;
var UpBtn = 38;
var DownBtn = 40;
if (k.keyCode == RightBtn) {
var moveEl = document.getElementById("test"),
currLeft = parseInt(moveEl.style.left || 0);
moveEl.style.left = (currLeft + 10) + 'px';
}
}
#test {
position: relative;
left: 0px;
width: 25px;
height: 80px;
background-color: black;
}
<div id="test"></div>
Further reading and examples - HTMLElement.style
Remove px from 10.
if (k.keyCode == RightBtn) {
document.getElementById("test").style.left = document.getElementById("test").style.left + 10;
}
Try following way:
document.onkeydown = KeyPressed;
function KeyPressed(k) {
var LeftBtn = 37;
var RightBtn = 39;
var UpBtn = 38;
var DownBtn = 40;
if(k.keyCode == RightBtn) {
document.getElementById("test").style.left = parseInt(document.getElementById("test").style.left || 0) + 10 + 'px';
}
}

jQuery autoScroll to the nearest section

If the user is place in the top half of current section it automatically scroll top of that section.
Then if the user is in the bottom half of the current section it automatically scroll to the top next section.
function autoScroll(aid){
var aTag = $("#"+ aid);
body.animate({scrollTop: aTag.offset().top},1500);
}
$(window).scroll(function() {
var windowScroll = $(window).scrollTop();
if(windowScroll < ($("#Section2").offset().top/2) && !(windowScroll > ($("#Section2").offset().top/2))){
section_id = 'Section1';
}
$(document).off('scroll');
console.log(section_id);
autoScroll(section_id);
});
http://jsfiddle.net/x6xzh69v/2/
I created a working example in CODEPEN.
$(document).ready(function() {
var origHeight = [];
var curScroll = 0;
var cumSumHeight = 0;
var animHeight = 0;
var i = 0;
var timeoutVar;
$(".section").each(function(index) {
origHeight.push($(this).height());
});
$(window).scroll(function() {
curScroll = $("body").scrollTop();
cumSumHeight = 0;
while ((cumSumHeight + origHeight[i]) < curScroll) {
cumSumHeight += origHeight[i];
i++;
}
if (i == 0) {
if (curScroll < (origHeight[i] / 2)) {
animHeight = 0;
} else {
animHeight = origHeight[i];
}
} else {
if ((curScroll - cumSumHeight) < (origHeight[i] / 2)) {
animHeight = cumSumHeight;
} else {
animHeight = origHeight[i] + cumSumHeight;
}
}
clearTimeout(timeoutVar);
timeoutVar = setTimeout(function() {
$("body").stop(true,true).animate({
scrollTop: animHeight
}, 200);
}, 300);
});
});
.section {
width: 100%;
position: relative;
height: 300px;
}
#Section1 {
background: red;
}
#Section2 {
background: blue;
}
#Section3 {
background: orange;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="Section1" class="section"></section>
<section id="Section2" class="section"></section>
<section id="Section3" class="section"></section>

Sound-Reactive css animation on chrome android/iOs

I'm working on a website for my Sound Design degree for which I need to visualize the music.
I managed to animate the background of my website according to the "volume" of the sound playing (variation of the opacity). It works like a charm on Chrome osx but I can't can't figure out how to make it work on android/iOS. Should I use a specific library for mobile css animation ?
Thanks a lot !!
Here is the messy my code in his entirety :
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Choir_Test</title>
<link href="http://fonts.googleapis.com/css?family=Open+Sans:400,300" rel="stylesheet" type="text/css">
<style>
body {
font-family:'Open Sans', serif; font-size:40px;
background-color:#000000;
padding : 0;
margin: 0;
width: 100%;
height: 100%;
}
Header {
position: center 40px;
height: 100px;
width: 100%;
color: white;
}
.contentWrapper {
width:1000px; margin-left: 40px; font-size:22px; font-weight:200;
}
h1 {
font-size:60px; font-weight:300;
}
.area {
height: 150px;
width: 100%;
color: white;
z-index:10;
padding : 0;
margin: 0;
}
#circularCenter {
margin: auto;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width:74px;
height:74px;
border-radius:100%;
background:rgb(255,0,0);
}
.circle {
background:rgba(255,0,0, 1);
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
-webkit-transition:0.1s ease all;
z-index:-1;
}
.initiator {
position:absolute;
width:100%; height:100%;
background:rgba(255,255,255, 0);
-webkit-transition:0.3s ease all;
z-index:1;
cursor:pointer;
}
.experiment {
background:rgba(0,0,0, 1);
background:-webkit-linear-gradient(#000,#000);
background:-moz-linear-gradient(#000,#000);
background:-ms-linear-gradient(#000,#000);
width:100%;
height:100%;
position: center 40px;
background-image:url(Images/Choirs.png);
background-size:150px 75px;
background-attachment:fixed;
background-repeat:no-repeat;
background-position:center 40px;
z-index: 100;
height: 100%;
Width: 100%;
padding : 0;
margin: 0;
}
.header
{
height: 100px;
padding-right: auto;
padding-left:auto;
z-index: 1000;
}
.footer
{
position: absolute;
bottom: 0px;
height: 30px;
padding-left:40px;
margin-bottom: 40px;
z-index: 750;
-webkit-filter: invert(100%);
}
</style>
</head>
<body>
<div class="experiment" id="r3">
<div class="initiator"></div>
<div id="circles" class="area"></div>
<div id="circles" class="footer">
<img src="Images/Twitter.png" width="40px"></img>
<img src="Images/Facebook.png" width="40px"></img>
</div>
</div>
</div>
<audio id="r0audio" loop>
<source src="Musics/China1.mp3"></audio>
<script>
window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext;
var renderers = {
'r0': (function() {
var barsArr = [],
initialized = false,
barsEl;
var height = 0;
var init = function(config) {
var count = config.count;
var width = config.width;
var barWidth = (width/count) >> 0;
height = config.height;
barsEl = document.getElementById('bars');
for(var i = 0; i < count; i++ ){
var nunode = document.createElement('div');
nunode.classList.add('bar');
nunode.style.width = barWidth + 'px';
nunode.style.left = (barWidth * i) + 'px';
barsArr.push(nunode);
barsEl.appendChild(nunode);
}
initialized = true;
};
var max = 256;
var renderFrame = function(frequencyData) {
for(var i = 0; i < barsArr.length; i++) {
var bar = barsArr[i];
bar.style.height = ((frequencyData[i]/max)*height + 'px');
}
};
return {
init: init,
isInitialized: function() {
return initialized;
},
renderFrame: renderFrame
}
})(),
'r3': (function() {
var circles = [];
var initialized = false;
var height = 0;
var width = 0;
var init = function(config) {
var count = config.count;
width = config.width;
height = config.height;
var circleMaxWidth = (width*0.99) >> 0;
circlesEl = document.getElementById('circles');
for(var i = 0; i < count; i++ ){
var node = document.createElement('div');
node.style.width = node.style.color = (i/count*circleMaxWidth) + 'px';
node.classList.add('circle');
circles.push(node);
circlesEl.appendChild(node);
}
initialized = true;
};
var max = 256;
var renderFrame = function(frequencyData) {
for(var i = 0; i < circles.length; i++) {
var circle = circles[i];
circle.style.cssText = '-webkit-transform:scale('+1+');';
circle.style.cssText += 'opacity:'+((frequencyData[i]/max))+';';
}
};
return {
init: init,
isInitialized: function() {
return initialized;
},
renderFrame: renderFrame
}
})(),
};
window.onload = function() {
function Visualization(config) {
var audio,
audioStream,
analyser,
source,
audioCtx,
canvasCtx,
frequencyData,
running = false,
renderer = config.renderer,
width = config.width || 360,
height = config.height || 360;
var init = function() {
audio = document.getElementById('r0audio');
audioCtx = new AudioContext();
analyser = audioCtx.createAnalyser();
source = audioCtx.createMediaElementSource(audio);
source.connect(analyser);
analyser.connect(audioCtx.destination);
analyser.fftSize = 64;
frequencyData = new Uint8Array(analyser.frequencyBinCount);
renderer.init({
count: analyser.frequencyBinCount,
width: width,
height: height
});
};
this.start = function() {
audio.play();
running = true;
renderFrame();
};
this.stop = function() {
running = false;
audio.pause();
};
this.setRenderer = function(r) {
if (!r.isInitialized()) {
r.init({
count: analyser.frequencyBinCount,
width: width,
height: height
});
}
renderer = r;
};
this.isPlaying = function() {
return running;
}
var renderFrame = function() {
analyser.getByteFrequencyData(frequencyData);
renderer.renderFrame(frequencyData);
if (running) {
requestAnimationFrame(renderFrame);
}
};
init();
};
var vis = document.querySelectorAll('.initiator');
var v = null;
var lastEl;
var lastElparentId;
for(var i=0; i<vis.length; i++) {
vis[i].onclick = (function() {
return function() {
var el = this;
var id = el.parentNode.id;
if (!v) {
v = new Visualization({renderer: renderers[id] });
}
v.setRenderer(renderers[id]);
if (v.isPlaying()) {
if (lastElparentId === id) {
v.stop();
el.style.backgroundColor = 'rgba(0,0,0,0.5)';
} else {
lastEl.style.backgroundColor = 'rgba(0,0,0,0.5)';
el.style.backgroundColor = 'rgba(0,0,0,0)';
}
}else {
v.start();
el.style.backgroundColor = 'rgba(0,0,0,0)';
}
lastElparentId = id;
lastEl = el;
};
})();
}
};
</script>
</body>
</html>

Categories

Resources