• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Accessing movieClip.children array Animate CC Canvas

Community Beginner ,
May 19, 2018 May 19, 2018

Copy link to clipboard

Copied

Hello,

I’m trying to make a reusable widget for our design team, and instead of the user having to put this.movieClipInstances in a array inside my logic, I’d like to sort through the children of my container movieClip using Easlejs myContainer.children and storing them dynamically. If I console.log myContainer.children, I get an array with all the children in the movie clip - Great! But if I try to get the length or try to get an index of container.children[0] it returns undefined.  I am so confused as to why this shows up but I’m unable to access it?

On the stage I have a movieClip instance myContainer.

In myContainer I have three movie clip instances test_01, test_02, test_03.

(Inside my container movieClip)

var c = this;

var arrChildren = c.children;

console.log(arrChildren); //returns array

console.log(arrChildren.length); //returns 0

console.log(arrChildren[0]); //returns undefined

If I console.log arrChildren, I get:

Array(3)

0: lib.Symbol1{objects properties}

1: lib.Symbol1{objects properties}

2: lib.Symbol1{objects properties}

length:3

__proto__:Array(0)

Does anyone know why I can’t loop through this array or access even it’s length?

Any help from the community would be awesome. Thank you in advance!

Views

6.7K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

LEGEND , Jun 12, 2018 Jun 12, 2018

I'd just like to add some more information to the above post. While the setTimeout approach does work for safely executing initialization code in the same frame, it has the disadvantage that it executes after rendering. So any visual properties you've changed won't show up until the next stage update. However, it turns out the CreateJS API provides an even better approach. You can do this instead:

stage.on("drawstart", myInitFunction, this, true);

Every time the stage is updated, it fires two even

...

Votes

Translate

Translate
Community Expert ,
May 19, 2018 May 19, 2018

Copy link to clipboard

Copied

Hi.

I changed the size of your text because it was too small.

About your question, it seems that in HTML5 (Canvas) documents, Movie Clips on stage are always accessible, you can console.log them, and so on, but their internal contents/timeline no. Not always.

Run a test:

Extend the layer with the content until the 2nd frame and also put the code in the second frame and see if you get the result you're expecting.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
May 19, 2018 May 19, 2018

Copy link to clipboard

Copied

You are awesome, that worked. I've been beating my head on my desk for a day so I thank you for your response 

I changed nothing but extended the script to frame 2 (and added a stop of course) and I am able to access the children array as expected.

Many thanks!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
May 19, 2018 May 19, 2018

Copy link to clipboard

Copied

This is wonderful!

You're welcome!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
May 19, 2018 May 19, 2018

Copy link to clipboard

Copied

If you want to keep your widget more code-driven, you don't have to add another timeline frame. To wait the duration of one frame using code, do this:

createjs.Ticker.on("tick", myInitFunction, this, true);

function myInitFunction() {

    // your initialization code...

}

However, you don't even really need to wait an entire frame to make things work right. The problem you were experiencing happens because of execution order. CreateJS calls timeline code first, then child initialization code. If you could somehow shuffle your code to execute after all the child initialization, but before the next frame begins, it would work fine. And huzzah, you can!

setTimeout(myInitFunction.bind(this), 0);

function myInitFunction() {

    // your initialization code...

}

Using setTimeout() with a delay of 0 basically yields execution to whatever else the browser has to do (in this case running the rest of the setup code and rendering the current frame), and schedules the function you give it to execute as soon as possible.

javascript - Why is setTimeout(fn, 0) sometimes useful? - Stack Overflow

javascript - What is setTimeout doing when set to 0 milliseconds? - Stack Overflow

If you stick console.log(this.currentFrame); in your init code, you'll see that the first variant executes on frame 1, but the second variant executes while still on frame 0. So it's probably the better option for getting your widget fully operational as quickly as possible.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

I'd just like to add some more information to the above post. While the setTimeout approach does work for safely executing initialization code in the same frame, it has the disadvantage that it executes after rendering. So any visual properties you've changed won't show up until the next stage update. However, it turns out the CreateJS API provides an even better approach. You can do this instead:

