1

I can't get FlashPro CC HTML5 Canvas exports to work with sound on the iPad/iPhone. I reached out on Twitter and got this response:

"Timeline plays on click, but sound plays asynchronously on frame2. Fix this using "playEmptySound."

Here is the link I was given. http://www.createjs.com/Docs/SoundJS/classes/WebAudioPlugin.html#method_playEmptySound

OK, now the problem, I am an animator at best, and know very little if any code… where do I insert this "playEmptySound" code?

I've posted the 2 files Flash kicks out, the HTML & the JS Any help on this will be greatly appreciated.

This is the JS animation generated from Flash CC

(function (lib, img, cjs) {

var p; // shortcut to reference prototypes

// library properties:
lib.properties = {
    width: 550,
    height: 400,
    fps: 15,
    color: "#FFFFFF",
    manifest: [
        {src:"audio/moo.mp3", id:"moo"}
    ]
};



// symbols:



(lib.triangle = function() {
    this.initialize();

    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f("#6600FF").s().p("AolIlIIJxKIJBRKg");
    this.shape.setTransform(55,55);

    this.addChild(this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,110,110);


(lib.square_btn = function() {
    this.initialize();

    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f("#FF0000").s().p("AnkHlIAAvJIPJAAIAAPJg");
    this.shape.setTransform(48.5,48.5);

    this.addChild(this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,97,97);


(lib.blue_btn = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});

    // timeline functions:
    this.frame_2 = function() {
        playSound("moo");
    }

    // actions tween:
    this.timeline.addTween(cjs.Tween.get(this).wait(2).call(this.frame_2).wait(1));

    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f().s("#009900").ss(1,1,1).p("AGQAAQAAClh2B1Qh1B2ilAAQikAAh2h2Qh1h1AAilQAAikB1h2QB2h1CkAAQClAAB1B1QB2B2AACkg");
    this.shape.setTransform(40,40);

    this.shape_1 = new cjs.Shape();
    this.shape_1.graphics.f("#0066FD").s().p("AkaEaQh1h1AAilQAAikB1h2QB2h1CkAAQClAAB1B1QB2B2AACkQAAClh2B1Qh1B2ilAAQikAAh2h2g");
    this.shape_1.setTransform(40,40);

    this.timeline.addTween(cjs.Tween.get({}).to({state:[{t:this.shape_1},{t:this.shape}]}).to({state:[{t:this.shape_1},{t:this.shape}]},2).wait(1));

}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(-1,-1,82,82);


(lib.background = function() {
    this.initialize();

    // Layer 1
    this.shape = new cjs.Shape();
    this.shape.graphics.f("#666666").s().p("EgsXAgMMAAAhAXMBYvAAAMAAABAXg");
    this.shape.setTransform(284.1,206.1);

    this.addChild(this.shape);
}).prototype = p = new cjs.Container();
p.nominalBounds = new cjs.Rectangle(0,0,568.2,412.1);


(lib.sound_mc = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});

    // timeline functions:
    this.frame_0 = function() {
        /* 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();

        /* Click to Go to Frame and Play
        Clicking on the specified symbol instance moves the playhead to the specified frame in the timeline and continues playback from that frame.
        Can be used on the main timeline or on movie clip timelines.

        Instructions:
        1. Replace the number 5 in the code below with the frame number you would like the playhead to move to when the symbol instance is clicked.
        2.Frame numbers in EaselJS start at 0 instead of 1
        */

        this.square_btn.addEventListener("click", fl_ClickToGoToAndPlayFromFrame_2.bind(this));

        function fl_ClickToGoToAndPlayFromFrame_2()
        {
            this.gotoAndPlay(1);
        }
    }
    this.frame_2 = function() {
        playSound("moo");
    }

    // actions tween:
    this.timeline.addTween(cjs.Tween.get(this).call(this.frame_0).wait(2).call(this.frame_2).wait(58));

    // square
    this.square_btn = new lib.square_btn();
    this.square_btn.setTransform(48.5,48.5,1,1,0,0,0,48.5,48.5);
    new cjs.ButtonHelper(this.square_btn, 0, 1, 1);

    this.timeline.addTween(cjs.Tween.get(this.square_btn).to({y:210.5},33).wait(27));

}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(0,0,97,97);


// stage content:



(lib.moo_button = function(mode,startPosition,loop) {
    this.initialize(mode,startPosition,loop,{});

    // timeline functions:
    this.frame_0 = function() {
        /* 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();

        /* Click to Go to Frame and Play
        Clicking on the specified symbol instance moves the playhead to the specified frame in the timeline and continues playback from that frame.
        Can be used on the main timeline or on movie clip timelines.

        Instructions:
        1. Replace the number 5 in the code below with the frame number you would like the playhead to move to when the symbol instance is clicked.
        2.Frame numbers in EaselJS start at 0 instead of 1
        */

        this.blue_btn.addEventListener("click", fl_ClickToGoToAndPlayFromFrame.bind(this));

        function fl_ClickToGoToAndPlayFromFrame()
        {
            this.gotoAndPlay(1);
        }
    }

    // actions tween:
    this.timeline.addTween(cjs.Tween.get(this).call(this.frame_0).wait(50));

    // Layer 2
    this.triangle = new lib.triangle();
    this.triangle.setTransform(377,178,1,1,0,0,0,55,55);

    this.timeline.addTween(cjs.Tween.get(this.triangle).wait(50));

    // Layer 1
    this.blue_btn = new lib.blue_btn();
    this.blue_btn.setTransform(85,203,1,1,0,0,0,40,40);
    new cjs.ButtonHelper(this.blue_btn, 0, 1, 2);

    this.timeline.addTween(cjs.Tween.get(this.blue_btn).to({x:455},49).wait(1));

    // Layer 4
    this.sound_mc = new lib.sound_mc();
    this.sound_mc.setTransform(220.6,84.5,1,1,0,0,0,48.5,48.5);

    this.timeline.addTween(cjs.Tween.get(this.sound_mc).wait(50));

    // Layer 3
    this.instance = new lib.background("synched",0);
    this.instance.setTransform(278.1,202.1,1,1,0,0,0,284.1,206.1);

    this.timeline.addTween(cjs.Tween.get(this.instance).wait(50));

}).prototype = p = new cjs.MovieClip();
p.nominalBounds = new cjs.Rectangle(269,196,568.2,412.1);

})(lib = lib||{}, images = images||{}, createjs = createjs||{});
var lib, images, createjs;

