I've got my sprite sheet animating in vanilla JS by shifting the background-position at a fixed FPS, using requestAnimationFrame and setTimeout to set the framerate.
Ultimately I'd like to animate it with an easing curve, such as QuadInOut, or better still a custom curve. Most of the frameworks I've looked at have their easing built into their tween function, and not for animating a sprite sheet.
Can anyone suggest a JS framework that might help? GSAP or Enchant perhaps? Or alternatively explain the logic behind updating the fps via an easing curve?
Here's my 'linear' animation at the moment:
var theSprite= $('.sprite');
var timesRun = 0;
var shift = 0;
var fps = 20;
var anim = function() {
setTimeout(function() {
shift -= 520;
theSprite.css('background-position', shift +'px 0');
timesRun += 1;
if(timesRun === 19) {
timesRun = 0;
shift = 0;
}
animAgain = requestAnimationFrame(anim);
}, 1000 / fps);
}
anim();
Enchant.js has a few different ways sprite animation. if you look at the enchant.timeline class here http://wise9.github.io/enchant.js/doc/plugins/en/symbols/enchant.Timeline.html it has a few different functions for easing sprites in different ways.
I think you would definitely enjoy KineticJS. It works like a charm and is designed for what you are trying to do.
See: HTML5 Canvas KineticJS Sprite Tutorial
Related
I am trying to get a simple random "rotation" based on the angle property, and would like to achieve the following.
Random Rotation, say "rotate" to 500 degrees
Start with a high speed and when getting nearer to the "rotated" degrees, lower the "rotating" speed so that the stop is not instant.
I put a basic concept of what I am trying to achieve on this link:
https://www.pixiplayground.com/#/edit/yalRPEN~6tg3seIHq5hbI
In the animate function, if I put the let degrees = 2000; as a Math.Random value it screws up the animation as it seems that this animate function is called numerous times?
Also, I tried using the speed property which would start off with a high value and starts to get lower with "rotations", but it seems to do nothing? Also tried using animationSpeed since I am using the angle property to change degrees, but I see no speed difference.
Any feedback would be appreciated.
Thanks
One approach is to change the angle and not the speed. Something like this:
var angleStep = 40;
let rotateSpeed = Math.floor(Math.random() * 300)
function animate() {
bunny.angle += angleStep;
angleStep = angleStep - angleStep/rotateSpeed;
if ((angleStep.toFixed(1) <= 0.0)) {
console.log("stopped rotation")
bunny.angle = bunny.angle;
return bunny.angle;
} else {
requestAnimationFrame(animate);
}
}
I can directly set the position with myScrollview.setPosition(y), or apply a motion manually with myScrollview.setVelocity(delta). However, is there a way to apply a smooth, precise easing transition to the position of a Scrollview? Thanks!
Alternatively you can use the FlexScrollView which uses a physics spring to smoothly pull the scroll-position to the new position. It also has an extended API for setting the scroll position:
https://github.com/IjzerenHein/famous-flex/blob/master/docs/FlexScrollView.md
https://github.com/IjzerenHein/famous-flex/blob/master/docs/ScrollController.md
https://github.com/IjzerenHein/famous-flex/blob/master/tutorials/FlexScrollView.md
https://github.com/IjzerenHein/famous-flex
Here's what I settled on (there's probably a better way to do this):
var self = this; // current view object
var transitionTime = 500; //ms
// How far do we need to move every 16.67 ms (1/60th of a second)?
self.animatedScrollDelta = (self.myScrollview.getPosition() / (transitionTime / 16.6667));
self.animatedScroller = Timer.every(animateScrollerCallback, 1);
function animateScrollerCallback()
{
var pos = self.myScrollview.getPosition() - self.animatedScrollDelta;
self.myScrollview.setPosition(Math.max(0, pos));
if(pos < 0)
Timer.clear(self.animatedScroller);
}
Note: This animates linearly, which was what I needed. I'm sure other easing formulas could be implemented using a TweenTransition.
I am creating a chronometer for which I already have all the code working. Now I'm trying to tie the rotation of a 'notch' to the passage of seconds. I have the following code-block:
var minutesNotchAnimation = new Kinetic.Animation(function(frame) {
var notch = self.minutesNotchLayer.get('#minutesNotchShape')[0];
notch.rotate(rotationAngle);
}, this.minutesNotchLayer);
minutesNotchAnimation.start();
How can I execute the animation once every second? Also how can I apply custom easing to it? And lastly... how do I control the length of the animation? I find the KineticJS documentation to be really lacking in places, also there are not a lot of comprehensive resources out there that explain the Animation class in depth.
Thanks in advance!
P.S. Here's a fiddle of the complete code in case anyone needs to check it out --> http://jsfiddle.net/k4xA8/
You can't set the animation interval because this object is not doing for that. If you want to make something more accurate (and use easing), it's a lot easier to employ a Tween instead.
By the way, you can use the frame.timeDiff property, or the frame.time in order to control the animation...
var minutesNotchCount = 0;
var minutesNotchAnimation = new Kinetic.Animation(function(frame) {
minutesNotchCount += frame.timeDiff;
var notch = self.minutesNotchLayer.get('#minutesNotchShape')[0];
if (minutesNotchCount >= 40) {
notch.rotate(0.25);
minutesNotchCount = 0;
}
}, this.minutesNotchLayer);
minutesNotchAnimation.start();
I'm working on a project that uses SVG with Raphael.js. One component is a group of circles, each of which "wiggles" around randomly - that is, slowly moves along the x and y axes a small amount, and in random directions. Think of it like putting a marble on your palm and shaking your palm around slowly.
Is anyone aware of a Raphael.js plugin or code example that already accomplishes something like this? I'm not terribly particular about the effect - it just needs to be subtle/smooth and continuous.
If I need to create something on my own, do you have any suggestions for how I might go about it? My initial idea is along these lines:
Draw a circle on the canvas.
Start a loop that:
Randomly finds x and y coordinates within some circular boundary anchored on the circle's center point.
Animates the circle from its current location to those coordinates over a random time interval, using in/out easing to smooth the effect.
My concern is that this might look too mechanical - i.e., I assume it will look more like the circle is tracing a star pattern, or having a a seizure, or something like that. Ideally it would curve smoothly through the random points that it generates, but that seems far more complex.
If you can recommend any other code (preferably JavaScript) that I could adapt, that would be great too - e.g., a jQuery plugin or the like. I found one named jquery-wiggle, but that seems to only work along one axis.
Thanks in advance for any advice!
Something like the following could do it:
var paper = Raphael('canvas', 300, 300);
var circle_count = 40;
var wbound = 10; // how far an element can wiggle.
var circleholder = paper.set();
function rdm(from, to){
return Math.floor(Math.random() * (to - from + 1) + from);
}
// add a wiggle method to elements
Raphael.el.wiggle = function() {
var newcx = this.attrs.origCx + rdm(-wbound, wbound);
var newcy = this.attrs.origCy + rdm(-wbound, wbound);
this.animate({cx: newcx, cy: newcy}, 500, '<');
}
// draw our circles
// hackish: setting circle.attrs.origCx
for (var i=0;i<circle_count;i++) {
var cx = rdm(0, 280);
var cy = rdm(0, 280);
var rad = rdm(0, 15);
var circle = paper.circle(cx, cy, rad);
circle.attrs.origCx = cx;
circle.attrs.origCy = cy;
circleholder.push(circle);
}
// loop over all circles and wiggle
function wiggleall() {
for (var i=0;i<circleholder.length;i++) {
circleholder[i].wiggle();
}
}
// call wiggleAll every second
setInterval(function() {wiggleall()}, 1000);
http://jsfiddle.net/UDWW6/1/
Changing the easing, and delays between certain things happening should at least help in making things look a little more natural. Hope that helps.
You can accomplish a similar effect by extending Raphael's default easing formulas:
Raphael.easing_formulas["wiggle"] = function(n) { return Math.random() * 5 };
[shape].animate({transform:"T1,1"}, 500, "wiggle", function(e) {
this.transform("T0,0");
});
Easing functions take a ratio of time elapsed to total time and manipulate it. The returned value is applied to the properties being animated.
This easing function ignores n and returns a random value. You can create any wiggle you like by playing with the return formula.
A callback function is necessary if you want the shape to end up back where it began, since applying a transformation that does not move the shape does not produce an animation. You'll probably have to alter the transformation values.
Hope this is useful!
There is a very good set of easing effects available in Raphael.
Here's a random set of circles that are "given" bounce easing.
Dynamically add animation to objects
The full range of easing effects can be found here. You can play around with them and reference the latest documentation at the same time.
Putting calls in a loop is not the thing to do, though. Use callbacks, which are readily available.
http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
If I move the slider on this page, the blurring is very smooth.
But if I try and automate the animation:
var speed = 1250;
var blur = 100;
var interval = speed/blur;
setInterval(function(){
blur--;
stackBlurImage(image, canvas, blur);
}, interval);
The steps are very obvious and it doesn't even work at high speed.
Could anyone suggest an alternative approach to this?
Pre-render the different blur levels, store them and cycle through them as frames. Its possible that whatever stackBlurImage does just can't be done fast enough to look like an animation.
Edit: I take that back, exactly what you did: http://jsfiddle.net/nwellcome/27QUM/ that looks great to me in Chrome, what browser are you using?
Edit 2: Try the second approach in this fiddle: http://jsfiddle.net/nwellcome/27QUM/4/, rather than decreasing the blur radius by 1 each time, fix the fps at something setInterval can handle and manipulate the amount you decrease the blur radius each frame.
var fps = 30;
var blur = 100;
var blurTime = 0.5; // seconds
var interval = 1000 / fps;
var step = blur/ (fps * blurTime);
var anim = setInterval(function(){
blur-= step;
if (blur < 0) {
clearInterval(anim);
}
stackBlurImage(image, canvas, blur);
}, interval);
Edit 3: just for the fun of it, with the HTML5 file API, you can upload your own image to blur: http://jsfiddle.net/nwellcome/27QUM/12/