jQuery animate not moving to the correct location - javascript

I've run into a mysterious problem. I'm using jQuery's animate function and the object I'm animating is not moving to the 'left' coordinate I provide; rather the left coordinate is always 0. However, the 'top' coordinate does move as expected. I had this working fine at one point and I rearranged some things around and it has stopped.
var new_x,
new_y,
player_tranistion_holder;
new_x = bg_app.boardModel[id_num].x+'px';
new_y = (bg_app.boardModel[id_num].chips.length) * bg_app.game_utils.parse_css_dimension(selected_chip.chip.css('height'));
console.log(new_x) //outputs 300px for example - the expected value;
selected_chip.chip.animate({'left': new_x, 'top': new_y }, 500, 'easeInOutQuad', function () {
console.log(selected_chip.chip.css('left'); //output is 0
});
Any idea what could cause this to screw up? The stuff I changed around it was merely in how the function came to be called, nothing in the function itself. Do I have some syntax error that I'm missing?
I've put the broken site here:
http://www.warunicorn.com/bg_show_busted/
here is an example with it working:
http://www.warunicorn.com/bg_show/
Any advice would be appreciated.

I found the problem. When using the animate function if the new value passed in is the same as the current value of the object jQuery gets confused and sets the value to 0. I haven't done extensive testing on this and so there may be exceptions where it does work, but in this case, that was the problem.

Related

Incorrect value returned by d3.mouse offset

For some reason d3.mouse(this) is returning an incorrect value. The value it returns seems to be off by around 10px. More interestingly the values offset increases as the mouse is clicked further along the scale.
Has anyone seen any problems like this before? Any ideas what could interfere with the returned value?
My browser is set to 100% zoom.
This is really the only code i can paste.
// get mouse position and use invert to get scale value for X
layers.on('mousedown', e => {
cursorX = xLayers.invert(d3.mouse(this)[0])
DrawCursor()
})
Whatever the language you are using ( I guess coffeescript). I think it is giving you a different "this" inside the mousedown event.

Getting the position of an element being translated

I'm trying to get the position of a div being translated using CSS3 inside another div with a overflow: hidden property.
Here's a jsFiddle that demonstrates it: https://jsfiddle.net/meeuz3w9
The top position of the element is not updated when trying to get it with jQuery's position().top.
I have no idea why this is happening, does anyone have a solution?
Updated: This doesn't work on Chrome 44 on OSX, but works on other browsers
After playing with it a while, I guess I have an answer:
This is a performance issue
Chrome uses the resources to make the animation more fluid making the script to get less callbacks called and less positions updated.
While Firefox uses the resources to keep both updated, wich makes the animation not so fluid, but the script gets more updated positions.
In Chrome the profile of the calls is also very irregular (between 2 and 100 calls per position), while in Firefox keeps under 4 calls per position.
In this fiddle I tried to get better performance, using a native calculus in a global variable:
var position = function() {
return this.getBoundingClientRect().top -
this.offsetParent.getBoundingClientRect().top;
};
and avoiding the use of console.log ...
var callback = function(){
var top = position.call(callback.target);
if(benchmark[top] === undefined){
benchmark[top] = 0;
} else {
benchmark[top] += 1;
}
};
then I found this perfomance difference.
How to solve it
You can get more info here about the differences between JavaScript animations and CSS animations:
https://css-tricks.com/myth-busting-css-animations-vs-javascript/
So after this reading, I propose the following solution:
Do it with JavaScript
The animation you describe is as easy as:
$('#bar').animate({
'translate3d': '-2000'
}, {
step: function (now, fx) {
console.log(now);
$(this).css({"transform": "translate3d(0px, " + now + "px, 0px)"});
},
duration: 1000,
easing: 'linear',
queue: false
},
'linear');
this way you will be able to handle the position on javascript on every tick instead of asking it to the CSS.
I hope it helps.

Update 'duration' of .animate function within the 'onChange'?

I'm trying to improve an animation that I've been working on where things move across the screen.
Currently the object moves at a set speed and has no variance.
I'm trying to include two features that will ultimately end up doing the same thing; changing the speed of the animated object.
I'd like the user to be able to change the speed and also for the object to slow down or speed up depending on where it is on the screen.
I'm not sure if I'm looking in the right place as currently I've been unable to update the duration once the animation loop has started. I first thought I could replace the number with a function that would return an int. This works in that the value of 'speed' changes but the animate loop is not updated.
Any help is hugely appreciated, thanks.
Code snippets below.
function moveObj () {
//initially the duration was set here. I understand that will not work as the animation is only
//being called once.
//animation process
obj.animate('top', '+=' + canvas.height, {
duration: speedOfObj(0),
abort: function () {
},//end abort callback
onChange: function () {
//testing only//
speedOfObj(1000);
}
//test function to see what the results would be. speed changes when called within the on change but the animation is not affected.
function speedOfObj(modifier){
var speed = 10000 / (new Number(speedControl.value));
if(modifier == 0){
console.log("speed: "+speed);
return speed;
}else{
speed *= modifier;
console.log("speedBBBB: "+speed);
return speed;
}
}
Once a jQuery animation is off and running, it's pretty much off on its own. If you want to change how it works, you can .stop(true) it and then start up a new animation that starts again from where it is now at your new speed.
It's also possible to implement a custom step function in the animation that might takes some queues for how to work from outside influences that can change during the animation, but I think that would end being much more complicated than just stopping the original animation and starting a new one that moves at the newly desired speed.
Working demo: http://jsfiddle.net/jfriend00/tzxca/

jQuery .animate() loop produces unexpected offset over time

I have the following Javascript code (using jQuery):
floatUpAndDown();
function floatUpAndDown() {
$("#bird").animate({top: '+=30px'}, 1400)
.animate({top: '-=30px'}, 1400, 'swing', floatUpAndDown);
}
#bird is an img tag that is absolutely positioned. Simply by looking at the code above, one should think that the bird would move 30px down, then back up 30px, and then loop forever. That is in fact exactly what happens, except for this: Over time the object happens to find itself closer and closer to the top of the page. When it has reached the top, it still continues to float up and down, but the y offset stops increasing. What do you make of this strange behaviour?
Sounds like a rounding error to me. You can fix it by adding a statement at the start of the function that automatically moves #bird to the correct starting position -- imperceptibly, one would hope.
EDIT: Complete rewrite because most of my previous answer was incorrect.
As per mblase's suggestion, you can use jQuery's offset() function to store the original offset, and then again to reset the element either in the callback of the second animation or at the start of floatUpAndDown().
var bird = $("#bird");
var birdOrgOffset = bird.offset();
function floatUpAndDown() {
bird.offset(birdOrgOffset);
bird.animate({top: '+=30px'}, 1400)
.animate({top: '-=30px'}, 1400, 'swing', floatUpAndDown);
}
floatUpAndDown();
And just a little tip for you (or anyone else). Making calls to $()—as in $("#bird")—is kind of expensive in terms of resources. If you find that you are repeatedly invoking the same selector, it's often better to call it once and then store the result in a var as I have done in the example above. So rather than reselecting #bird every time we restart the animation an reset the offset, we do it once and reuse the result after that. In general, you probably won't notice...but if you're using selectors in a loop then it will definitely start to add up.

raphael question - using animateAlong

I am using raphael to do some SVG animation and cannot seem to get the function animateAlong to work. I continue to get the error "attrs[0] is undefined" referencing line 3450 of the un-compressed raphael code.
Basically, I create a circle with a given center and then want to animate an image around that path. Here is that simple code:
var circle = paper.circle(circleCenterX, circleCenterY, circleRadius);
I then clone an image (since I plan to have a number of these on this path) and place at the edge of the circle:
var wheelClone = wheel.clone();
var wheelRadius = parseInt(wheel8ImageWidth/2);
wheelClone
.translate((circleCenterX + circleRadius)-3, circleCenterY-wheelRadius);
where I init circleCenterX earlier with circleCenterX = circle.attr(cx);
This all works fine with image placed correctly - but it errors on animateAlong.
I have studied as many examples as i can find and have dissected the documentation but cannot get the hang here.
So, I simply try to call the function but have no earthly idea what the documentation is referring to. The documentation animates a dot around a path but refers to two variables - rx and ry which I cannot suss out - both in an init function and then with the callback.
Here is what I have - - where the rx and ry and just made up as I have no idea what they refer to.
var wheelAttr = {
rx: 5,
ry: 3
};
wheelClone.attr(wheelAttr).animateAlong(circle, 2000, true, function() {
wheel.attr({rx: 4, ry: 4});
});
My current jsFiddle is a bit of a mess at the moment and I can clean it up, but I suspect that there is some obvious thing here?
Thanks to all
S
I don't think a circle is actually a valid path (i.e, something you can pass to animateAlong()). I think you need to create a path that is circular. See the following:
svg-animation-along-path-with-raphael
Hopefully, it will help.

Categories

Resources