This is the HTML generated from Flash CC

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>moo_button-tringle2</title>

<script src="script/easeljs-0.7.1.min.js"></script>
<script src="script/tweenjs-0.5.1.min.js"></script>
<script src="script/movieclip-0.7.1.min.js"></script>
<script src="script/preloadjs-0.4.1.min.js"></script>
<script src="script/soundjs-0.5.2.min.js"></script>
<script src="moo_button-tringle2.js"></script>

<script>
var canvas, stage, exportRoot;

function init() {
    canvas = document.getElementById("canvas");

    var loader = new createjs.LoadQueue(false);
    loader.installPlugin(createjs.Sound);
    loader.addEventListener("complete", handleComplete);
    loader.loadManifest(lib.properties.manifest);
}

function handleComplete() {
    exportRoot = new lib.moo_button();

    stage = new createjs.Stage(canvas);
    stage.addChild(exportRoot);
    stage.update();
    stage.enableMouseOver();

    createjs.Ticker.setFPS(lib.properties.fps);
    createjs.Ticker.addEventListener("tick", stage);
}

function playSound(id, loop) {
    createjs.Sound.play(id, createjs.Sound.INTERRUPT_EARLY, 0, 0, loop);
}
</script>
</head>

<body onload="init();" style="background-color:#D4D4D4">
    <canvas id="canvas" width="550" height="400" style="background-color:#FFFFFF"></canvas>
</body>
</html>
Lanny
  • 11,244
  • 1
  • 22
  • 30
tonyteach
  • 11
  • 1

2 Answers2

1

OJay's answer is what I would have initially tried. The only other thing I would try instead is, inside of your function handleComplete() something like:

function handleComplete() {
    exportRoot = new lib.moo_button();

    stage = new createjs.Stage(canvas);
    stage.addChild(exportRoot);
    stage.update();
    stage.enableMouseOver();

    createjs.Ticker.setFPS(lib.properties.fps);
    createjs.Ticker.addEventListener("tick", stage);

    var listener = function() {
        createjs.WebAudioPlugin.playEmptySound();
        window.removeEventListener('touchstart', listener);
    };
    window.addEventListener('touchstart', listener);
}

¯\_(ツ)_/¯

Brian Mathews
  • 682
  • 4
  • 6
0

you'll want to insert it in lib.moo_button function fl_ClickToGoToAndPlayFromFrame. It should look like this:

function fl_ClickToGoToAndPlayFromFrame()
{
  if(createjs.WebAudioPlugin.context != null) {
    createjs.WebAudioPlugin.playEmptySound();
  }
  this.gotoAndPlay(1);
}

You may need to apply it to all your buttons if you are not sure which one will be pressed first, but the downside is that the code will run on every button press. Coding in Flash is not the best solution for this kind of problem, but can get the job done.

Hope that helps.

OJay
  • 1,249
  • 7
  • 14
  • Thanks, neither of these have worked. Actually, yes they work in the "browsers" for iPad & iPhone, BUT I'm using these inside an ePub3. The sound plays as it should in the ePub everywhere else, but inside iPad/iPhone. – tonyteach Mar 13 '15 at 01:15
  • WebView's are tricky. If ePub is based off Cordova, you could try the new CordovaAudioPlugin with the latest [SoundJS-Next](https://github.com/CreateJS/SoundJS). Web audio has trouble inside of web views because it requires xhr to load audio which is not available to load local files. You could force HTMLAudioPlugin to avoid this issue: `createjs.Sound.registerPlugins([HTMLAudioPlugin]);` – OJay Apr 23 '15 at 15:30