I am looking to create a webpage that scrolls on a continuous loop from one element to the next without any user interaction. I have searched and it looks like scrollToElement is what I'm looking for (in fact the fiddle from this answer on another post is similar but does have user interaction). Unfortunately everything seems to be done by click or doesn't loop. I'm fairly new to JS but I feel like it should be doable. Any help is appreciated.
How about creating a function that calls scrollToElement and then setting it as a CB function in the setInterval(). read more:MDN
Here's a quick example with jQuery using setInterval() and $.animate() to scroll to sections.
var $sections = $('section'),
count = 1,
speed = 250,
delay = 2000;
var interval = setInterval(function() {
$('html, body').animate({
scrollTop: $sections.eq(count).offset().top
}, speed);
count = (count + 1) % $sections.length;
}, delay)
section {
height: 200vh;
background: red;
}
section:nth-child(2) {
background: blue;
}
section:nth-child(3) {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section></section>
<section></section>
<section></section>
Related
I am trying to control a GSAP animation using a forward & backward button. The expected behaviour I am aiming for is:
When the user hovers over the forward button the animation moves forward (increments in px).
When the user mouseleaves the button then the animation pauses.
When the user hovers over the backwards button the animation moves the other way.
The issue I have encountered is that I have tried to add a dynamic positioning variable in place which increments when the user hovers over the 'forward' button. This is not working as expected - instead it just moves once instead of waiting until the user's mouse leaves to stop.
I tried to add a setInterval to the button event listener to increment the positioning so that when the user hovered over the button it would move px at a time, which did work, but it would not stop causing the browser to crash. I also added a mouseleave to clear the setInterval but I don't think it was good practise.
var masterTimeline = new TimelineMax();
var mousedown = false;
var forwardBTN = document.getElementById("forward");
var backwardBTN = document.getElementById("backward");
var pauseBTN = document.getElementById("pause");
var blueboxElement = document.getElementById("blueBox");
var direction = '+';
var counter = 0;
var distance = 0;
var value1 = direction + '=' + distance;
var tween;
forwardBTN.addEventListener("mouseenter", function(){
// setInterval(function() {
directionMove('moveForward');
// }, 500);
});
backwardBTN.addEventListener("mouseenter", function(){
directionMove('moveBackward')
});
pauseBTN.addEventListener("click", function(){
directionMove('pause');
});
function directionMove(playk) {
if (playk == 'moveBackward') {
var direction = '-';
value1 = direction + '=' + distance; // how to update value
masterTimeline.to(blueboxElement, 0.1, {css: {x: value1}, ease: Linear.easeNone}); // no need move by default
}
else if (playk == 'moveForward') {
var direction = '+';
value1 = direction + '=' + distance; //how to update value
masterTimeline.to(blueboxElement, 0.1, {css: {x: value1}, ease: Linear.easeNone}); // no need move by default
}
else if (playk == 'pause') {
masterTimeline.kill();
console.log("killed");
//
}
}```
The expected behaviour is to move forward incrementally without stopping until the user moves off the forward button but at present it is just moving a single amount one time.
Here is a CodePen link if this helps:
https://codepen.io/nolimit966/pen/pXBeZv?editors=1111
I think you're overcomplicating this a bit (at least in the demo). The entire point of GSAP is moving things along a timeline. What you're trying to do is essentially forcibly use a timeline to work in a non-timeline way, which is why I think you're having trouble.
If you step back and just think about your three requirements, I think it becomes a lot more simple. It's always good to think about it in words like you did because it can help you simplify it and understand it better.
The key steps are to:
Create a timeline for the movement of the box.
Play the timeline forward when the forward button is hovered.
2b. Pause it when it's no longer hovered.
Play the timeline backward when the reverse button is hovered.
3b. Pause it when it's no longer hovered.
In code that looks like this:
var tl = new TimelineMax({paused: true});
var forwardBTN = document.getElementById("forward");
var backwardBTN = document.getElementById("backward");
var pauseBTN = document.getElementById("pause");
var blueboxElement = document.getElementById("blueBox");
tl.to(blueboxElement, 10, {x: window.innerWidth - blueboxElement.clientWidth, ease: Linear.easeNone});
function pause() {
tl.pause();
}
forwardBTN.addEventListener("mouseenter", function() {
tl.play();
});
forwardBTN.addEventListener("mouseleave", pause);
backwardBTN.addEventListener("mouseenter", function() {
tl.reverse();
});
backwardBTN.addEventListener("mouseleave", pause);
Demo
By the way, you're much more likely to get a faster response over on the official GreenSock forums :)
Do you mean something like this?
var tl = new TimelineMax({paused: true});
tl.to('.element', 3, {
x: 800,
});
$(document).on({
mouseenter: function () {
if($(this).hasClass('forward')){
tl.play();
}
else if($(this).hasClass('backwards')){
tl.reverse();
}
},
mouseleave: function () {
tl.pause();
}
}, ".btn");
.wrapper{
width: 100%;
padding: 40px;
}
.element{
width: 100px;
height: 100px;
background: red;
}
.btn{
display: inline-block;
padding: 15px;
background: #bbb;
margin-top: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrapper">
<div class="element_wrapper">
<div class="element"></div>
</div>
<div class="forward btn">Forward</div>
<div class="backwards btn">Backwards</div>
</div>
Currently I have a simple fire animation. It just show two flames tongues in same place and show hide within 0.3s. Right now I want set delays. After few milliseconds, stop the loop and start again like that. I tried with javascript setInterval but it's continuously running.
var $wrapper = $('.wrapper');
setInterval(function() {
$wrapper.toggleClass("alt");
}, 300);
.wrapper {
text-align: center;
position: relative;
}
.flames,
.wrapper-img,
.show-1,
.show-2 {
position: absolute;
}
.flames {
display: none;
}
.flame-1 {
left: 38px;
top: 32px;
}
.flame-2 {
left: 67px;
top: 40px;
}
.flame-2 img {
top: 220px;
}
.wrapper-img {
top: 220px;
}
.wrapper .flame-1 {
display: block;
}
.wrapper .flame-2 {
display: none;
}
.wrapper.alt .flame-1 {
display: none;
}
.wrapper.alt .flame-2 {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="flame-1 flames">
<img src="https://i.imgur.com/0Pfsrdh.png" alt="">
</div>
<div class="flame-2 flames">
<img src="https://i.imgur.com/EypytyC.png" alt="">
</div>
<div class="wrapper-img">
<img src="https://i.imgur.com/moNtPwG.png" class="wrap-img" alt="">
</div>
</div>
Any solution? Jsfiddle
As far as I see you need soething like this
var $wrapper = $('.wrapper');
function flamebaby(){
$wrapper.toggleClass("alt");
setTimeout(function() {
$wrapper.toggleClass("alt");
setTimeout(function() {
flamebaby();
},600)
}, 200);
}
flamebaby();
https://jsfiddle.net/uy43w5qq/7/
You are probably looking for CSS keyframe animations which will let you run keyframe based transitions/animations without the need of JavaScript. This will also ensure that the browser can do optimizations for your animations, they will probably run smoother.
JS based answers are already provided so I'm not going in there except for a small sidenote on setInterval.
Using setInterval() is not recommended since the body function theoretically may take longer than the interval causing a stackoverflow. A better way is to use setTimeout to call a function, which at the end of executions schedules a new timeout for itself.
const foo = () => {
console.log('bar');
setTimeout(foo, 300);
}
setTimeout(foo, 300);
Also, when animating is may be useful to first use pen and paper to write down how the animations should behave, this may help when writing the code to implement them.
I'm not sure, if i understand correctly, but what you want is this ?
var $wrapper = $('.wrapper');
function startAnimation () {
var animationCount = 4
var iterationCount = 0
var intervalValues = {
animation: 300,
loops: 900
}
function toggleAlt () {
$wrapper.toggleClass("alt");
iterationCount++
if (iterationCount > 0 && iterationCount % animationCount === 0) {
setTimeout(toggleAlt, intervalValues.loops)
} else {
setTimeout(toggleAlt, intervalValues.animation)
}
}
toggleAlt();
}
startAnimation()
i've tried to keep simple, Fiddle: https://jsfiddle.net/50gemkrk/
Toggle class few times with interval of few ms.
Wait for few ms.
Repeat first step: Toggle class few times with interval of few ms
IMHO,
I might be wrong, but setIntervals is not recommended in most of cases, it's easy to lose control
Also, i agree with Sven's answer, CSS3 Animation is cool, i recomend it !
take a time To look at this website http://www.thejewelrysource.net/ and stay for like 7 seconds in the bottom left corner there is a small pop up that will appear and disappear again I want to do something like that using Jquery.
I know I could use Slideup and SlideDown Method but the problem I am facing is that How could traverse to the Given data in an Array so that I will Pop up the Data One at a Time. I am using only Static Data. Thank you for your Help in Advance! may someone help me! Thank You So Much
I couldn't understand much from your description. By any chance is this what are you looking are?
I have used setTimeout and setInterval to simulate this and a closure variable to keep track of the next item to display.
$(document).ready(function() {
var $popup = $(".popup"),
aMessages = ["Hello", "This is alert", "Is this what are you look for?"],
counter = 0;
$(".popup").hide();
var interval = setInterval(showMessage, 3000);
function showMessage() {
var iMessageId = counter % aMessages.length;
$popup.text(aMessages[iMessageId]);
$popup.show();
counter++
setTimeout(hideMessage, 1000);
}
function hideMessage() {
$(".popup").fadeOut(100);
}
setTimeout(function() {
clearInterval(interval);
}, 10000);
});
.popup {
width: 200px;
height: 100px;
background-color: yellow;
border-radius: 50px;
padding: 20px;
position: fixed;
left: 10px;
bottom: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div class="popup"></div>
I am currently learning JavaScript and all the solutions that I've come across use the jQuery library. Is there a way to do it, just using pure JavaScript?
The idea is to have something like:
function passed(element) {if passed: do something}
Listen for the scroll event. To find the current scroll position, you can call the scollY method.
To get the Y coordinate of the top of an element, you can use the element's offsetTop. Because the element has a height, we want to add the height to our calculation.
That's it.
window.addEventListener("scroll", function() {
var elementTarget = document.getElementById("section-2");
if (window.scrollY > (elementTarget.offsetTop + elementTarget.offsetHeight)) {
alert("You've scrolled past the second div");
}
});
.section-1 {
height: 400px;
width: 100%;
background: green;
}
.section-3 {
height: 400px;
width: 100%;
background: orange;
}
<div class="section-1"></div>
<div id="section-2">Scroll past this div</div>
<div class="section-3"></div>
You should be able to use the following:
if(window.scrollY >(element.offsetHeight + element.offsetTop)){
// do something
}
With https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetTop you can get the Y coordinate of an element.
With https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY you can get the current Y coordinate of the scroll.
With https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight you get the height of an element.
So the only thing that remains to do is to check if scrollY > (offsetHeight + offsetTop). If this is true, you passed the element with the scroll.
I leave to you the implementation, as a practice to learn Javascript ;)
if (element.getBoundingClientRect().y < 0) {
// do something
}
This can be achieved with the IntersectionObserver API without having to rely on scroll events at all.
const elementTarget = document.getElementById("section-2");
// skip first callback when first observing
let firstCallback = true;
const observer = new IntersectionObserver(entries => {
if (!entries[0].isIntersecting) {
if (firstCallback) {
firstCallback = false;
} else {
alert("You've scrolled past the second div");
}
}
});
observer.observe(elementTarget);
// remember to unobserve when done
.section-1 {
height: 1000px;
width: 100%;
background: green;
}
.section-3 {
height: 1000px;
width: 100%;
background: orange;
}
<div class="section-1"></div>
<div id="section-2">Scroll past this div</div>
<div class="section-3"></div>
I am using datatables with a custom plugin I got from here fnSetFilteringDelay but wanted to add an indicator or loader of some sort to tell the user when the search will happen on the typed text in the filter textbox. I have done this but it is a bit buggy, maybe someone can help me to get this fluent and beautiful.
But if you type more and more, the indicator bar starts to look like it is shattering.
I would like to get rid of the shattering part if possible.
Here is my code after initialising the datatables to variable oTable
oTable.fnSetFilteringDelay(550); //After the last character is entered, will take 550 milliseconds to search
$('#gvProjectList_filter input').parent().append($("<div id='lder' style='width: 0px; height: 30px; background-color: #999; float:right;'></div>"));
$('#gvProjectList_filter input').on('keyup', function (a) {
document.getElementById("lder").style.width = "50px"; //Start the indicator at 50px and end at 0px
var count = 550; //Same as the filtering delay set above
var counter = setInterval(timer, 25); //will run it every 25 millisecond
function timer() {
count -= 25; //Minus 25 milliseconds
if (count <= 0) {
clearInterval(counter);
document.getElementById("lder").style.width = "0px";
return;
}
var neww = parseInt((count / 550) * 50); //calculate the new width vs. time left of 550ms
document.getElementById("lder").style.width = neww + "px";
}
});
Basically it must start at 50px width, and go down, when the user types another character, the bar must start at 50px again.
Here is my jsFiddle demo, just type something to search, first one letter and then a whole name, you will see what I mean.
I have found my own solution. I have made use of the jquery animate function
oTable.fnSetFilteringDelay(550);
$('#mytable_filter input').parent().append($("<div id='lder' style='width: 0px; height: 20px; background-color: #999; float:right;'></div>"));
$('#mytable_filter input').on('keyup', function (a) {
$("#lder").width('50px');
$("#lder").stop().animate({width:'0px'},550);
});
works like a charm!
Here is the final Fiddle, check it out!