Reputation: 95
Hello Stackoverflow community
As I am trying to build a small game, i came to a problem. Somehow, when i try to fade out multiple shapes, respectivly a group with the shapes in it, some of the shapes will not fade out or browser gets a stack overflow.
So as i tried out several hours to fix the problem i need your help.
Heres the link to a little fiddle i made: http://jsfiddle.net/hnBPT/
As you can see theres a function newFadeShapesOut() which needs the nodes that should be fade out and also the layer of the nodes. It moves the nodes into a group and fades the group out. Somehow and sometimes, one or more shapes will not fade out or there occurs a fatal error.
Function for fadeout:
function newFadeShapesOut(shapes, layer, callback, speed){
if(typeof(speed) == 'undefined'){
speed = 1;
}
var g = new Kinetic.Group();
console.log(layer.getChildren().length);
console.log(shapes.length);
layer.add(g);
shapes.each(function(shape){
shape.moveTo(g);
});
console.log(layer.getChildren().length);
console.log(shapes.length);
var tween = new Kinetic.Tween({
node: g,
opacity: 0,
duration: speed,
onFinish: function(){
if(typeof(callback) != 'undefined'){
callback();
tween.destroy();
}
}
}).play();
}
PS: Google Chrome is recommend, firefox tends to crash.
Thank you for your help.
EDIT: Sorry i forgot about that, you can activate the script by clicking the red square.
Upvotes: 3
Views: 699
Reputation: 95
After several attempts to bend projeqht's function to my way i finally did it! Somehow, the collection shapes just updates itself when adding the group to the layer! If i use an array instead, it works.
Hope it helps someone!
So here my solution which works like a charm.
function fadeShapesOut(shapes, callback, speed){
layer = shapes[0].getLayer();
if(typeof(speed) == 'undefined'){
speed = 1;
}
var g = new Kinetic.Group();
layer.add(g);
for(i in shapes){
shapes[i].moveTo(g);
}
var tween = new Kinetic.Tween({
node: g,
opacity: 0,
duration: speed,
onFinish: function(){
if(typeof(callback) != 'undefined'){
callback();
}
tween.destroy();
}
}).play();
}
If you have further questions, don't mind contacting me.
Upvotes: 2
Reputation: 3160
There's some strange behaviour going on here. Look at my comments as I tried to rewrite your function:
function fadeShapesOut(layer, callback, speed) {
var children = layer.children;
//The layer here already shows some children have moved.
//2 children remain, 1 text and 1 rect.
console.log("LAYER");
console.log(layer);
//Again, children shows that there are only 2 children of layer at this point: Test 2 and Button Rect
console.log('CHILDREN');
console.log(children);
if(typeof(speed) == 'undefined'){
speed = 1;
}
var group = new Kinetic.Group();
layer.add(group);
children.each(function(child) {
console.log("CHILD");
console.log(child); //This spits out Test 1, Test 3 and the newly added Group. (Strange order???
child.moveTo(group);
});
//Since group is already added to the layer, you're all of layer's children to group, including group itself. Which is causing a never ending loop of references to group including itself - causing the stack overflow.
var tween = new Kinetic.Tween({
node: group,
opacity: 0,
duration: speed,
onFinish: function(){
if(typeof(callback) != 'undefined'){
callback();
tween.destroy();
}
}
}).play();
}
What's messing you up is that the group is being considered a child of layer (Even though it hasn't been added yet in the order of function calls, which is strange behaviour to me). So when you loop through the children of layer in the each function, you're trying to move group --> group which screws up the reference in a never ending loop.
I logged a bunch of things in my fiddle, so go ahead and take a look to see some of the strange behaviour I was talking about above.
Anyways, if your callback is going to destroy the layer, what is the point of moving everything to a new group in the function? That Group is messing your code up and I don't see the point of it if you're just going to destroy the layer.
Instead you can achieve the effect you want by just tweening the layer itself:
function fadeLayer(layer, callback, speed) {
var tween = new Kinetic.Tween({
node: layer,
opacity: 0,
duration: 2,
onFinish: function(){
layer.destroy();
tween.destroy();
}
}).play();
}
If you must stick with your original function format, then you can grab children by using names:
newsobj[n] = new Kinetic.Text({
nid: n,
x: 140,
y: ((n == 0) ? 294.5 : 304.5 ),
text: news[n],
fill: 'white',
fontFamily: 'Corbel W01 Regular',
fontSize: 11.26,
name: 'fadeThisAway'
});
button = new Kinetic.Rect({
x: 10,
y: 10,
width: 100,
height: 100,
fill: 'red',
name: 'fadeThisAway'
});
In my example, I used the name fadeThisAway
. And then, using your old function:
function newFadeShapesOut(layer, callback, speed){
var shapes = layer.get('.fadeThisAway');
if(typeof(speed) == 'undefined'){
speed = 1;
}
var g = new Kinetic.Group();
console.log(layer.getChildren().length);
console.log(shapes.length);
layer.add(g);
shapes.each(function(shape){
shape.moveTo(g);
});
console.log(layer.getChildren().length);
console.log(shapes.length);
var tween = new Kinetic.Tween({
node: g,
opacity: 0,
duration: speed,
onFinish: function(){
if(typeof(callback) != 'undefined'){
callback();
tween.destroy();
}
}
}).play();
}
Instead of passing shapes
through the function, just call
var shapes = layer.get('.fadeThisAway');
at the beginning of the function (you're passing layer through the function already anyways) to grab the children that are named fadeThisAway
. (Note: This works because the group is not named fadeThisAway
)
Working example and comments inside: JSFIDDLE
UPDATE
Okay so I made a basic example of the issue with layer.children
And it looks like that's just how the children of layer works. This proves that you definitely have to distinguish between shapes and group, because the group will always be considered a child of layer.
The naming method works to distinguish your shapes between layers by giving all shapes a common name that excludes groups.
Upvotes: 2