Copy link to clipboard
Copied
I'm sue this is very basic, but I cannot find the answer anywhere. I am making an HTML5 canvas doc.
Thank you to any who can help.
I thought of a safer approach, for the case where you want to either play one animation or all animations. You could have. variable that you test. On the last frame of each animation you have this:
if(playone) this.stop();
Then, when you tell them to play one animation you do this:
playone = true;
this.gotoAndPlay("animation 3");
Animation 3 would play, and it would stop on the last frame of that animation. If you want to play all animations you would do:
playone = false;
this.gotoAndPlay("animation 1"
...Copy link to clipboard
Copied
Hi.
You code your button play from the initial label using your_movie_clip.gotoAndStop("X") and then you put a this.stop() inside of your_movie_clip in the frame where your label "Y" begins.
Copy link to clipboard
Copied
Hi, thanks for responding! Not sure if that would work. I have no movie clips. I may not have explained what I am trying to do clearly.
They easiest way to describe it would be, if I had a 100 frame animation, I need the user to be able to just play the whole thing straight through (1-100), or, when clicking a button, they play frames 70-90 (start at 70, end at 90). And there will be several instances where they can click a button and play a specific range. I can't put stops anywhere because that will disrupt the flow of those who want to watch it straight through.
EDIT Sorry, I misunderstood your use of "movie clip" when stating I have no movie clips. Basically I need the "stop and play" command to reside within the action for the button instance, and not be tied to any particular frame. Thanks
Copy link to clipboard
Copied
Trying to make it more clear here -
Basically, for the following line:
_this.gotoAndPlay(XXXXX);
What would I put in place of "XXXXX" to mean "frames 70 to 90"?
Copy link to clipboard
Copied
Nothing. The gotoAndPlay() function Does Not Work That Way. If you want playback to stop on a certain frame, you put a this.stop() on that frame.
Copy link to clipboard
Copied
Thank you for replying. Is there another way I can make this happen? I don't think I can put stop () in that frame because I want the user to be able to watch the entire movie straight through if they choose (without getting stopped at that frame).
Copy link to clipboard
Copied
Sigh. Okay, if you're dead set on doing whatever weird thing you're doing, paste this code somewhere in your initialization where it will only ever be run once.
createjs.MovieClip.prototype.playRange = function(startFrame, stopFrame) {
var _this = this;
stopFrame = _this.timeline.resolve(stopFrame);
if (_this.playingRange) {
createjs.Ticker.removeEventListener("tick", _this.playingRange);
}
_this.playingRange = createjs.Ticker.addEventListener("tick", function() {
if (_this.currentFrame >= stopFrame) {
createjs.Ticker.removeEventListener("tick", _this.playingRange);
_this.playingRange = 0;
_this.stop();
}
});
_this.gotoAndPlay(startFrame);
}
This adds a new movieclip method that supports playing a range of frames. Either parameter can be a frame number or a frame label. Use like this:
this.playRange(20, 50);
...or whatever. There's no error checking, so use responsibly.
Copy link to clipboard
Copied
Thank you! I will try this.
But, from your subtle tone , I'm thinking I've set out to do this is in a dumb way? Is there a better way to do it?
"It" being (I'm rounding all numbers etc for simplicity sake):
1) Allows the user to watch all ten animations, in order, straight through (play button)
2) Allow the user to skip to the next or previous animation, and just that animation (next, previous buttons)
3) Allow the user to skip directly to any individual animation, and just that animation (go to x)
Thanks. You've helped a lot already so if not in the mood to keep going that's totally fine, I get it, and I appreciate the responses already.
Copy link to clipboard
Copied
A different approach, that may not always be frame accurate, but perhaps that doesn't matter, would be to use setTimeout():
var startframe = 20;
var endframe = 53;
//and for this example the frame rate is 24 fps
var framerate = 24;
var self = this;
this.gotoAndPlay(startframe);
setTimeout(dostop, (endframe - startframe + 1) / 24 * 1000);
function dostop() {
self.stop();
alert(self.currentFrame);
}
I tried it a lot of times, and it stopped on the right frame each time.
Copy link to clipboard
Copied
I thought of a safer approach, for the case where you want to either play one animation or all animations. You could have. variable that you test. On the last frame of each animation you have this:
if(playone) this.stop();
Then, when you tell them to play one animation you do this:
playone = true;
this.gotoAndPlay("animation 3");
Animation 3 would play, and it would stop on the last frame of that animation. If you want to play all animations you would do:
playone = false;
this.gotoAndPlay("animation 1");
The last frame of the last animation would have:
this.stop();
so that it stops whether you were playing one or all animations.
Copy link to clipboard
Copied
Sorry for the late response! Thank you for these two replies Colin. I will try the latter approach.
Copy link to clipboard
Copied
So you're going with the solution that requires adding timeline code to every single chunk of frames.
People confuse me.
Copy link to clipboard
Copied
I don't really know what I'm doing and therefore I actually don't know which solution is best. I'm not sure which one I will eventually end up implementing. I'm going to experiment with what I've learned here, and I'm thankful for everyone's input. I didn't mark this as answered, if that's what you are referring to. I'm not sure how that happened (unless I did it by accident).
Copy link to clipboard
Copied
Thanks for this ClayUUID, it worked perfectly. My use case was similar except I did not need to play through all the animations. Our designer created a bunch of actions on the timeline with labels for each action, we just wanted to make each action playable from outside of the animation. So I walked through each label and used your PlayRange aproach to play just the frames in that label. Then attached each method to a global object so we could access from outside of the animation file. For good measure I wrapped it in a promise for chaining and pass in a boolean for optionall looping. So I could control the animation like this:
// window.<instanceName>Animations.<anyLabelName>(loop: bool);
window.rockyAnimations.idle(true)
window.rockyAnimations.lip_flap()
window.rockyAnimations.lip_flap().then(()=> {window.rockyAnimations.idle(true)})
If there is a better way of doing this, I would be very interested. But here is what I ended up with:
// drop this code in an action on the first frame
var _this = this;
// this should be renamed to whatever you named your <instanceName>
const uniqueInstanceName = "rocky";
// with some help from this suggestion: https://community.adobe.com/t5/animate-discussions/how-do-i-instruct-a-button-to-play-a-specific-range-of-frames-i-e-quot-play-from-frame-labelled-x-to/td-p/9849836
cjs.MovieClip.prototype.playRange = function(startFrame, stopFrame, loop) {
return new Promise((resolve, reject) => {
var _this = this;
stopFrame = _this.timeline.resolve(stopFrame);
if (_this.playingRange) {
cjs.Ticker.removeEventListener("tick", _this.playingRange);
}
_this.playingRange = createjs.Ticker.addEventListener("tick", function() {
if (_this.currentFrame >= stopFrame) {
cjs.Ticker.removeEventListener("tick", _this.playingRange);
_this.playingRange = 0;
if(loop) {
_this.playRange(startFrame, stopFrame, loop);
resolve();
}
else {
_this.stop();
resolve();
}
}
});
_this.gotoAndPlay(startFrame);
});
}
const animationList = window[uniqueInstanceName + "Animations"] = {};
const instance = _this[uniqueInstanceName];
const labelsWithEndPosition = [];
for(let i = 0; i < _this.labels.length; i++) {
let endPosition = _this.timeline.duration - 1;
if(i + 1 < _this.labels.length) {
endPosition = _this.labels[i+1].position - 1;
}
labelsWithEndPosition.push({
label: _this.labels[i].label,
start: _this.labels[i].position,
end: endPosition
});
}
labelsWithEndPosition.forEach(
labelObj => {
animationList[labelObj.label] = function (loop = false) {
return instance.playRange(labelObj.start, labelObj.end, loop);
};
}
)
animationList.stop = function() { instance.stop(); }
instance.stop();