stage.on("drawstart", myInitFunction, this, true);

Every time the stage is updated, it fires two events-- "drawstart" before it starts drawing, and "drawend" when it's done. Hooking an event listener to "drawstart" allows executing setup code with fully initialized clips, but before anything is actually drawn for the current frame/tick. For example you can do this.my.deeply.nested.clip.stop(); in the event handler and it will work, without having to wait a frame.

The reason to use on instead of addEventListener is because of the extra functionality on provides. The third argument specifies the scope that the event handler executes in (so you don't have to mess with bind), and the fourth argument specifies that the listener only executes once.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

That's useful to know, thanks. Do you know where a tick listener falls in time? Like, does a tick listener function extend the current frame duration, in the way that exitframe would do in AS3 or Lingo? Even if tick is handled before draw starts, is there any drawback (pardon the pun) to using the drawstart approach instead of a tick listener?

By the way, one worry is that drawstart would happen when everything is ready to draw. If you then change the state of something, will the new state be drawn, or the state before the change?

I'll be trying it out anyway!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Jun 13, 2018 Jun 13, 2018

Copy link to clipboard

Copied

I just wanted to complement you for mentioning Lingo . And that this is one of the best flash posts in years. I am coming back to the IDE after years of frustration with React and everything else post 2010. This is gold.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 14, 2018 Jun 14, 2018

Copy link to clipboard

Copied

Before I was well known for working in Flash Pro, I was famous for working in Director.. Quite a few Director engineers went on to work on Flash Pro, which is why, for example, Flash 8 gained some of the imaging code that was already in Director. Another thing that was added to ActionScript was exitframe.

For a long time Director didn't have enterframe, and so it did suffer from the problem of complex code causing the frame to last longer than it should. I guess exitframe is useful for jumping to another part of the timeline, knowing that the current frame has been shown for long enough. But for getting lengthy code to run, enterfame is good in both tools, because it runs while the current frame is being displayed.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

Forget most of what I just said. It looks like the drawstart approach is a one time thing, not every frame. Maybe it's also when you change frames? But staying on one frame and using drawstart instead of tick, stops anything you were animating with code.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

No, drawstart executes once per tick, regardless of whether the playhead is advancing. This will rapidly fill up the console:

this.stop();

stage.addEventListener("drawstart", function(){console.log("hello")});

Regarding listenening for a tick event, as I noted in my older post, that delays code execution until the next frame (or frame render).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

Could I be using the 'this' or 'true' wrongly? Here you can see my normal line and the replacement line, and with the normal way I can flick some movieclips and over time they come to a halt. With drawstart they stop moving as soon as I release the mouse button:

//stage.on("drawstart", inertia, this, true);
createjs.Ticker.addEventListener("tick", inertia);

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

Remember, passing true as the fourth argument says to only execute the listener once. That makes it useful for initialization code.

The distinction between listening for tick vs drawstart appears to be... subtle. If you stick this in the first frame of a multi-frame timeline:

createjs.Ticker.on("tick", function(){console.log("Tick:"+this.currentFrame)}, this);

stage.on("drawstart", function(){console.log("Drawstart:"+this.currentFrame)}, this);

You get:

Drawstart:0

Drawstart:1

Tick:1

Drawstart:2

Tick:2

Drawstart:3

Tick:3

etc...

So drawstart appears to be guaranteed to fire within the same frame the listener is added.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Mar 04, 2020 Mar 04, 2020

Copy link to clipboard

Copied

Adding some new info to this old thread. I recently found it necessary to confirm the exact order of event execution in Canvas documents, and this is what I found.

 

Animate HTML5 Canvas Event Order

(CreateJS 2015 and 1.0.0)

  1. Frame incremented
  2. Frame code executes (in CJS2015 this is interleaved with object updating)
  3. Stage “drawstart” event fires
  4. Stage rendered
  5. Stage “drawend” event fires
  6. Ticker “tick” event fires
  7. setTimeout 0 code executes

 

That last item refers to setTimeout code scheduled with a delay of zero, as described elsewhere in this thread.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Participant ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

Interesting post !

Colin, Clay, Joao, have you looked deeply into the animate JS final output file?

From a glance, the load order/queuing of code within the final animate may be influencing this ?

The lib is processes from the get go, so you can at any time call anything from the library directly.

Then, the rest of the content, as animate uses a timeline approach, is loaded as separate functions as dictated by your placement in the timeline on your stage.

Adding to that, if you have 1 frame with code, and a movie clip, it looks like the timeline functions are processed first, then the stage items. Layer order with regards to the code seems to be ignored, its always loaded first, even if the code layer is at the bottom.

Which falls in line with the recommend" placing code on the second frame, not the first" to ensure all the visual elements have been loaded that many people here have said ?

But, not sure if this is the case, haven't had time to look deeply into it.

Regards,

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 13, 2018 Jun 13, 2018

Copy link to clipboard

Copied

My usual approach is to have the symbols I want to talk to be on a given frame, and then have the code that talks to them be on the next frame. Then I'm sure they are around. Clay's drawstart idea is a away to do that on the same frame.

My other way of working is to put the code needed to set up a symbol in the first frame of that symbol. This is sometimes the only realistic way to do some things. For example, I have animations where the animated character needs to be customized on the fly, based on selections the user had made previously. Like, they had chosen a certain head type, different shirts, hat, eyewear, and so on. In each of those I might have something like (this would be the hat symbol):

this.gotoAndStop(window.hatnumber);

Previously window.hatnumber has been set to be the variation of the hat that the user wanted. In the hat symbol would be as many frames as there are hats, and when the user chose a hat it would have been (for JavaScript), 0-n (n being one less than the number of hats).

The good thing about this approach is both that the timeline of the symbol does exist at the time that I this.gotoAndStop(window.hatnumber);, but more importantly it doesn't matter how deep in the hierarchy the symbol is. If I did the same thing from the main timeline I might have something like:

this.character1.head.hat.gotoAndStop(this.hatnumber);

That's fine if the character is at the main timeline, but what if I put it into an animated scene, that is inside another holder symbol. The depth to the hat could get to be:

this.scene.room1.character1.head.hat.gotoAndStop(this.hatnumber);

It's not worth the hassle!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

All of this information is really useful. I've unchecked my answer as the correct and marked Clay's.

And I think it would be really useful if someone from the CreateJS team could stop by once in awhile here in the forums to give us insight about the application of these libraries inside of Animate CC.

I know there is the official documentation but in my experience and seeing the doubts from the users that show up here, I feel that there are many details that could be clarified.

Or the Animate Team could provide a online doc for this integration.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

I found this page:

https://createjs.com/docs/easeljs/classes/Stage.html#event_drawstart

and now realize that for my application, drawend is more useful. drawstart will solve the problem of talking to things and knowing that they are initialize, and what you do will show up even in the first redraw. But I was interested in something equivalent to enterframe.

The good thing about enterframe is that you are doing your time consuming things after the frame is drawn, and you have 1/framerate of a second of time to finish doing those things. exitframe will always extend the duration of the current frame, to be 1/framerate of a second, plus how long it takes for your code to run. Similarly, timerevents could happen at any time, and will very often extend the length of the current frame.

So, if I'm right (and I'll try to test it), using drawend to trigger when your time consuming things will happen could improve performance.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

