.css transform not applying with jquery - javascript

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.

Related

Javascript animation with variable speed based on cursors position

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.

Mousemove animation

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

Clickable song progress bar Soundmanager2

This is my code for the current and loading bar:
whileloading: function() {
$(".loadBar").css('width', ((this.bytesLoaded / this.bytesTotal) * 100) + '%');
},
whileplaying: function() {
$(".progBar").css('width', ((this.position/this.duration) * 100) + '%');
},
How can i change the current audio position when i click on the current time bar?
Thanks in advance for your help
Something like this should do the trick:
var that = this;
$("#ProgressAndLoadBarContainer").click(function(e){
var $this = $(this);
var relX = e.pageX - parseFloat($this.css("left"));
var time = track_duration*(relX / $this.width());
that.setPosition(time);
});
The easiest approach IMHO is to use the offsetX property. Unfortunately while that works in Chrome, it does not in Firefox (see http://www.jacklmoore.com/notes/mouse-position/ for some background on cross-browser issues). The following works for me:
var pBar = document.createElement('progress');
$(pBar).click(function(evt) {
var clickX = evt.offsetX;
if(clickX == undefined){
// welcome to Firefox
var rect = evt.target.getBoundingClientRect();
clickX = evt.clientX - rect.left;
}
var percent = clickX / evt.target.offsetWidth;
console.log("pBar click at " + clickX+", "+percent+"%");
});
You could also use the slider widget provided by jQuery UI.

Jquery thumbnail scroller with buttons

I'm trying to make a jquery thumbnail scroller with buttons that work on mousedown and mouseup events . I can do the scrolling but when i try to make a function out of it to use it again n again , it dont work . Here is my code for the scroller
var $wrapper = $('.my_ul');
var $div = $('.my_div');
var $ul = $('.my_ul');
function scrollRight()
{
var divLeft = $ul.css('marginLeft');
divLeft = Math.abs(parseInt(divLeft)) - 60;
var width = $div.width();
var ulwid = $ul.width();
var ulWidth = $ul.width() - width;
if(divLeft >= ulWidth){stopScrolling();}
else{
// contintually increase scroll position*/
$wrapper.animate({'margin-left' : '-=10'}, 1, scrollRight);}
}
function scrollLeft()
{
var divLeft = $ul.css('marginLeft');
divLeft = parseInt(divLeft);
if(divLeft >= 0){stopScrolling();}
else{
// contintually increase scroll position*/
$wrapper.animate({'margin-left' : '+=10'}, 1, scrollLeft);}
}
function stopScrolling()
{
// stop increasing scroll position
$wrapper.stop();
}
$('.scroll_right').mousedown(scrollRight).mouseup(stopScrolling);
$('.scroll_left').mousedown(scrollLeft).mouseup(stopScrolling);
I need to make a function using parameters but when i try that , it dont work . Moreover , The animation gets slow because of the recursive calls . If anyone have any better solutions , please let me know .
This should work:
function scrollingStuff($right, $left, $wrapper, $div, $ul) {
$right.mousedown(scrollRight).mouseup(stopScrolling);
$left.mousedown(scrollLeft).mouseup(stopScrolling);
... put functions here ...
}
Call it with the result of a jQuery selector for the elements.
scrollingStuff($(".scroll_right"), $(".scroll_left"), ...);
This would move twice as fast:
$wrapper.animate({'margin-left' : '+=20'}, 1, scrollLeft);}
I would use a little delay. This is 1/60 sec:
$wrapper.animate({'margin-left' : '+=10'}, 16, scrollLeft);}
I also think you can move this part out of the function and not call jQuery twice. It doesn't change during the scrolling or even after loading the div and the ul's:
var width = $div.width();
var ulwid = $ul.width();
var ulWidth = ulwid - width;

Moving Div by everyclick without JQuery

