Vanilla Javascript animate margin-left of section - javascript

I'm having an issue getting my slider to work. It's a simple system of clicking buttons to get to and from sections but I'm having issues getting it to work.
I have made a codepen here: https://codepen.io/ItsBrianAgar/pen/JrbZEz
This is the js I have so far.
It needs to be Vanilla Js
var nextSection = function() {
var username = document.querySelector("input[name=\"username\"]").value;
var password = document.querySelector("input[name=\"password\"]").value;
if (username.length && password.length > 4) {
return window.location = "appSection.html";
} else {
alert("username and password must be longer than 4 characters");
}
}
var nextPage = function() {
var elem = document.getElementsByClassName("app");
var pos = 0;
var posDiff = 0;
var currentPos = elem[1].style.marginLeft;
var id = setInterval(frame, 5);
function frame() {
if (posDiff == -320) {
clearInterval(id);
posDiff = 0;
} else {
pos--;
for (var i = 0; i < elem.length; i++) {
elem[i].style.marginLeft = pos + 'px';
}
posDiff = currentPos + pos;
}
}
}
document.getElementById("cancel").onclick = previousPage = function() {
var elem = document.getElementsByClassName("app");
var pos = 0;
var id = setInterval(frame, 5);
function frame() {
for (var i = 0; i < elem.length; i++) {
if (pos == 640) {
clearInterval(id);
} else {
elem[i].style.marginLeft = pos + 'px';
pos += 320;
}
}
}
}

You can use Element.animate() to animate a DOM element
const [div, animationState, props] = [
document.querySelector("div")
, ["click to animate", "click to reverse animation"]
, ["0px", "320px"] // from, to
];
div.textContent = animationState[0];
div.onclick = () => {
div.animate({
marginLeft: props
}, {
duration: 1000,
easing: "linear",
iterations: 1,
fill: "both"
})
.onfinish = function() {
props.reverse();
div.textContent = animationState.reverse()[0];
}
}
<div></div>

Related

How can I make this collision detection possible?

I'm using a number of boxes that are floating around the screen, I want for them to bounce away from each other when they collide and I am testing this by just changing their colours instead when they collide, for some reason their colour changes at the start(their starting colour is white and if they collide it should change to red but they start and stays red). Is there something I am doing wrong? I would also like for everything to be done within the constructor function. I am sorry for not commenting my code as yet.
function BoxSplash()
{
this.sample = [];
var test = false;
this.col = color(129)
this.changeColour = function()
{
this.col = color(random(0,255),random(0,128),random(0,255))
}
this.intersect = function(other)
{
for(var i = 0; i < numberss; i++)
{ var currentBox = this.sample[i]
var d = dist(currentBox.x,currentBox.y,other.x,other.y)
if(d < currentBox.width + other.width)
{
return true;
}
else
{
return false
}
}
noLoop()
}
this.draw = function()
{
stroke(255)
line(0,windowHeight/2,windowWidth,windowHeight/2)
stroke(0)
for(var i = 0; i < numberss; i++)
{
var box = {
x:random(0,windowWidth - 50),
y:random(windowHeight/2 ,windowHeight - 50),
width:50,
height:50,
speedX:random(1,5),
speedY:random(1,5)
}
this.sample.push(box)
}
//use numberss variable to work with gui
for(var i = 0; i < numberss; i++)
{
fill(this.col)
rect(this.sample[i].x,this.sample[i].y,50,50)
}
this.move()
}
this.move = function()
{
for(var i = 0; i < numberss; i++)
{
var shape = this.sample[i]
shape.x += shape.speedX
shape.y += shape.speedY
if(shape.x + shape.width >= windowWidth || shape.x <= 0 )
{
shape.speedX = -shape.speedX
}
if(shape.y + shape.height >= windowHeight || shape.y <= windowHeight/2)
{
shape.speedY = -shape.speedY;
}
for(var j = 0; j < numberss; j++)
{
var others = this.sample[j]
var d = dist(shape.x,shape.y,others.x,others.y)
if( i != j && d < shape.width + others.width)
{
test = true;
}
else
{
test = false
}
if(test)
{
this.col = color(255,0,0)
}
}
}
}
}
You should visit this link and transform their circles into your boxes.
1st: Calculate dist(object1.x, object.y, object2.x, object2.y) and save into a variable called d
2nd:
if (d < object1.h + object2.h) {
// Enter your code here
}

