I have a div .move that starts to move from left to right when the button "go div" is clicked.
Then I have two div .sound in the center of content div with an audio element.
I want that when the div .move arrives to .sound div, the audio inside .sound div starts to play.
But how to say whenever .move div arrives at .sound element, every audio elements in .sound div starts to play?
https://jsfiddle.net/dda5z70r/
jQuery:
$( "#div" ).click(function() {
https://jsfiddle.net/popnoodles/dda5z70r/5/
Check for collision each animate step.
Add your code to play the sound where I have added a class to show this visually.
NB I added the ID bar to the bar that moves because it's faster to search the DOM for an ID than a class. If you have more than one moving bar I can alter this.
$( "#go" ).click(function() {
var stop = $(".stop").offset().left;
var obj = document.getElementById("audio");
// how to say whenever .move div arrives at .sound element, the sound associated to that .sound div starts to play?
//obj.play();
$( "#bar" ).animate({
opacity: 0.25,
left: stop-($(".stop").width()+$(this).width()),
}, {
duration: 5000,
step: function(){
$('.sound').each(function(){
if (collision($(this), $('#bar'))){
$(this).addClass('playme');
} else{
$(this).removeClass('playme');
}
});
}, complete: function() {
$(this).css('left',0);
$(this).css('height','100%');
}});
});
function collision($div1, $div2) {
var x1 = $div1.offset().left;
var r1 = x1 + $div1.width();
var x2 = $div2.offset().left;
var r2 = x2 + $div2.width();
if (r1 < x2 || x1 > r2) return false;
return true;
}
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>
I can't figure out of to make scroll, (when a div is clicked), and make it smooth. (like not going straight to the scroll position)
Here's my code:
$('.about-center').click(function() {
var div = document.getElementById('ABOUT');
var pos = div.offsetTop;
$(window).scrollTop(pos);
});
try this one:
$('.about-center').click(function() {
var div = $('#ABOUT');
var pos = div.offset().top;
$('html, body').animate({scrollTop:pos},2000); // will take two seconds to scroll to the element
});
I am having some issues with some code. I am trying to get a div to move in time with a slider show. Each time a new slide is shown the div moves.
This is what I came up with
setInterval(function() {
$( ".bar" ).animate({ "left": "+=13.5em" }, "slow" );
}, 3000);
This works great, the div keeps up with the slider. But It never stops. I have been trying to come up with the code to make this work but I can't seem to do it.
Once the div reaches a certain point I want it to go back to its starting point and then repet its animation over and over just as the image slider does.
Could I put another timer on another line of code to tell the div to go back to a point after a set duration? then the above code will keep playing the aniamtion? (I will give this ago now!)
Are you using a plugin for the slider? Some plugins you can set a callback like flexslider plugin:
$(elem).flexslider({
before: function(){
//event before slide transition
},
after: function(){
//event after slide transition
}
});
var count = $(".bar").length;
var current = 1;
setInterval(function() {
$( ".bar" ).animate({ "left": "+=13.5em" }, "slow" );
current++;
if(current == count) {
$( ".bar" ).animate({ "right": "+=" + (count*13.5) "em" }, "fast" );
current = 1;
}
}, 3000);
Maybe something like that?
var startPos = $(".bar").offset();
var endPos = $("foo").offset();
var foo = setInterval(function() {
var updatedPos = $( ".bar" ).position();
if (updatedPos.left === endPos.left) {
$(".bar").css({"left":startPos.left,"top":startPos.top});
}
$( ".bar" ).animate({ "left": "+=13.5em" }, "slow" );
}, 3000);
EDIT:
var pos = $(".bar").offset(); this gets the position relative to the document, you could also get the position relative to the parent node with .position() and then check on the interval if it hit the position, you could also just update the left right or top bottom, depending on your needs. but this would be a way to reset the position. You just need to know the start and end points.
I am developing a website which have a scrolling newsticker in a strip using jquery.li-scroller.1.0.js.
page address is: http://www.designforce.us/demo/ticker/index.html
When we hover the mouse on the newsticker, strip is stop. At this stage i want to show a popup box right under the current li with its text. something i've done and when we hover the mouse pointer over the strip, newsticker stops and box is showing with its text.
PROBLEM:
jquery.li-scroller newsticker have a wrapper with {overflow:hidden} so if i add the popup box withing li then its not showing. Thats why i've coded the popup (.tickPop) withing a seperate space and white some script of jquery document ready. my script is:
$('ul#ticker01 li').each(function(e){
var iClass;
$(this).hover(function(){
iClass = $(this).attr('class');
$(this).css('height',$('tickPop').height()+30)
var offset = $(this).offset();
var left = offset.left;
var top = offset.top+20;
var iWidth = $(this).width();
var sText = $(this).children().html();
$(this).css('background','#f6f4f4');
$('.tickPop').css('left',left);
$('.tickPop').css('top',top);
$('.tickPop').css('width',iWidth);
$('.tickPop').css('display','block');
$('.tickPop').text(sText);
}, function(){
$('.tickPop').mouseleave(function(){
bHovering = false;
$(this).css('display','none');
});
$(this).css('background','transparent');
//$('.tickPop').css('display','none');
if(iClass == 'Yellow')
$(this).css('background','url(images/icon-yellow.jpg) left center no-repeat');
else
$(this).css('background','url(images/icon-white.jpg) left center no-repeat');
});
});
popup box called $('.tickPop') is hidden by default and when user hover on newsticker then jquery function set the attribute $('.tickPop').css('display','block') and it is visible.
Now problem is that as we move the mouse pointer over the popup box then newsticker is again start scrolling while i want when we mouseleave from the popup box then newsticker should start.
Dear Experts, Please advise..............?
Looking forward for a kind response.
Regards
You should modify jquery li-scroller sources.
watch this code (from li-scroller sources):
function scrollnews(spazio, tempo){
$strip.animate({left: '-='+ spazio}, tempo, "linear", function(){$strip.css("left", containerWidth); scrollnews(totalTravel, defTiming);});
}
scrollnews(totalTravel, defTiming);
// $strip = $(this) so it triggers when you're hover a news
$strip.hover(function(){
jQuery(this).stop();
},
function(){
var offset = jQuery(this).offset();
var residualSpace = offset.left + stripWidth;
var residualTime = residualSpace/settings.travelocity;
scrollnews(residualSpace, residualTime);
});
You should add something like:
var popup = jQuery('.tickPop');
popup.hover(function(){
$strip.stop();
},
function(){
var offset = jQuery(this).offset();
var residualSpace = offset.left + stripWidth;
var residualTime = residualSpace/settings.travelocity;
scrollnews(residualSpace, residualTime);
});
I didn't test that code but should work....
P.S. Sorry for the indentation
Basically there are 4 images that scroll off the page. Now when a user clicks the link, that one scrolls off. But I wanted to added an additional animation where a paragraph (".image_text p") appears on page as well and then when another link is clicked, that text goes along with rest of image and scrolls off. Everything works except the animation of the paragraph part.
The problem:
The text is all squished together (there's four paragraphs and they are overlapping each other)
When I click - it doesn't even have time to fade it- and foes swirving off page before it fades.
First time page loads, the first paragraph doesn't even appear at all - when button is clicked, all paragraphs appear. It's supposed to be the first paragraph appears on page load and then click then the next paragraph appears as first scrolls away with image.
The markup and css are correct. I think problem is somewhere in this javascript:
$(function() {
$('#slideshow').crossSlide({
sleep: 2,
fade: 1
}, [
{ src: '../images/img1.png' },
{ src: '../images/img2.png' },
{ src: '../images/img3.png' },
{ src: '../images/img4.png' }
])
$(".paging").show();
$(".paging a:first").addClass("active");
$(".image_text p:first").addClass("active");
//Get size of the image, how many images there are, then determin the size of the image reel.
var imageWidth = $(".window").width();
var imageSum = $(".image_reel img").size();
var imageReelWidth = imageWidth * imageSum;
//Adjust the image reel to its new size
$(".image_reel").css({'width' : imageReelWidth});
//Paging and Slider Function
rotate = function(){
$activep = $('.image_text p:first');
var triggerID = $active.attr("rel") - 1; //Get number of times to slide
var image_reelPosition = triggerID * imageWidth; //Determines the distance the image reel needs to slide
$(".paging a").removeClass('active'); //Remove all active class
$(".image_text p").removeClass('active'); //Remove all active class
$active.addClass('active'); //Add active class (the $active is declared in the rotateSwitch function)
$activep.addClass('active');
//Slider Animation
$(".image_reel").animate({
left: -image_reelPosition
}, 500 );
$(".image_text p").animate({
opacity: .99,
left: -image_reelPosition
}, 500 );
};
//Rotation and Timing Event
rotateSwitch = function(){
play = setInterval(function(){ //Set timer - this will repeat itself every 7 seconds
$active = $('.paging a.active').next(); //Move to the next paging
$activep = $('.image_text p').next(); //Move to the next paging
if ( $active.length === 0) { //If paging reaches the end...
$active = $('.paging a:first'); //go back to first
}
rotate(); //Trigger the paging and slider function
}, 7000); //Timer speed in milliseconds (7 seconds)
};
rotateSwitch(); //Run function on launch
//On Hover
$(".image_reel a").hover(function() {
clearInterval(play); //Stop the rotation
}, function() {
rotateSwitch(); //Resume rotation timer
});
//On Click
$(".paging a").click(function() {
$active = $(this); //Activate the clicked paging
//Reset Timer
clearInterval(play); //Stop the rotation
rotate(); //Trigger rotation immediately
rotateSwitch(); // Resume rotation timer
return false; //Prevent browser jump to link anchor
});
});
CSS for paragraph:
.image_text p {
text-align: right;
width: 500px;
opacity: 0;
position: absolute;
top: 0;
left: 0;
}
As it can bee seen the reason why the text isn't shown is because the opacity starts at 0. But this is intended because it's supposed to fade in. However, it appears it doesn't fade in but rather only becomes visible when link is clicked and by that time it scrolls off the page.
The solution was to specify how may p tags and multiple that by width of container and then specifying the container with the css declaration overflow:hidden, which hides all p tags except the current. Also, p tags had to be floated left in order to get them to behave inline:
.window {
margin-top: 20px;
height:286px;
width: 655px;
overflow: hidden;
position: relative;
}
.image_text {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
.image_text p {
float: left;
margin-left: 10em;
}