I suspect using setTimeout with a delay of 0 would do what you want, since that will defer execution of your callback until CreateJS is done and waiting for the next tick.

Hmm... although, scheduling that to execute on every frame could be tricky. Drawend probably would be easier.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 12, 2018 Jun 12, 2018

Copy link to clipboard

Copied

I tried it anyway. All sorts of test of the other three ways of working ended up being much the same time to do a lot of complex tasks. But then I changed to looking at how far a complicated animation had advanced in the same time. With tick, drawstart, and drawend, the animation had advanced about 12 frames during the test. With setTimeout it advanced 50 frames.

My conclusion is that behind the scenes CreateJS is doing a lot to keep regular timing, no matter what technique you're doing, and setTimeout is a way to defeat that.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Jun 14, 2018 Jun 14, 2018

Copy link to clipboard

Copied

https://forums.adobe.com/people/Colin+Holgate  wrote

I tried it anyway. All sorts of test of the other three ways of working ended up being much the same time to do a lot of complex tasks. But then I changed to looking at how far a complicated animation had advanced in the same time. With tick, drawstart, and drawend, the animation had advanced about 12 frames during the test. With setTimeout it advanced 50 frames.

If I'm understanding the experiment you're describing correctly, this result makes perfect sense. Tick, drawstart, and drawend events will never fire any faster than the CreateJS frame rate. setTimeout with an interval of 0, on the other hand, will execute its callback as frequently as possible, continuously pushing itself onto the browser event queue. Probably not a great idea for a continuous animation, since this could easily blow up CPU utilization and yield an uneven frame rate.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Jun 21, 2019 Jun 21, 2019