How to activate an interval when a certain position is reached?

The problem is that It calls the var intervalLeft and intervaRight at the same time. When it is moving right I want the intervalLeft not to work & vice versa.
When It reaches startPosition 100 it activates the intervalLeft and when it reaches startPosition 0 it activates intervalRight infinite.
<div id="moveAnimation" class="block"></div>
</div>
<script>
var elem = document.getElementById("moveAnimation");
elem.addEventListener("click", movingImage);
function movingImage() {
var startPosition = 0;
var intervalRight = setInterval(frameRight, 10);
var intervalLeft = setInterval(frameLeft, 10);
function frameRight() {
if (startPosition >= 100) {
clearInterval(intervalRight);
frameLeft();
} else {
startPosition += 0.5;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
function frameLeft() {
if (startPosition <= 0) {
clearInterval(intervalRight);
frameRight();
} else {
startPosition -= 2;
document.getElementById("moveAnimation").style.right = startPosition + "%";
}
}
}
</script>
This is the exercise:
Below this, you have a div that needs to move left to right using JS for the motion. Make it reach the end in 2 seconds, then return in 5s. Repeat that forever.
Have updated your code. Use below
<div id="moveAnimation" class="block"></div>
</div>
<script>
var elem = document.getElementById("moveAnimation");
elem.addEventListener("click", movingImage);
function movingImage() {
var startPosition = 0;
var intervalRight = setInterval(frameRight, 10);
var rightTimer = true;
var leftTimer = false;
var intervalLeft;
function frameRight() {
if(!rightTimer){
rightTimer = true;
intervalRight = setInterval(frameRight,10)
return;
}
if (startPosition >= 100) {
rightTimer = false;
clearInterval(intervalRight);
frameLeft();
} else {
startPosition += 0.5;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
function frameLeft() {
if(!leftTimer){
leftTimer = true;
intervalLeft = setInterval(frameLeft,10)
return;
}
if (startPosition <= 0) {
leftTimer = false;
clearInterval(intervalLeft);
frameRight();
} else {
startPosition -= 2;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
}
</script>
After testing some more i've found the answer with fewer lines of code.
var elem = document.getElementById("moveAnimation");
elem.addEventListener("click", movingImage);
function movingImage() {
var startPosition = 0;
var intervalRight = setInterval(frameRight, 10); //1
function frameRight() {
if (startPosition >= 100) {
clearInterval(intervalRight);
intervalLeft = setInterval(frameLeft, 10);
} else {
startPosition += 0.5;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
function frameLeft() {
if (startPosition <= 0) {
clearInterval(intervalLeft);
intervalRight = setInterval(frameRight, 10);
} else {
startPosition -= 0.2;
document.getElementById("moveAnimation").style.left = startPosition + "%";
}
}
}
</script>
this works how it Should. In the original code I posted the clearInterval was not linked to an actual intervalID

While working with animation, clearInterval does not stop event triggered, or second animation does not get run

I am working on a animation there are four buttons with directions that can be pressed multiple times, and Run button. When Run buttons is pressed it should execute all the movements.
I have a catch 22 type of problem where ether events are fired forever and animation never stops or it only is being run once.
I tried multiple solutions and now settled on triggers, program works in a way where moves are being added to array and then fired in for loop, firing mechanism is setting triggers that would fire for that direction in short intervals.
Below code is done only for button right to reproduce the problem just click it twice and press run and you will see what I mean, I have also added console debugs that indicate the problem, and a Jsfiddle https://jsfiddle.net/0rxs9jpy/1/
If you want to reproduce where it only fires once check this fiddle https://jsfiddle.net/0rxs9jpy/2/ or uncomment line //if (r) return;
var moves = [];
leftpx = 0;
downpx = 0;
uppx = 0;
rightpx = 0;
var up = function() {
moves.push('up')
}
var down = function() {
moves.push('down')
}
var left = function() {
moves.push('left')
}
var right = function() {
moves.push('right')
}
document.addEventListener("moveRight", function(e) {
});
document.addEventListener("stopRight", function(e) {
console.log(e.detail);
clearInterval(e.detail);
});
var Run = function() {
for (var i = 0; i < moves.length; i++) {
if (moves[i] == 'up') {
document.getElementById('square').style.top = setInterval(myMove(), 3000);
};
if (moves[i] == 'left') {
document.getElementById('square').style.left = myMove3()
};
if (moves[i] == 'down') {
document.getElementById('square').style.top = myMove2()
};
if (moves[i] == 'right') {
//if (r) return;
var r = setInterval(function() {
var event = new CustomEvent("moveRight", {
"detail": "Example of an event"
});
document.dispatchEvent(event)
var event1 = new CustomEvent("stopRight", {
"detail": r
});
document.dispatchEvent(event1);
}, 300);
};
}
moves = [];
}
function myMove4(pos) {
var elem = document.getElementById("square");
var id = setInterval(frame, 5);
var i = elem.style.left == '' ? 0 : parseInt(elem.style.left.replace('px', ''));
pos = elem.style.left == '' ? pos : pos + i;
console.log(i + ' ' + pos);
function frame() {
if (elem.style.left == pos + 'px') {
clearInterval(id);
} else {
// pos++;
elem.style.left = (i++) + "px";
}
}
}
#square {
width: 50px;
height: 50px;
background-color: blue;
position: relative;
animation: myfirst 5s linear 2s infinite alternate;
}
<input type='button' value='up' onclick='up()'></input>
<input type='button' value='down' onclick='down()'></input>
<input type='button' value='left' onclick='left()'></input>
<input type='button' value='right' onclick='right()'></input>
<input type='button' value='Run' onclick='Run()'></input>
<div id="square"></div>
<!--https://jsfiddle.net/0rxs9jpy-->
What I am looking for is if I press the right button twice and then Run it does two movements and then stops.
One way to do this was to use javascript Promises
Working example is below:
<html>
<head></head>
<body>
<input type = 'button' value = 'up' onclick = 'up()'></input>
<input type = 'button' value = 'down' onclick = 'down()'></input>
<input type = 'button' value = 'left' onclick = 'left()'></input>
<input type = 'button' value = 'right' onclick = 'right()'></input>
<input type = 'button' value = 'Run' onclick = 'Run()'></input>
<br />
<br />
<br />
<div id = "square"></div>
<script>
var moves = [];
leftpx = 0;
downpx = 0;
uppx = 0;
rightpx = 0;
var up = function() {
moves.push('up')
}
var down = function() {
moves.push('down')
}
var left = function() {
moves.push('left')
}
var right = function() {
moves.push('right')
}
function setTimeoutPromise(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms);
});
}
function foo(item, ms) {
return function() {
return setTimeoutPromise(ms).then(function() {
if (item == 'right') {
myMove4(100)
};
if (item == 'down') {
myMove2(100)
};
if (item == 'left') {
myMove3(-100)
};
if (item == 'up') {
myMove(-100)
};
});
};
}
function bar() {
var chain = Promise.resolve();
moves.forEach(function(el, i) {
chain = chain.then(foo(el, 600));
});
return chain;
}
bar().then(function() {});
var Run = function() {
bar();
moves = [];
}
function myMove(pos) {
var elem = document.getElementById("square");
var id = setInterval(frame, 5);
var i = elem.style.top == '' ? 0 : parseInt(elem.style.top.replace('px', ''));
pos = elem.style.top == '' ? pos : pos + i;
console.log(i + ' ' + pos);
function frame() {
if (elem.style.top == pos + 'px') {
clearInterval(id);
} else {
elem.style.top = (i--) + "px";
}
}
}
function myMove2(pos) {
var elem = document.getElementById("square");
var id = setInterval(frame, 5);
var i = elem.style.top == '' ? 0 : parseInt(elem.style.top.replace('px', ''));
pos = elem.style.top == '' ? pos : pos + i;
console.log(i + ' ' + pos);
function frame() {
if (elem.style.top == pos + 'px') {
clearInterval(id);
} else {
// pos++;
elem.style.top = (i++) + "px";
}
}
}
function myMove3(pos) {
var elem = document.getElementById("square");
var id = setInterval(frame, 5);
var i = elem.style.left == '' ? 0 : parseInt(elem.style.left.replace('px', ''));
pos = elem.style.left == '' ? pos : pos + i;
console.log(i + ' ' + pos);
function frame() {
if (elem.style.left == pos + 'px') {
clearInterval(id);
} else {
// pos++;
elem.style.left = (i--) + "px";
}
}
}
function myMove4(pos) {
var elem = document.getElementById("square");
var id = setInterval(frame, 5);
var i = elem.style.left == '' ? 0 : parseInt(elem.style.left.replace('px', ''));
pos = elem.style.left == '' ? pos : pos + i;
console.log(i + ' ' + pos);
function frame() {
if (elem.style.left == pos + 'px') {
clearInterval(id);
} else {
// pos++;
elem.style.left = (i++) + "px";
}
}
}
</script>
<style>
#square{
width: 50px;
height: 50px;
background-color: blue;
position: relative;
animation: myfirst 5s linear 2s infinite alternate;
}
</style>
</body>
</html>

Converting Javascript to jQuery not working

I wrote a basic slider in Javascript in a practice file and now trying to implement it in my site by converting it to jQuery for efficiency, however with using jQuery it doesn't work. I don't see where I am wrong.
JavaScript
(function Slider() {
var slide = document.getElementsByClassName("slide"),
dot = document.getElementsByClassName("dot"),
slideList = [slide[0],slide[1],slide[2]],
buttonL = document.getElementById('btL'),
buttonR = document.getElementById('btR'),
index = 0;
slideList[0].style.display = 'block';
(function displayDot() {
var dotContainer = document.getElementById('dotContainer'),
dotHtml ='',
i;
for (i = 0; i < slideList.length; i++) {
dotHtml += '<div class="dot"></div>';
}
dotContainer.innerHTML = dotHtml;
}());
dot[0].style.backgroundColor = '#e29f6f';
function slideIt(direction) {
previous = index;
if (direction === 'right') {
index++;
if (index >= slideList.length) {
index = 0;
}
} else if (direction === 'left') {
index--;
if (index < 0) {
index = slideList.length-1;
}
}
slideList[index].style.display = 'block';
slideList[previous].style.display = 'none';
dot[index].style.backgroundColor = '#e29f6f';
dot[previous].style.backgroundColor = 'grey';
}
buttonR.addEventListener('click', function(){ slideIt('right'); }, false);
buttonL.addEventListener('click', function(){ slideIt('left'); }, false);
}());
jQuery attempt
$(document).ready(function() {
var slide = $( ".slide" ),
dot = $( ".dot" ),
slideList = [slide[0], slide[1], slide[2]],
buttonL = $( '#btL' ),
buttonR = $( '#btR' ),
index = 0;
slideList[0].css("display", "block");
(function displayDots() {
var dotContainer = $( "#dotContainer" ),
dotHtml ='',
i;
for (i = 0; i < slideList.length; i++) {
dotHtml += '<div class="dot"></div>';
}
dotContainer.append(dotHtml);
}());
dot[0].css("background-color", "#e29f6f");
function slideIt(direction) {
previous = index;
if (direction === 'right') {
index++;
if (index >= slideList.length) {
index = 0;
}
} else if (direction === 'left') {
index--;
if (index < 0) {
index = slideList.length-1;
}
}
slideList[index].css("display", "block");
slideList[previous].css("display", "none");
dot[index].css("background-color", "#e29f6f");
dot[previous].css("background-color", "grey");
}
buttonL.click(function() {
slideIt('left');
});
buttonR.click(function() {
slideIt('right');
});
});
when you do something like:
$( ".dot" )
You can do:
$( ".dot" ).css(...);
The result is a JQuery collection
But no
$( ".dot" )[0].css(...);
$( ".dot" )[0] is a DOM node
You can do for example:
var elem = $( ".dot" )[0];
$(elem).css(...);

Resolve conflict with navigation slider in javascript

I'm currently building a small slider in Javascript
which is working pretty well (almost) but I have an issue !
You will find here the codepen link :
Slider
Line 22, 32, 38
I have my two navigations supposed to add a class active (after remove) but I have a shift with my next/prev button and the other buttons below the slider. I can't find a solution and it's a pain :( !
Any idea ? Thank you !
Try to use this your changed code:
var currentSlide = 0;
var prevSlide = 0;
var slider = document.getElementById('slider').children[0];
var slides = document.getElementsByClassName('slider-item');
var links = document.getElementsByClassName('link');
var prev = document.querySelector('.prev');
var next = document.querySelector('.next');
var btnActive = document.getElementsByClassName('set-active');
for (var i = 0; i < slides.length; i++) {
slider.style.width = (slides[0].clientWidth * slides.length) + 'px';
links[i].innerHTML = i + 1;
links[i].addEventListener('click', function(e) {
e.preventDefault();
prevSlide = currentSlide;
currentSlide = this.getAttribute('data-href');
slider.style.left = '-' + (100 * currentSlide) + '%';
utils.addClass(links[currentSlide], 'active');
utils.removeClass(links[prevSlide], 'active');
});
}
function updateSlide() {
slider.style.left = '-' + (100 * currentSlide) + '%';
utils.addClass(links[currentSlide], 'active');
utils.removeClass(links[prevSlide], 'active');
}
prev.addEventListener('click', function() {
if(currentSlide == 0)
return
prevSlide = currentSlide;
currentSlide--;
updateSlide();
});
next.addEventListener('click', function() {
if(currentSlide == 10)
return
prevSlide = currentSlide;
currentSlide++;
updateSlide();
});
var utils = utils || (function() {
'use strict';
return {
hasClass: function(el, cl) {
var regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
return !!el.className.match(regex);
},
addClass: function(el, cl) {
el.className += ' ' + cl;
},
removeClass: function(el, cl) {
var regex = new RegExp('(?:\\s|^)' + cl + '(?:\\s|$)');
el.className = el.className.replace(regex, ' ');
},
toggleClass: function(el, cl) {
var testClass = this.hasClass(el, cl) ? this.removeClass(el, cl) : this.addClass(el, cl);
},
getNextElementSibling: function(el) {
if (el.nextElementSibling) {
return el.nextElementSibling;
} else {
do {
el = el.nextSibling;
}
while (el && el.nodeType !== 1);
return el;
}
},
elementInViewport: function(el) {
var rect = el.getBoundingClientRect();
return (
rect.top >= 0 && rect.left >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight)
);
},
sameHeight: function(el) {
var maxHeight = 0;
for (var i = 0; i < el.length; i++) {
var thisHeight = el[i].offsetHeight;
if (thisHeight > maxHeight) {
maxHeight = thisHeight;
}
}
for (i = 0; i < el.length; i++) {
el[i].style.height = maxHeight + 'px';
}
}
};
})();

Categories