Hello I am trying to achive this effect http://mario.ign.com/modern-era/super-mario-3D-world no mousemove I would like to do it with some kind of ease effect to make it smooth but actually dont know how to achive de desaceleration effect, so far what I've done is this http://jsfiddle.net/xtatanx/8RB24/1/:
var $container = $('#container');
var contWidth = $container.width();
var $point = $('.point');
var delay = 100;
$container.mousemove(function(e){
clearTimeout(timer);
var timer = setTimeout(function(){
console.log(e.offsetX);
$point.each(function(){
if( e.offsetX > (contWidth - $point.width())){
return;
}
var xp = $(this).position().left;
xp += parseFloat((e.offsetX - xp)/ 20);
$(this).css({
left: xp
});
});
}, delay);
});
But I think that the animation doesnt feel as smooth as mario site i would appreciate if you guys could help me ginding resources or guiding me to achieve this effect. Thank you very much.
Your choppiness is because it's running solely on the mousemove event. If you break it out into an interval (say 30 frames per second), it will be much smoother. This way it continues to ease even after the mouse stops.
var $container = $('#container');
var contWidth = $container.width();
var $point = $('.point');
var delay = 100;
var decay = .1;
var intervalId;
var mouseX, mouseY;
//this function is called 30 times per second.
function ticker(){
$point.each(function(){
if( mouseX > (contWidth - $point.width())){
mouseX = (contWidth - $point.width()); //instead of returning, just set the value to the max
}
var xp = $(this).position().left;
xp += parseFloat((mouseX - xp) * decay); //using a decay variable for easier tweaking
$(this).css({
left: xp
});
});
}
//this interval calls the ticker function every 33 milliseconds
intervalId = setInterval(ticker, 33); //33 millisecond is about 30 fps (16 would be roughly 60fps)
$container.mousemove(function(e){
mouseX = e.offsetX; //store the current mouse position so we can reference it during the interval
mouseY = e.offsetY;
});
take a look at this. not sure it this is what you want but it sure does "a" trick.
$container.mousemove(function(e){
var xp = e.clientX-offset;
blue.css({
left: xp+'px'
});
});
http://jsfiddle.net/d65yan/8RB24/2/
look at the .blue{} css
some vendro prefix are needed if you want to support older versions of moz and chrome, forget about ie up to version 9 though
Related
I have the following code which works fairly okay to set a video's current time to the page's scroll position:
var vid0 = document.getElementById('v0');
var scrollpos = 0; var targetscrollpos = 0; vid0.pause();
window.onscroll = function(){ targetscrollpos = window.pageYOffset / 1700;};
setInterval(function(){
scrollpos += (targetscrollpos - scrollpos) * 0.25;
vid0.currentTime = scrollpos; vid0.pause();
}, 40);
My issue is that this is independent of the page height - so you set the acceleration with a number, instead of calculating either that number from the page height or connect the page height somehow to the video's length, so when the user scrolls the video ends exactly when the document is scrolled all the way to the end.
The playback speed in this case would depend on the document length, which is absolutely fine and expected, I just have no idea how to go about this issue.
Any ideas?
solved it.
var vid0 = document.getElementById('v0');
var scrollpos = 0; var targetscrollpos = 0; vid0.pause();
window.onscroll = function(){
var vrate = document.body.scrollHeight / (vid0.duration * 1.1);
targetscrollpos = window.pageYOffset / vrate;};
setInterval(function(){
scrollpos += (targetscrollpos - scrollpos) * 0.25;
vid0.currentTime = scrollpos; vid0.pause();
}, 40);
What I want to achieve is a javascript animation with variable speed based on cursor position.
For that porpouse I'm using jquery's animate function and mousever event and javascript's setInterval function, but those aren't required, so if there is a better way to achieve it I would be more than happy to hear it (the only requeriment would be javascript).
The problem I'm facing is that I can't change speed dinamicly, for some reason the speed keeps adding to the one it already had instead of set what I wanted and even if it would change as spected it just doesn't happen in a smoothly way because of an unknown reason for me.
Here is the javascript that I have so far:
//settings for container_slider. Are used in startSlider() which handles the animation
var steps_animation_speed = 1000;
var steps_interval = 1500;
var steps_speed_factor = 1; // 100%
var amount_sliders = 3;
//cache DOM elements
var $container_slider = $('#container_slider');
var $shown_slides = $('.shown_slides', $container_slider);
var $slide = $(".slide");
// Just making sure sizing (widths) fits as they should.
var slides_width = $container_slider.width()/amount_sliders;
var slides_margin = parseInt($slide.css('marginLeft').replace('px', '')) + parseInt($slide.css('marginRight').replace('px', ''));
var steps_width = slides_width + slides_margin;
$shown_slides.css('width', steps_width*(amount_sliders+1) + 'px');
$slide.css('width', slides_width);
var interval;
// This function is responsible of the animation
function startSlider() {
$shown_slides.stop(false);
interval = setInterval(function() {
$shown_slides.animate({'margin-left': '-='+steps_width}, steps_animation_speed*steps_speed_factor, function() {
$('.shown_slides > li:last').after($('.shown_slides > li:first'));
$('.shown_slides').css('margin-left', '0');
});
}, steps_interval);
}
function pauseSlider() {
clearInterval(interval);
}
$container_slider.mouseleave(function(){
steps_interval = 3000;
$shown_slides.stop(true);
pauseSlider();
startSlider();
});
// $container_slider.mouseenter(function(){
// pauseSlider();
// });
$container_slider.mousemove(function(event){
pauseSlider();
var cursor_location = '';
if(event.pageX > 0 && event.pageX < 165){
cursor_location = "Cursor is on the left side";
// This is where i'm doing the tests that should work of changing animation's speed based on cursor position
if(steps_speed_factor !== (event.pageX / 165)){
steps_speed_factor = event.pageX / 165;
steps_speed_factor = (steps_speed_factor < 0.15 ? 0.15 : steps_speed_factor);
steps_interval = 0;
startSlider();
}
} else if(event.pageX > 165 && event.pageX < ($container_slider.width()-165)){
cursor_location = "Cursor is in the center (paused)";
// This stops animation, it could be achieved way better but i'm focusing on above's block of code.
steps_speed_factor = 1;
steps_interval = 3000;
$shown_slides.stop(true);
pauseSlider();
} else if(event.pageX > ($container_slider.width()-165) && event.pageX < $container_slider.width()) {
cursor_location = "Cursor is on the right side";
// This would be an exact copy (almost) of the left side, but since it doesn't work yet, this is pretty much a "blank" block of code
steps_interval = 0;
steps_speed_factor = ( event.pageX - ($container_slider.width() - 165) ) / 165;
}
$(".coordinates").html("X: " + event.pageX + " Y: " + event.pageY );
$(".cursor_location").html(cursor_location);
$(".speed_factor").html("Speed Factor is: "+steps_speed_factor);
});
startSlider();
Here is a codepen showing this javascript code "working".
--- EDIT
I forgot to explain propperly what happens in the codepen , since it is just an example didnt give it to much importance. Mainly what should happen is that the furthier the cursor is from the center, the tinier/faster the invervals of the animation should be without losing fluidness.
In this case i'm using a "speed factor" which I calculate by taking cursor's X position and then comparing it with a predefined area, converting it in a percentage (decimal) from 15% to 99%. But it isn't actually the important part. I'm clueless about how to achieve this and the more I try the messier my code gets, so as long as you can give me an example of changing animation's speed (in "real" time, i mean, smoothly/fluid) based on cursor's position as an example it would be perfect.
I adapted this code to create a large div which scrolls horizontally inside a smaller div, depending on the position of the mouse.
You can see my example here.. http://thetally.efinancialnews.com/tallyassets/20years/index.html
What I am trying to achieve is for the inner (yellow) div to stop at a maximum of left:0px, in other words the far left of the yellow div will become stuck to the far left of the outer div if you go that far.
I tried to implement this with an 'if else' statement, however as this piece of code gets run every 30th of a second it creates a strange result, which I can't find a solution for. I'm sure its very simple but its stumped me
You can see my code here...
var x=0,
rate=0,
maxspeed=10;
var backdrop = $('.container');
var years = $('.events');
$('.direction', backdrop).mousemove(function(e){
var $this = $(this);
var left = $this.is('.left');
if (left){
var w = $this.width();
rate = (w - e.pageX - $(this).offset().left + 1)/w;
} else {
var w = $this.width();
rate = -(e.pageX - $(this).offset().left + 1)/w;
}
});
backdrop.hover(function(){
var scroller = setInterval( moveBackdrop, 30 );
$(this).data('scroller', scroller);
},
function(){
var scroller = $(this).data('scroller');
clearInterval( scroller );
});
function moveBackdrop(){
if ( parseInt(years.css("left"), 10) <= 0 ) {
x += maxspeed * rate;
var newpos = x+'px';
years.css('left',newpos);
} else {
years.css('left','0');
}
}
The code in question is right here at the end^
Is this what you were trying to do?
function moveBackdrop(){
if ( parseInt(years.css("left"), 10) <= 0 && rate < 0 ) {
// Means that the element is already at left: 0 or less,
// and we are trying to move it even more left with rate being negative.
// So keep the element at left: 0
years.css('left','0');
} else {
x += maxspeed * rate;
var newpos = x+'px';
years.css('left',newpos);
}
}
Extra note for future: parseInt uses base 10 by default :) so parseInt("20px") will equal 20
Final Edit: Ah there is an even better way to do it.
function moveBackdrop(){
x += maxspeed * rate;
if( x < 0 ) x = 0; // If left less than 0, fix it at 0
var newpos = x+'px';
years.css('left',newpos);
}
How can I make a repeated scrollBy call smoother like when animating with jQuery's animate scrollTop?
Currently it is jumpy, the page jumps to and from the different scroll positions. How can I make it smoother?
Here is the scrollBy code:
window.scrollBy(0, -10*(scrollCount ? scrollCount<0 ? -1 : 1 : 0)) , 600*x); })(i);
And here is the for loop that contains it:
for(var i = 0; i < Math.abs(scrollCount); i++){
(function(x){
setTimeout(
window.scrollBy(0, -10*(scrollCount ? scrollCount<0 ? -1 : 1 : 0))
, 600*x); })(i);
}
}
Usage
First add this to your page.
scrollByAnimated = function(scrollY, duration){
var startTime = new Date().getTime();
var startY = window.scrollY;
var endY = startY + scrollY;
var currentY = startY;
var directionY = scrollY > 0 ? 'down' : 'up';
var animationComplete;
var count = 0;
var animationId;
if(duration === undefined){
duration = 250;//ms
}
//grab scroll events from the browser
var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel" //FF doesn't recognize mousewheel as of FF3.x
//stop the current animation if its still going on an input from the user
var cancelAnimation = function () {
if(animationId!==undefined){
window.cancelAnimationFrame(animationId)
animationId=undefined;
}
}
if (document.attachEvent) {
//if IE (and Opera depending on user setting)
document.attachEvent("on"+mousewheelevt, cancelAnimation)
} else if (document.addEventListener) {
//WC3 browsers
document.addEventListener(mousewheelevt, cancelAnimation, false)
}
var step = function (a,b,c) {
var now = new Date().getTime();
var completeness = (now - startTime) / duration;
window.scrollTo(0, Math.round(startY + completeness * scrollY));
currentY = window.scrollY;
if(directionY === 'up') {
if (currentY === 0){
animationComplete = true;
}else{
animationComplete = currentY<=endY;
}
}
if(directionY === 'down') {
/*limitY is cross browser, we want the largest of these values*/
var limitY = Math.max( document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight );
if(currentY + window.innerHeight === limitY){
animationComplete = true;
}else{
animationComplete = currentY>=endY;
}
}
if(animationComplete===true){
/*Stop animation*/
return;
}else{
/*repeat animation*/
if(count > 500){
return;
}else{
count++;
animationId = window.requestAnimationFrame(step);
}
}
};
/*start animation*/
step();
};
Then use it;
scrollByAnimated(100, 250);// change in scroll Y, duration in ms
Explanation
Here's a more robust version than your original code suggested you needed. Additional features include stop scrolling at the top and bottom of the page, uses requestAnimationFrame().
It also only supports scrolling up and down because thats all I need at this time. You'd be a cool, cool person if you added left and right to it.
It has only been tested in Chrome, so your milage may vary.
This code leverages requestAnimationFrame(). First scrollByAnimated() sets variables, then runs step() which loops until the duration has been reached.
At each frame it calculates the animation's completeness as a number from 0 to 1. This is the difference between the startTime and now, divided by duration.
This completeness value is then multiplied by the requested scrollY. This gives us our amount to scroll for each frame. Then we add the startY position to achieve a value that we can use window.scrollTo() to set the frame's position, rather than increment the current position.
try to use animate like this
$('html,body').animate({scrollTop: currentoffset},400);
I'm trying to play with mouse events in javascripts and ran into an issue.
I took this example : http://jsfiddle.net/vL5g3/1/ to understand how it works and later have tried to apply it in a transform case.
While I knew the result would mostlikely fail I at least expected that something would happen but nothing is happenning. Isn't is possible to apply css transform with jquery ?
Here is the code :
http://jsfiddle.net/pool4/Bbcp2/1/
var x=0,
y=0,
rate=0,
maxspeed=10;
var cont= $('.container');
$(cont).mousemove(function(e){
var $this = $(this);
var w = $this.width();
rate = -(e.pageX - $(this).offset().left + 1)/w;
});
cont.hover(
function(){
var scroller = setInterval( moveCont, 30 );
$(this).data('scroller', scroller);
},
function(){
var scroller = $(this).data('scroller');
clearInterval( scroller );
}
);
function moveCont(){
x += maxspeed * rate;
var newpos = 'translate('+x+'px, '+y+'px)';
$('.transform').css('-webkit-transform',newpos);
}
add at the end of moveCont
$('.transform').css('-moz-transform',newpos);
for mozilla hope it will work and your fiddle load jquery library.