Skip to main content
Participant
December 2, 2015
Answered

Controlling an Edge Animate OAM file with the Captivate play/pause buttons on the skin.

  • December 2, 2015
  • 5 replies
  • 5135 views

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

    This topic has been closed for replies.
    Correct answer Jordster1

    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!

    5 replies

    chrismay_at_delta6226261
    Inspiring
    June 21, 2018

    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.

    Inspiring
    June 22, 2018

    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

    chrismay_at_delta6226261
    Inspiring
    June 22, 2018

    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.

    chrismay_at_delta6226261
    Inspiring
    June 14, 2018

    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.

    Inspiring
    June 15, 2018

    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

    Known Participant
    June 13, 2018

    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.

    Inspiring
    June 13, 2018

    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

    Known Participant
    June 13, 2018

    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.

    Inspiring
    June 13, 2018

    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

    Jordster1
    Jordster1Correct answer
    Participating Frequently
    December 9, 2015

    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!

    randy1Author
    Participant
    December 12, 2015

    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

    Jordster1
    Participating Frequently
    December 14, 2015

    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