I just need animate something, i need create few tween for feew difrent object, example bubbles. So i just want animate bubble per bubble, i mean start animate bubble number two when animation bubble numer one was end. I write somethink like that:
var tweens = [];
for(var i =0; i < bubbleTab.length; i++)
{
var tween = new Kinetic.Tween({
node: bubbleTab[i],
x: invisibleBubbles[i].getX(),
y: invisibleBubbles[i].getY(),
easing: Kinetic.Easings.BounceEaseOut,
onFinish: function(){
tweens[i+1].play();
},
duration: 2
});
tweens.push(tween);
}
or i just replace onFinish: function() to playNextTween(i) and write method
function playNextTween(i)
{
tweens[i].play();
}
But still isn't working. I don't know what i can do. I try animate tween in loop but in loop all tween execute in the same time.
Any ideas? I know about GSAP and his TweenTimeline but with KineticJS no one ease from GSAP working
Instead of using
tweens[i+1].play();
Use a variable counter to iterate through your tween array. For example:
var rects = layer.get('Rect');
var rectCount = rects.length;
var tweens = [];
var tweenCounter = 1;
for (var i = 0; i < rectCount; i++) {
var tween = new Kinetic.Tween({
node: rects[i],
duration: 1,
y: 150,
onFinish: function() {
if (tweenCounter !== rectCount) { //Prevent an undefined tween from being played at the end
tweens[tweenCounter].play();
tweenCounter++;
}
}
});
tweens.push(tween);
}
JSFIDDLE
Ok thanks to #projeqht i know how do this with KineticJS but i working on it, and i have better solution with GASP. Cause with GASP i can overlap animation and much more ;) so here is the code:
//Dodawanie animacje kolejnego bombla do timeline
function addAnim(i){
tl.to(bubbleTab[i], 0.5, {kinetic:{scaleX:1, scaleY:1}}, "-=0.45");//-0.45 mean overlap
}
//Dodawanie animacji do timeline
for(var i = 0; i < bubbleTab.length; i++)
{
layer.add(bubbleTab[i])
addAnim(i);
}
tl.play()
It's simple doesn't it? But you must remeber to add kineticJS plugin :D i fo
Related
This will be a "strange" question, because my code works. I just want to check if it can be tweaked because I dont have programming experience.
I wrote a script that gets a stream of kinect joints and plots them on a three js scene on an coordinates system with a webgl renderer.
At first I create a set of spheres, based on Stemkoski's examples and then add the event listener for the json skeleton that arrives in the update function, so I can update the spheres coordinates and have it moving.
The only problem that this creates is that now I cannot rotate the coordinates system with my mouse (while I could when I was testing it with static spheres or with pulsing spheres, as in Stemkoski's example).
So the first question is how can I correct this problem.
The second, more complex question is this : Is this a correct practice? I may not be a developer but I have learned that when my gut says this is awkward or bad practice, it probably is.. Any help and suggestions, appreciated.
Oh, and I have implemented this for only one skeleton in the scene. I will try to make it for more skeletons but I ll wait for your input here in case this all could be simpler and better written.
Here's the relevant code, the initialization of the sphere/joints and the update function:
WholeSkeleton = new THREE.Object3D();
particleAttributes = { startSize: [], startPosition: [] };
var totalParticles = 20; //=num.skeleton.joints //add later variable number
var radiusRange = 50;
for (var i = 0; i < totalParticles; i++) { // INITIALIZE THE SKELETON JOINTS POSITION
var sphereMaterial = new THREE.MeshLambertMaterial({ color: 'rgb(255,0,0)' });
var jointSphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
//initialize positions
jointSphere.position.set(0, 0, 0);
WholeSkeleton.add(jointSphere);
// add variable qualities to arrays, if they need to be accessed later
particleAttributes.startPosition.push(jointSphere.position.clone());
}
scene.add(WholeSkeleton);
}
function animate() {
requestAnimationFrame(animate);
render();
update();
}
function update() {
document.addEventListener("skeletonEvent", function (e) {
jsonObject = e.detail.SkeletonSourceData;
// for (var i = 0; i < jsonObject.Skeletons.length; i++) {
for (var j = 0; j < jsonObject.Skeletons[0].Joints.length; j++) { //only for skeleton 0.
var incoming=jsonObject.Skeletons[0].Joints[j];
var joint = WholeSkeleton.children[j];
joint.position.x = (particleAttributes.startPosition[j].x + incoming.Position.X)*30;
joint.position.y = (particleAttributes.startPosition[j].y + incoming.Position.Y)*30;
joint.position.z = (particleAttributes.startPosition[j].z + incoming.Position.Z)*10;
}
// }
});
}
--
I'm trying to animate between two complex paths using Paper.js and Tween.js. I've gotten pretty close, I can move all of the points in the path to the correct final positions, but I'm having problems with the handleIn and handleOut for each segment. It doesn't seem to be updating them.
Here's my code: http://codepen.io/anon/pen/rVBaZV?editors=101
var endPathData = 'M740,342.9c-32,...etc...';
var endPath = new Path(endPathData);
endPath.fillColor = '#4CC7A4';
beginPathData = 'M762.8,262.8c-48,...etc...';
var beginPath = new Path(beginPathData);
beginPath.fillColor = '#FFC1D1';
var numberOfSegments = beginPath.segments.length;
for (var i = 0; i < numberOfSegments; i++) {
var tween = new TWEEN.Tween(beginPath.segments[i].point)
.to({
x: endPath.segments[i].point.x,
y: endPath.segments[i].point.y
}, 3000)
.easing(TWEEN.Easing.Linear.None)
.start();
}
view.draw();
view.onFrame = function (event) {
TWEEN.update();
};
I'd like the pink path to end up exactly like the green one, but now I'm stuck. Is there anyway to achieve this?
You need to tween the handles too.
Each segment has two handles: segment.handleIn and segment.handleOut
in your example code you tween the segment.point (the segments position) resulting in the right location of the segments.
I don't know your Tween library, so it is up to you to implement it.
But It looks like you can add to more new tween one for the
beginPath.segments[i].handleIn
and one for the
beginPath.segments[i].handleOut
You can easily check that your code is right by letting paperjs smooth your path and taking care of the handles. By updating the onFrame function like this:
view.onFrame = function (event) {
TWEEN.update();
beginPath.smooth();
endPath.smooth();
};
and this results in the same shaped path.
I have a very simple animation with svg.js that I would like to run on a loop as long as the page is open. I haven't been able to find any thing while looking through either the github, documentation, or stack overflow pages. A working version of the animation without looping can be found here. The important js is:
//create the svg element and the array of circles
var draw = SVG('canvas').size(300, 50);
var circ = [];
for (var i = 0; i < 5; i++) {
//draw the circles
circ[i] = draw.circle(12.5).attr({
fill: '#fff'
}).cx(i * 37.5 + 12.5).cy(20);
//first fade the circles out, then fade them back in with a callback
circ[i].animate(1000, '<>', 1000 + 100 * i).attr({
opacity: 0
}).after(function () {
this.animate(1000, '<>', 250).attr({
opacity: 1
});
});
}
I know this would be pretty easy to do without a js library, but I'm looking at this as just a first step into using svg.js. Later I plan on using it for much more robust animations. Thanks for any advice or pointers.
From version 0.38 of svg.js on the loop() method is built in:
https://github.com/wout/svg.js#loop
I'm also planning on creating a reverse() method in one of the upcoming releases. Right now the loop() method restarts the animation from the beginning.
I'm not sure if its possible just with svg.js attributes, as its not clear from svg.js if its creating typical svg animation elements or not. Whatever, it could be done with a loop though. So...
function anim( obj,i ) {
obj.animate(1000, '<>', 1000 + 100 * i).attr({
opacity: 0
}).after(function () {
obj.animate(1000, '<>', 250).attr({
opacity: 1
});
});
};
function startAnims() {
for( var i = 0; i< 5; i++ ) {
anim( circ[i],i );
}
setTimeout( startAnims, 5000 ); // Or possibly setInterval may be better
};
jsfiddle here http://jsfiddle.net/8bMBZ/7/ As its not clear if its adding elements each time behind the scenes (you may want to store the animation and just start that if so). There are other libs that tie in differently to SVG if you need like Raphael, snap, d3, Pablo.js that you could try as alternatives if you need to look at animation from a slightly different way.
I used after to call a function that start the animation recursively. This way I was able to achieve both infinite looping and reversing. Of course you can count to avoid infinite looping but the general idea is as follows:
//custom animation function whose context is the element animated
function myCustomAnimation(pos, morph, from, to) {
var currentVal = morph(from, to); //do morphing and your custom math
this.attr({ 'some prop': currentVal });
}
var animationStart = 0; //just extra values for my custom animation function
var animationEnd = 1; //animation values start at 0 and ends at 1
line.attr({ 'stroke-width': 2, stroke: 'red' });
animateMeRepeatedly.apply(line);
function animateMeRepeatedly()
{
this.animate(1500)
.during(function (pos, morph) {
myCustomAnimation.apply(this, [pos, morph, animationStart, animationEnd]);
})
.after(function () {
this.animate(1500).during(function (pos, morph) {
myCustomAnimation.apply(this, [pos, morph, animationEnd, animationStart]);
}).after(animateMeRepeatedly);
});
}
I've got the following JS code:
// utility function to convert r,g,b to html color
function RGB2HTML(red, green, blue) {
var decColor =0x1000000+ blue + 0x100 * green + 0x10000 *red ;
return '#'+decColor.toString(16).substr(1);
}
// recursive utility function to animate color
// elNames an array of Ids (these are mainly TDs)
// curCnt is current animation step
// totSteps is total steps
function pulseBGMany(elNames, curCnt, totSteps) {
for(var i=0; i < elNames.length; ++i) {
var curEl = document.getElementById(elNames[i]);
var curColor = RGB2HTML(255, 255*(curCnt/totSteps), 255*(curCnt/totSteps));
curEl.style.backgroundColor = curColor;
}
if(curCnt < totSteps) {
setTimeout( function(){ pulseBGMany(elNames, curCnt+1, totSteps); }, 40);
}
}
// eventually in another piece of code, it all gets triggered
...
// schedule ui update here!
// use a closure
(function(names){ setTimeout( function(){ pulseBGMany(names, 0, 25); }, 40)})(diffRes);
...
The code above works, but unfortunately the animation is very chopped and I'm not able to see a smooth gradient from red to white; it seems like all major browsers are losing frames (tested on Firefox and Chromium on Ubuntu).
The array of TDs varies from 1 to even 80 elements, but the effect is always the same.
What am I doing wrong?
As requested, JSFiddle link: http://jsfiddle.net/PsvCP/2/ (You have to set No wrap in body)
Thanks,
Ema
Try doubling the amount of steps, 25fps is somewhat choppy.
Doubling the steps should put you at 50fps which should be fine.
Also make the elmntlist a array of dom elements and not a array of element id's,
Dom lookups are really slow and probaply causing most of your problems.
Think I've gotten around it. Apparently the setTimeout API is particularly slow in both Chrom(ium) and Firefox. Scheduling all the gradient function calls in advance is much more efficient for current browsers and does the trick:
// non-recursive utility function to animate color
function pulseBGMany(elNames, curCnt, totSteps) {
var curColor = RGB2HTML(255, 255*(curCnt/totSteps), 255*(curCnt/totSteps));
for(var i=0; i < elNames.length; ++i) {
elNames[i].style.backgroundColor = curColor;
}
}
...
// schedule ui update here!
// use a closure
var numFade = 15;
for(var i=0; i < numFade; ++i) {
(function(names, iter, tot){ setTimeout( function(){ pulseBGMany(names, iter+1, numFade); }, 50*iter)})(diffRes, i, numFade);
}
...
and as expected this works a lot faster.
I've recently switched to EaselJs and would like to animate the color of a circle.
The code I've got so far is this:
var shape = new createjs.Shape();
shape.graphics.beginFill(createjs.Graphics.getRGB(255, 0, 0));
shape.graphics.drawCircle(0, 0, 10);
stage.addChild(shape);
var tween = createjs.Tween.get(shape, { loop: true }).
to({color:"#00FF00" }, 1000);
but that doesn't work. What is the right property to animate?
I don't think it's possible to animate the color of a shape like that, afterall the drawing of your shape could include many different colors, how should the Tween know which of those colors to modify?
There are two ways that I can think of right know:
Method 1) Use a createjs.ColorFilter, apply it to your shape and then tween the properties of your filter:
var shape = new createjs.Shape();
//making the shape shape white, so we can work with the multiplyers of the filter
shape.graphics.beginFill(createjs.Graphics.getRGB(255, 255, 255));
shape.graphics.drawCircle(0, 0, 10);
stage.addChild(shape);
var filter = new createjs.ColorFilter(1,0,0,1); //green&blue = 0, only red and alpha stay
shape.filters = [filter];
var tween = createjs.Tween.get(filter, { loop: true }).
to({redMultiplier:0, greenMultiplier:1 }, 1000);
I did not test this, so...let me know it this works. Also note, that filters are only applied/updated when calling cache() or updateCache() on your shape, so you will have to add that to your tick-function.
Method 2) Or you just redraw the shape every frame...but 1) is probably easier.
I was just trying to do the same thing. My solution was to tween custom properties on the shape object and then call an update method on the tween 'change' event. hope it this helps, I'm really new to createjs but so far I really like it!
var s = new createjs.Shape();
s.redOffset = 157;
s.blueOffset = 217;
s.greenOffset = 229;
s.updateColor = function()
{
var color = createjs.Graphics.getRGB(
parseInt(this.redOffset),
parseInt(this.greenOffset),
parseInt(this.blueOffset),
1);
this.graphics.beginFill( color ).drawRect(0, 0, 300, 300);
}
createjs.Tween.get(this.background).to({
redOffset : 255,
greenOffset : 255,
blueOffset : 255
}, 3000).addEventListener('change', function()
{
s.updateColor ();
});
Non filter version.
var colorObj = { r:255, g:0, b:0 };
var shape = new createjs.Shape();
var command = shape.graphics.beginFill(createjs.Graphics.getRGB(colorObj.r, colorObj.g, colorObj.b)).command;
shape.graphics.drawCircle(60, 60, 10);
stage.addChild(shape);
var tween = createjs.Tween.get(colorObj, { loop: true }).to({ r:255, g:255, b:255 }, 1000);
tween.addEventListener( "change", function( event ) {
command.style = createjs.Graphics.getRGB(Math.floor(colorObj.r), Math.floor(colorObj.g), Math.floor(colorObj.b));
});
beginFill(...).command object is able to update.
fiddle
https://jsfiddle.net/MasatoMakino/uzLu19xw/
I just read another option for animating colors here: http://community.createjs.com/discussions/easeljs/4637-graphics-colour-animation
It makes use of the createjs inject-method. I copied the relevant code from the provided code-example with a little bit of explanation fo my own.
According to the docs:
inject ( callback, data ):
Provides a method for injecting arbitrary Context2D (aka Canvas) API calls into a Graphics queue. The specified callback function will be called in sequence with other drawing instructions (...)
With this method you can for example change the native context2d fillstyle so we can change the fill color that easeljs uses to draw on the canvas.
Here we tell createjs about our own setColor function (defined below), this function will thus get automatically executed before every redraw:
var shape = new createjs.Shape();
shape.graphics.beginFill(createjs.Graphics.getRGB(255, 0, 0));
shape.graphics.inject(setColor, data)
shape.graphics.drawCircle(0, 0, 10);
stage.addChild(shape);
The definition of the setColor-function which calls the canvas native fillStyle method:
function setColor(o) {
// sets the context2D's fillStyle to the current value of data.fill:
this.fillStyle = o.fill; // "this" will resolve to the canvas's Context2D.
}
And the tick-function which changes the value of the fill:
function tick(evt) {
count = (count+3)%360;
// update the value of the data object:
data.fill = createjs.Graphics.getHSL(count, 100, 50);
// redraw the stage:
stage.update();
}
Modifying fill Instructions will do the trick of changing the color. This might help in doing the animation.
I dont know the impacts of this, but this works very fine for me.
Try this,
var circle = new createjs.Shape();
circle.graphics.f('#ffffff').s('#000000').ss(0.7).arc((30 * j),50,10, 0, Math.PI * 2, 1);
circle.number = j;
circle.addEventListener('click', function(e) {
var fillStyle = e.target.graphics._fillInstructions[0].params;
var currentFillStyle=fillStyle[1]+"";
for (var i = 0; i < circles.length; i++) {
var resetFillStyle = circles[i].graphics._fillInstructions[0].params;
resetFillStyle[1] = "#ffffff";
}
if (currentFillStyle == "#00B4EA") {
fillStyle[1] = "#FFFFFF";
} else {
fillStyle[1] = "#00B4EA";
}
stage.update();
})
Hope this helps!