I used this jquery to move a div by every click.
$(document).ready(function(){
$('#hero').click(function(){
$(this).animate({
left: '+=50px'
},300);
})
})
I'd like to avoid jquery whenever it is possible to get deeper into pure JS.
Is there anyway to achieve the same effect without using jquery?
I know that this will be more complex, but just trying to learn.
you can use the same technique in javascript:
// get the object refrence
var hero_obj = document.getElementById('hero');
// attach the onclick event
hero_obj.onclick = function(){
this.style.left = ( parseInt(this.style.left, 10) + 50 ) + 'px'
};
However, the effect won't be as smooth as jquery
I've stumbled upon this gem on vanilla-js.com a few weeks ago:
var s = document.getElementById('thing').style;
s.opacity = 1;
(function(){(s.opacity-=.1)<0?s.display="none":setTimeout(arguments.callee,40)})();
I really like the simplicity and the size of the code. Elegant and efficient!
I've created a function that affects the left property of an element of your choice based on the code above:
/* element: DOM element such as document.getElementById('hero')
distance: distance in pixels to move to the left such as 50 or 100 */
function moveBy(element, distance){
var target = isNaN(parseInt(s.left)) ? distance : parseInt(s.left) + distance;
(function(){
s.left = isNaN(parseInt(s.left)) ? '1px' : (parseInt(s.left) + 1).toString() + 'px';
if(parseInt(s.left) <= distance) setTimeout(arguments.callee, 40);
})();
}
You can play around and see what fits to your liking in terms of speed and smoothness. Try it here on a jsfiddle.
/* So you go: */
moveBy(document.getElementById('hero'), 50);
/* Or you can bind it to an event */
document.getElementById('hero').addEventListener('click', function(event){
moveBy(this, 50);
});
What a solution like this would need if you're willing to make it better is to replace the left property by translate. As Paul Irish states on his blog, translate provides way better performance than moving elements around with TRBL (top-left-bottom-right). Some sort of easing functions could be added as well to smooth things out.
Here's a code with animation. This snippet is only for modern browsers, but it is easy to modify to work with older browsers (IEs) too. (Actually only attachment of the event needs to be fixed.)
window.onload = function () {
var timer, k, intervals, kX, kY,
counter = 0,
hero = document.getElementById('hero'),
posX = hero.offsetLeft,
posY = hero.offsetTop,
anim = function (elem, params) {
posX += kX;
posY += kY;
elem.style.left = posX + 'px';
elem.style.top = posY + 'px';
if (counter > intervals) {
clearInterval(timer);
counter = 0;
} else {
counter++;
}
return;
},
move = function (elem, params) {
if (timer) {
clearInterval(timer);
counter = 0;
}
k = Math.atan2(params.left, params.top);
kX = Math.sin(k);
kY = Math.cos(k);
intervals = Math.floor(Math.sqrt(Math.pow(params.left, 2) + Math.pow(params.top, 2)));
timer = setInterval(function () {
anim(elem, params);
return;
}, params.speed);
return;
};
document.getElementById('hero').addEventListener('click', function (e) {
move(e.currentTarget, {left: 50, top: 0, speed: 0});
return;
}, false);
return;
}
As you can see, with this code you can also move elements vertical and adjust speed. To switch direction, just add - to corresponding property. The code is using pixels only as units, but that's easy to modify if needed.
It's also easy to convert this functional code to an object. Also jQuery-like duration can be added by passing property params.duration instead of params.speed and doing some advanced calculations with that and kX, kY.
Working demo at jsFiddle
I needed to create an animation solution with easing a while back without using a framework.
The tricky part for me was coping with interrupting/restarting animations part way through when they are tied to user interactions. I found that you can run into trouble pretty quickly if your animations double-fire.
Here is on github: https://github.com/robCrawford/js-anim
There are a few supporting functions but here's the main animation:
function animate(el, prop, to, pxPerSecond, easing, callback){
/**
* Animate style property
* i.e. animate(div1, "width", 1100, 1000, "out", function(){console.log('div1 anim end')});
*
* #param el DOM element
* #param prop Property to animate
* #param to Destination property value
* #param pxPerSecond Speed of animation in pixels per second
* #param easing (optional) Easing type: "in" or "out"
* #param callback (optional) Function to call when animation is complete
*/
var frameDur = 10,
initPropVal = parseInt(getCurrCss(el, prop)),
distance = Math.abs(to-initPropVal),
easeVal = (easing==="in")?1.5:(easing==="out")?0.5:1, // >1 ease-in, <1 ease-out
elAnimData = getData(el, 'animData');
//Quit if already at 'to' val (still fire callback)
if(initPropVal===to){
if(callback)callback.call();
return;
}
//Init animData for el if first anim
if(!elAnimData){
elAnimData = {};
setData(el, {'animData':elAnimData});
}
//Get data for prop being animated or create entry
var animDataOb = elAnimData[prop];
if(!animDataOb)animDataOb = elAnimData[prop] = {};
//Don't re-initialise an existing animation i.e. same prop/to
if(animDataOb.to === to)return;
animDataOb.to = to; //Store 'to' val
//Clear any exisiting interval
if(animDataOb.intId){
clearInterval(animDataOb.intId);
animDataOb.intId = null;
}
//Create new anim
animDataOb.intId = (function(animDataOb){
var totalSteps = Math.round((distance/pxPerSecond)/(frameDur*.001)),
thisStep = 0;
return setInterval(function(){
var newVal = easeInOut(initPropVal, to, totalSteps, thisStep++, easeVal);
if(!isNaN(newVal))el.style[prop] = newVal + "px"; //Allow 0
if(thisStep > totalSteps)endAnim(animDataOb, callback);
}, frameDur);
})(animDataOb);
}
function endAnim(animDataOb, callback){
//End anim
clearInterval(animDataOb.intId);
animDataOb.intId = animDataOb.to = null;
if(callback)callback.call();
}

Categories