Copy link to clipboard
Copied
I have 3 buttons. Once they are all clicked, they go through to the next stage.
I want to know how I can set it up so that when each button is clicked, their 'state' holds to show that it is completed.
Any help greatly appreciated.
[thread approved | repaired ussnorway]
Hi.
Adding to the example of the previous thread, one simple approach is to just remove all listeners from the selected buttons. Like this:
...this.check = function(e)
{
if (!e.target.selected)
{
e.currentTarget.count++;
e.target.selected = true;
e.target.removeAllEventListeners(); // NEW
}
if (e.currentTarget.count == e.currentTarget.children.length)
this.gotoAndStop(1);
};
this.stop();
this.container.count = 0;
this.container.on("click", this.chec
Copy link to clipboard
Copied
Hi.
Adding to the example of the previous thread, one simple approach is to just remove all listeners from the selected buttons. Like this:
this.check = function(e)
{
if (!e.target.selected)
{
e.currentTarget.count++;
e.target.selected = true;
e.target.removeAllEventListeners(); // NEW
}
if (e.currentTarget.count == e.currentTarget.children.length)
this.gotoAndStop(1);
};
this.stop();
this.container.count = 0;
this.container.on("click", this.check, this);
Then the appearance of the toggled state end up being the one you set as the down state.
I hope this helps.
Regards,
JC
Copy link to clipboard
Copied
ah, that would have been a great/easy way to do it.
I ended up changing my buttons to movie clips and then using e.currentTarget.gotoAndPlay('downstate') which seems to work.
I did a lot of debugging/fixing using console.log.
May I ask where you are getting the knowledge of using things like e.target.selected and e.target.removeAllEventListeners()?
Is there some sort of cheatsheet or a website that I don't know about? Last time I checked that doesn't really look like js to me.
Cheers
Copy link to clipboard
Copied
Excellent!
Yeah. I really wanted to suggest using Movie Clips instead of the default Button for this situation because Movie Clips are way easier to handle and way more dynamic.
But I'm glad you already figured it out.
To learn the way things work in HTML5 documents, it's important to learn CreateJS and the way CreateJS is integrated with Animate CC.
- To learn CreateJS, just head over to the offical website:
CreateJS | A suite of JavaScript libraries and tools designed for working with HTML5
- This page in particular is a must: EaselJS Tutorial: Mouse Interaction .
- Also checkout the demos: https://createjs.com/demos/easeljs/spritesheet
- Examples of using exportRoot, this, on, addEventListener, bind, custom reference to the current timeline: Button within Movieclip
You'll find the removeAllEventListeners method there. The selected property is a custom property I added dynamically.
To better understand the integration between ANCC and CreateJS, these are my recommendations:
- Use console.log(obj) and inspect the methods and properties the object has;
- Code Snippets panel;
- Examine the exported HTML and JS files;
- Animate CC templates (File > New > Templates or File > New from Template... (2019 version)).
- Camera API: Camera in Animate CC
- Advanced layers API: Create timeline layers with Animate CC
And there's no official cheatsheet. What I can do is to tell you some useful things:
SPECIAL PROPERTIES
exportRoot // a reference to the main timeline created by Animate CC
lib // reference to the Library
lib.properties // contains useful document properties like framerate
nominalBounds // a property created by Animate CC to display objects containing initial transform properties like width and height
movieclip.timeline.duration // total frames of a timeline
movieclip.timeline.position or movieclip.currentFrame // current frame of a movie clip
VAR DECLARATION
var score = 0; // declares a variable to that frame only
this.score = 0; // creates a property for that object and it's available for the entire timeline
score = 0; // declares a global variable
ADD OBJECTS DYNAMICALLY AT RUNTIME
this.addChild(new lib.LibraryLinkageName());
stage.addChild(new lib.LibraryLinkageName());
exportRoot.addChild(new lib.LibraryLinkageName());
PLACE REGULAR ANIMATE CC OBJECTS (LIKE MOVIE CLIPS AND BUTTONS) OVER COMPONENTS (LIKE VIDEO)
canvas.style.zIndex = "1"; // a value bigger than 0
HOW TO MAKE SURE THE CHILDREN PROPS AND METHODS ARE READY AND HOW TO ACCESS THEM:
var that = this;
that.start = function()
{
// if using advanced layers
that.container = that.container.children[0].children;
// if not using advanced layers
//that.container = that.container.children;
}
stage.on("drawstart", that.start, this, true);
// OR setTimeout(that.start, 0);
PERFORMANCE TIPS:
- Try testing your file with and without exporting the document as texture (Publish Settings > JavaScript/HTML > Image Settings > Export document as texture);
- Consider turning off the advanced layers mode (Ctrl/Cmd + J) if you don't need advanced features like camera or parenting because this mode has some impact on performance;
- Avoid complex containers with lots of children;
- Avoid complex shapes;
- Make sure you're not using color effects/filters;
- Use cache whenever possible;
- Avoid using large bitmaps. This is specially true for mobile devices;
- Try low resolution values for exported bitmaps (Publish Settings > JavaScript/HTML > Image Settings > Resolution);
- Try to balance wisely when an asset should be made of a vector shape or of a bitmap;
- Avoid using too many static text fields because they are exported as raw vector shapes;
- Avoid adding too many listeners;
- Add mouse events to a container and use the event.target property instead of adding a separate mouse event to dozens or hundreds of children;
- If possible set a container.tickChildren to false so the tick will not be propagated to children of a container;
- If using a tick event it may be a good idea to change the Ticker.timingMode and see which one works best for your case;
- Avoid using motion tweens because they are exported as frame by frame animation;
- Avoid having a huge main timeline with lots of tweens;
- Avoing very large shape tween spans.
Oh man, I wish I could remember every single detail right now...
But I hope it can get you started.
Regards,
JC
UPDATED: 08/07/2019
Copy link to clipboard
Copied
Mate!
Had no idea it was a Javascript Library under the hood there.
Your post will help me immensely. I'm finding it hard to find tutorials for html5 canvas use of Animate (I find lots of AS tuts).
As far as I can see - you've provided me with a huge cheatsheet right here.
I've saved the link to this page and called it 'Animate CC cheat sheet'
Ill be hitting you up again in the near future I assume - but the applications I am making are extremely simple so with the information provided should be more than enough.
Thanks again for all your help!
Copy link to clipboard
Copied
This is fantastic!
I'm really glad that these references are helpful to you. Believe me: some of them took me months to find out / understand. Haha
You can contact me anytime. I'll be happy to help.
Thanks and have a marvelous learning journey!
Copy link to clipboard
Copied
Hi João
your reply starting with "Excellent!" (06-Nov-2018 12:00) is really excellent as a cheatcheet for HTML/Canvas projects. Many things I knew already but it is nice to have everything handy in such a concise form. Great stuff!
One issue I'm left puzzled with is your point:
HOW TO MAKE SURE THE CHILDREN PROPS AND METHODS ARE READY AND HOW TO ACCESS THEM:
Well, I am struggling with some kind of check if all elements (or children, one might say) and their props are ready to be manipulated in runtime. Something like the $( document ).ready(function() {...)); in jQuery. Is that what you are doing here? I write your code myself instead of copy/past, just to reflect more on it:
var that = this;
that.start = function() {
// if using advanced layers
that.container = that.container.children[0].children;
// if not using advanced layers
// that.container = that.container.children;
};
setTimeout(that.start, 0);
Could you please elaborate on this a bit more? Assuming this in frame 1, you access this function straightaway (with a delay of zero milliseconds)? What precisely are you making SURE? Please, please explain. I was rrecently working on a stressful project and had a lot of console.log errors saying ..not a function, ..not defined, ..can't access property.. and it turned always out that it was a kind of timing problem , that props and/or children weren't ready in that tick moment I've tried to manipulate them. I helped myself by running through a delay with createjs.Ticker.getTime() before manipulation.
Hence when I saw this I got very alert ... but I don't get it to be honest.
Secondly the issue of Advanced Layers. When using them in coding terms (both JS and AS) things change. How you access objects within the document's tree-like hierarchy. Layers become symbols (movieclips it seems) and objects become children of those layers. In my stress project I mentioned I was all the time not aware of Advanced Layers being introduced to AN2019, let alone being activated by default. I ran into a variety of confusing problems and found workarounds of the stangest kind without really realising what's going on. First after finishing the project I started reading this forum to find some answers to accumulated questions. Well now I know what I should have known long before.
However, what I still don't get is how to access children when Advanced Layers are on. You are using children[0] which looks like you are assuming a number of layers within container, which can be accessed with array notation []. Does that mean children[0] assumes there is only one layer in container?
On this page form Adobe there is this odd example
Layer=getchildbyname("L1");
Layer.getchildbyname("symbol1");
but when I think that through, how comes "L1" into existence? Is that only for the sake of an example or is that supposed to be a generic name?
I made one test with adv.layers and in the resulting javascript I found the line:
this.Layer_1.name = "Layer_1";
More confusing is even that my production file (fla) has 3 layers with names from top "cjs", "caller" and "circle". "cjs" contains javascript only, the other two contain both a movieclip symbol. But only one layer is defined in the resulting javascript file. How to be certain how to access layers and children in layers when you have multiple children in multiple layers? I am currently trying hard to find reliable information about this but so far not much joy. You seem to be knowledgeable in this, could you elaborate on this a bit as well?
Sorry for being so verbose, that's my style
thanks in advance
Klaus
Copy link to clipboard
Copied
Hi, Klaus!
Thanks for the feedback.
Before anything, I'd like to suggest to you the deep and detailed explanations that ClayUUID has given in this thread:
Re: Accessing movieClip.children array Animate CC Canvas
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.
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.
I would just like to point out that by the time I replied to this thread I wasn't aware of the drawstart listener and/or of the correct usage of the on method.
Anyway, one obvious property I can tell you that won't be available is the length property of the children array. If you try a for-loop or a for each method without waiting for all children initialization, you'll probably get a length of 0.
As Clay mentioned, the disadvantage of using the setTimeout approach is when you need to set properties that alter appearance. But you still can count on this approach for other situations. I still use it in some of my projects.
About advanced layers, please notice it that this feature was introduced before the 2019 release - 2017, if I'm not mistaken. But as you mentioned, only now that this is turned on by default.
In the advanced layer mode, the layers indeed become Movie Clips. In HTML5 Canvas documents, my approach to access children, after using setTimeout or drawstart, is as follows:
// if using advanced layers
this.container.children[0].children;
// if not using advanced layers
this.container.children;
Please forgive me if the answers aren't what you were expecting and if I forgot something.
Regards,
JC
Copy link to clipboard
Copied
Thanks João
all of the first part about createjs.Ticker.on("tick", setTimeout(myInitFunction.bind(this), 0) and stage.on("drawstart" is enormously important and goes into memorize-book. Many cudos to you and ClayUUID.
The second part - in hindsight you're right with 2017, I myself was under the impression that the Camera tool was there earlier than version 2019. My confusion during my stress project was mainly in conjunction with the use of parent in code. I will make more experiments with advanced layers and coding and then might ask a question again but in another thread.
Klaus