Copy link to clipboard

Copied

Hate to be that guy that revives a year-old thread, but I found it extremely helpful.

Special thanks to everyone that chimed in.

I've been really excited about teaching beginners JavaScript using Animate CC but every time I try to get into it i run into these "hacks"

I just can't fathom how in 2019, we can't write code on the first frame that simply does

my_mc.x = 300; //works great.

my_mc.gotoAndStop(2); // fails

but now I have to write all this:

stage.on("drawstart", myInit, this, true);

 

function myInit() {

  this.my_mc.gotoAndStop(2);

  this.my_mc.x = 300

}

Perhaps I'm misunderstanding something, but is there any reason why Frame 1 code on the main timeline just wouldn't naturally wait for the first "drawstart" to fire by default? Shouldn't this be handled behind the scene when we export?

does that seem like a reasonable request?

I get warned 10,000 times when I export that EaselJS frame numbers start at 0... but nothing about something as simple as telling a movieclip to go to another frame isn't allowed. lol

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Engaged ,
Feb 04, 2020 Feb 04, 2020

Copy link to clipboard

Copied

Hey folks, good news. I was just using Animate 20.0.1 and you no longer need to wait a frame or do ANY tricks to access children of a movie clip on frame 1. One of my biggest problems with Animate / HTML5 is now gone!

 

let letters = this.words.children;

console.log(letters); // IT WORKS!

gsap.timeline({repeat:9})
.from(letters, {y:100, alpha:0, stagger:0.1, scaleX:0.2, ease:"back"})
.to(letters, {y:-50, alpha:0, duration:0.25, stagger:-0.05}, ">0.5");

 

Anyone know is this something the createJS folks fixed or the Animate team? 

Didn't see any mention of it in the release notes.


Either way, I'm so happy!

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
LEGEND ,
Feb 04, 2020 Feb 04, 2020

Copy link to clipboard

Copied

That should be "var", not "let". let isn't implemented correctly in IE11, so should just be avoided altogether.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Feb 05, 2020 Feb 05, 2020

Copy link to clipboard

Copied

Great thread, I have had good luck with drawstart, tick, & added (based on your classes link), with changing my dynamic button labels onLoad.

 

I still cannot get my buttons (movieClips) to simply gotoAndStop on "rollover" or "mouseover" using either frame numbers or label...any help?

 

 

this.btn01.addEventListener("rollover", fl_MouseOverHandler.bind(this));
function fl_MouseOverHandler(e) {
     //simply plays timeline and loops back to frame 1, even tho 'this.stop()'
     e.currentTarget.gotoAndPlay("over"); 

     //e.currentTarget.gotoAndStop("over"); //does nothing
     //e.currentTarget.gotoAndStop(0); //does nothing
     //e.currentTarget.gotoAndStop(1); //does nothing
}

 

 

Each buttonMC has unque label created from MC symbol and listeners appear to be applied correctly. Each fire alerts and individual labels applied....ANY IDEAS?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines