Copy link to clipboard
Copied
Hi Everyone,
I've been working on a project where I am mixing a variety of objects and animations. I am making the animations in Edge Animate. The problem I'm having is that when the end user clicks the pause button on the Captivate playback controls, the oam file does not pause. I've found descriptions of how I can make buttons in Edge Animate to play/pause the Captivate timeline, but I can't find anything about using the Captivate pause button to control the Edge Animate file. The only discussions I've managed to find on that don't seem to have any answers. Has anyone had any luck with that issue?
Any advice would be appreciated.
Thanks
Randy
Ok, this is kinda hacky but it totally works for controlling the main timeline object in an Edge file from Cap, where the Edge file has been imported to Cap 9 as a Web Object (oam). I went looking for answers same as you and came up empty, then starting tinkering on my own and came across the following method.
We're going to use window.postMessage to send a string between the Cap document window and the Edge iframe document window then react accordingly. You can read more about postMessage on the
...Copy link to clipboard
Copied
Ok, this is kinda hacky but it totally works for controlling the main timeline object in an Edge file from Cap, where the Edge file has been imported to Cap 9 as a Web Object (oam). I went looking for answers same as you and came up empty, then starting tinkering on my own and came across the following method.
We're going to use window.postMessage to send a string between the Cap document window and the Edge iframe document window then react accordingly. You can read more about postMessage on the accepted stack answer here: http://stackoverflow.com/questions/3076414/ways-to-circumvent-the-same-origin-policy
In your Edge file click on the Actions bracket for the Stage object in the timeline and select the compositionReady event. Paste this code into the text window:
// addEventListener for Chrome, attachEvent for IE
window.addEventListener( "message", receivedFromCaptivate, false );
window.attachEvent( "onmessage", receivedFromCaptivate );
function receivedFromCaptivate( event ){
switch( event.data ){
case "play":
sym.play();
break;
case "pause":
sym.stop();
break;
}
}
Save the file and publish it as an oam then import the oam into a Cap slide as you would normally. Now to set up the Cap stuff. Here's a visual aid for the rest of the explanation...
In the Cap file select whatever control you're using to initiate playing the Edge timeline (in the example above its "slide4Play"), select the "Use as Button" checkbox in the Properties area on the right, select the "Actions" tab, then for the dropdown for "On Success" choose "Execute Advanced Actions." Click the folder next to the Script selection control and the Advanced Actions dialog should pop up. Name your action something (eg, "playEdgeSlide4"), then click the "Add" icon in the grey bar to add a new action into the queue. From the "Select Action..." dropdown choose "Execute Javascript." From the "Select Window..." dropdown choose "current." Then click the "Script_Window" button to pop up a cruddy Javascript text window. Into that window you're going to paste this:
try{
$("iframe")[0].contentWindow.postMessage("play", "*");
} catch(e){
console.log(e.message);
}
Select "OK" to close the cruddy Javascript text window then hit the "Update Action" button to save your new action. Now we're going to do the same thing for the pause action - select the control you're using for pause, go through the above steps, name the action, set up the advanced action the same way and in the cruddy Javascript text window, paste the following:
try{
$("iframe")[0].contentWindow.postMessage("pause", "*");
} catch(e){
console.log(e.message);
}
Cap embeds the Edge file in an iframe on the page which has its own document window. In order to communicate between the base Cap window and the iframe window we use the postMessage call. So when you hit your Pause/Play button in Cap it posts an event to the function that gets registered in the Edge iframe. And in the event.data is the string we sent over from the Cap base window in the postMessage function ("play" or "pause"). We use a simple switch to react to the data string, stopping or playing the main Stage symbol in Edge ( sym.play(), sym.stop() ).
Hope this helps!
Copy link to clipboard
Copied
Hi Jordster1,
You are amazing! Not only does it work, but it makes sense! I can't begin to tell you how much I appreciate it. I only have one question. I'm assuming this only works on buttons you add to Captivate. Is there any way to use this with the play/pause that is part of the skin for the project or should I make the navigation and tell the skin editor to hide the playback controls?
Thanks
Randy
Copy link to clipboard
Copied
Thanks Randy, glad it's a viable option for you!
As to your question about controlling Edge from the skin, after some digging around I'm going to say in theory sure, you should be able to do it. Take it with the caveat that I'm still pretty new to Cap and haven't worked with the built-in skin playback controls at all but lets talk it out and see where we end up...
Somewhere those playback controls are throwing events that are getting caught and setting off a chain of instructions so it stands to reason that there's a spot in the code where we could drop our try/catch statements that target the Edge iframe. Check out the Common JS Interface docs for more info. The relevant events that stick out to me are adding listeners to CPAPI_MOVIESTART, CPAPI_MOVIESTOP, CPAPI_STARTPLAYBARSCRUBBING, and CPAPI_STOPPLAYBARSCRUBBING. Something to the tune of:
if( window.cpAPIInterface ){
if( window.cpAPIEventEmitter ){
window.cpAPIEventEmitter.addEventListener( "CPAPI_MOVIESTART", movieIsPlaying );
window.cpAPIEventEmitter.addEventListener( "CPAPI_MOVIESTOP", movieHasStopped );
// ...etc
}
}
function movieIsPlaying( event ){
// use the event object to sort out where you are in the project and react accordingly
}
function movieHasStopped( event ){
// use the event object to sort out where you are in the project and react accordingly
}
//...etc.
But we'd be adding this stuff to the root of the Cap project - in the onEnter of the Master slide like it shows in the Common JS Interface docs example - and technically we'd be reacting after those Cap events had been called so it might come off a bit disconnected between when we hit play/pause/scrub on the Cap controls and when the Edge movie would actually react. There's also CPAPI_SLIDEENTER event so we might have to start the event chain there instead and then check start/stop states. Regardless we'd likely need a few more project variables in Cap and generally a bit more coordination between Cap and Edge than what I'd posted previously. Aligning the scrubbing functionality and timing between Cap and Edge could be tricky, too. So, not impossible but you'd spend a fair amount of time under the hood of both Cap and Edge getting things to jive.
Part of me feels like I might be overthinking it, though - that maybe there's a much simpler or more reasonable solution. I'm sure someone will chime in if I've missed the boat entirely here but my sense of it otherwise is that going down this road would end up more convoluted than just creating your own playback control set and nixing Cap's if you're using Edge objects. It'd be nice if the Cap skin editor dialog let you attach events to playback buttons or linked them up to the Advanced Actions dialog - either of those options would feel pretty intuitive and probably get the job done. At one point in my initial research into the topic I'd come across documentation where if you'd imported a Flash movie you could align play/pause variables/events between Flash and Cap if you stuck to a certain naming convention but I don't think they ever got it aligned like that for Edge.
-Jord
Copy link to clipboard
Copied
Hi Jord,
I'm using Captivate 9 and Animate CC and I have a question relating to your answer to the question above.
I'm working on a project where I have animations that have been created in Animate CC and not Edge, and published as both HTML/JS & OAM files. These animations have then been imported into Captivate 9.
I have audio relating to these animations and these are placed on the Captivate timeline, and not in within the Animate CC output.
I would like to be able to stop/pause these animations and audio at the same time from a captivate button.
I tried your solution above to try and stop my animation, but it didn't seem to work. I'm assuming that's because the sym.play(); is a reference for Edge and doesn't relate to Animate CC. I tried replacing the sym.play(); with this.play(); but that didn't seem to work either.
I seems like your solutions should work for my application, but I'm just not sure how to implement it using Animate CC instead of Edge.
Any suggestions or help would be much appreciated.
Regards,
Richard
Copy link to clipboard
Copied
Hi Jord,
I'm in the same situation as Richard above. is there any way to control an Animate CC file from Captivate 9? The issue that I run into is that the button controlling the animation is not part of the tab order set in Captivate.
John
Copy link to clipboard
Copied
Hi all,
I am also interested in being able to control the timeline of an OAM exported in Animate and used in Captivate.
Noone has come up with a tweak of the above code?
Thanks
B
Copy link to clipboard
Copied
HI,
I ended up exporting from edge animate as an HTML5 file and using javascript to control the animation by calling a function in Captivate that would start the animation when a button was pressed. The only thing I was not able to figure out was how to get a transparent background in animate when exporting.
Animate file is loaded into Captivate as HTML5 web object.
In Captivate:
window.animationBegin();
if (audioPlay == "true"){
window.cp.show("sec01_11_speakerOff01_btn");
window.cp.hide("sec01_11_speakerOff_btn");
window.currentAudioButton = "_speakerOff01_btn";
} else {
window.currentAudioButton = "_speakerOff01_btn";
}
In Javascript:
function animationBegin() {
document.getElementById("myFrame" + animationControlID).contentWindow.cpPlayAnimation();
window.cp.disable(slideName + "_playAnimation_btn");
alphaChange("down", slideName + "_playAnimation_btn");
}
On main timeline in Edge Animate (stops the animation and causes it to play when button selected in Captivate):
this.stop();
window.myAnimation = this;
window.cpPlayAnimation = function()
{
myAnimation.gotoAndPlay(1);
};
(tells Captivate that the animation has stopped)
window.parent.animationCompleted();
/* Stop at This Frame
The timeline will stop/pause at the frame where you insert this code.
Can also be used to stop/pause the timeline of movieclips.
*/
this.stop();
This will also allow you to control your sound. Hope this helps.
Copy link to clipboard
Copied
Hi there romainj,
I am trying your solution in a Captivate file with an OAM from Adobe Animate CC.
In Animate CC I have the simplest tween (see the image).
I enter the code in the first frame of the Actions layer.
Then, where should I add the code exactly in Captivate.
You mention "In Javascript" - do you mean to a button that would execute a JavaScript?
In that case the first bit that you call "In Captivate" should be hooked to Java Script OnEnter of the slide?
Thanks for that
B
Copy link to clipboard
Copied
HI,
It will only work with HTML5. The javascript is actually in a separate .js file that loads when the captivate file loads. You place it in your assets folder (I created a js folder to hold external JavaScript files). I use javascript as it provides the ability to control and customize what's going on in Captivate.
The interactive section of the following sample shows some of the things you can do with JavaScript and Captivate (control navigation, interactive 360VR, etc). Securityguardtrainingontario.com Online Sample Take a look in the source for the page. In the assets folder is a js folder. The functions are found in the infinityUtils.js file.
Copy link to clipboard
Copied
Thanks for that.
I use a few bits of JS in Captivate but wanted to check if I can control with a Captivate button an OAM that is imported as animation in Captivate.
What you are saying is that this is NOT possible?
Copy link to clipboard
Copied
I couldn't make it work as an OAM and went to HTML5 which worked.
Copy link to clipboard
Copied
Strange that no one has found a solution for that. OAM is at the end of the day a bunch of files - HTML and JS among them ...
Copy link to clipboard
Copied
It IS possible, Bobby, but I leave that to all those JS experts to explain.
Copy link to clipboard
Copied
if you are using Adobe Animate, And know the name of the iframe that is created by Captivate, one line of code to stop:
document.getElementById($(this).attr("id")).contentWindow.exportRoot.stop();
to start:
document.getElementById($(this).attr("id")).contentWindow.exportRoot.play();
go to and play frame 300
document.getElementById($(this).attr("id")).contentWindow.exportRoot.gotoAndPlay(300);
Basically you are targeting the iFrame content created for the web object (animation), exportRoot is a method to access the animation from the document level.
Copy link to clipboard
Copied
Thank you Chris,
How do I get the name of the iframe? I checked in the folder "wor" created in the Captivate output folder but could not find it.
Also, are these lines supposed to be hooked to a button in Captivate?
Thanks again
B
Copy link to clipboard
Copied
Here a link to an example file:
Dropbox - AnimationControlExample.cptx
Preview the project in HTML5 browser and use the developer console to explore the resulting HTML.
If you nameed the animation object "Animation01" in the properties panel, the resulting iFrame id is usually "myFrame_Animation01c".
So the javascript would be "document.getElementById("myFrame_Animation01c").contentWindow.exportRoot.play();"
This can be on a button or as part of an advanced action, or anywhere you can run a javascript in Captivate.
Copy link to clipboard
Copied
That is fantastic.
Thank you for taking time and explaining it, crism. It totally works.
There is an additional nuance though. I put an invisible click box at the end of the captivate slide so the captivate timeline is stopped.
What I have left is only a pause and play buttons that do exactly what you described. I use the code you were so kind to share. One thing that happens is that when the OAM is at the end and has stopped (there is a this.stop(); in the animate project so it stops on the last frame). If I click the Play button it restarts the OAM animation. This is logical since the command is to play the movie which it does. However, I think the user may be confused. If the OAM has ended, s/he would click on the play button and the OAM will restart instead of the Captivate will move to the next slide. I can certainly put another button that would lead to the next slide, but the play button for the OAM will be still there.
This is just a thought.
On another hand, would the opposite be possible? To attach a script to a button in Animate that would move the Captivate timeline to a certain slide number?
Thanks again
Bobby
Copy link to clipboard
Copied
Script to tell Captivate to goto a certain slide number? yep, there is!
window.parent.cpCmndGotoSlideAndResume=X;
Where X is the slide number you want to jump to.
But I don't understand why the play button for the OAM would be on another slide? You could hide it when it is not needed, or only put it on the timeline of the slide with the OAM.
Copy link to clipboard
Copied
Thanks so much, chrism. This works great.
Would you please clarify your last comment? I think I lost the plot a bit.
I meant that when you have a play pause Captivate button to control the OAM, the play button would restart the OAM, but as said it does make sense.
Copy link to clipboard
Copied
Chris,
Using your code, I was able to pause and resume/play OAM animation from HTML5 Captivate; however, the audio that is integrated in the HTML5 animation (built in Animate CC) does not pause when the animation pauses. The audio in HTML5 animation (OAM file) is synced in Event mode.
Is there a way to pause (and resume) the audio along with the animation?
Thanks in advance,
Copy link to clipboard
Copied
Thank you! This worked perfectly.
Copy link to clipboard
Copied
Hi,
I know this is an old post, but the Dropbox link is no longer active, please repost.
I'm looking to achieve the same result.
thank you.
Copy link to clipboard
Copied
what if i have oam in few slides or few oam in one slide, do i have to name all to "myFrame..." too?
Copy link to clipboard
Copied
Is there anyone else who may have downloaded the example using the infinityUtil.js that may be able to share, It would be extremely useful to see how things are done. Many thanks in advance.
Note: In the mean time, I see the "security guard" example is still online, and there is a zip file within it showing the uploaded project, I'll delve into that and take a look.