Hi Yanjie,
Hmm... I think the music might have been changed since I first posted this. Now I am looking for the mute button as quickly as possible.
Anyway, this site is an example of how to combine a non-Frontal Flash piece with Frontal. So the non-Frontal piece is the flying ribbons and the side-scrolling background images. Frontal is handling the menu bar at the bottom of the screen and all the section pop ups. Now how the ribbons and background images are being drawn is more of a question for a general Flash forum (it's using a Bitmap that is shifted each frame and then stamped with "brushstroke" bitmaps centered near the mouse's position), but what I can address is how the two pieces are integrated.
When you visit the site, the Frontal renderer is loaded and it begins to process site.xml:
http://www.jchristophercapital.com/site.xmlYou're browser will show you an error when you go to this URL so after you get there either save the page and open it in a text editor or choose View > Page Source in your browser.
In that Frontal site document, you'll see the flying ribbons SWF being loaded by an img tag in this snippet:
- Code: Select all
<!-- Brush Stroke Background -->
<div class="leftWindow" style="width: 100%; layout:stack;">
<img id="canvasWidget" class="canvasWidget" src="stillBg.swf" />
<text id="debugBox" style="width: 400px; height: 20px; background-color: #333333; color: #ffffff; right: 100%;"><![CDATA[nothing]]></text>
</div>
Then just below that you'll see Frontal markup for the different section pop ups and the menu bar.
To see how everything is coordinated, we need to look at the style sheet which is found here:
http://www.jchristophercapital.com/styles/styles.xmlUse the same technique mentioned above to see a readable view of this XML file.
In that style sheet you'll see a style class named "canvasWidget" that is applicable to the img tag being used to load the ribbons SWF:
- Code: Select all
.canvasWidget {
width: 100%;
height: 100%;
resize-scale-origin: center middle;
resize-scale: showmost;
@onLoaded {
image.content.registerBgLoadCallbackContainer(this);
}
@onBgsLoaded {
document.dynamic.bgsLoaded = true;
if (gE("menuBar", false) != null) gE("menuBar", false).runInteractions("reveal");
}
@getImageDimensions {
return {width:1280, height:720};
}
@onEnterFrame {
// Start up the brushstroke
try {
if (image.content.resume != undefined) {
if (! document.dynamic.canvasInitYet) {
image.content.resume(null);
document.dynamic.canvasInitYet = true;
document.dynamic.canvas = image.content;
image.content.mouseIn = true;
}
com.frontalcode.Scheduler.setTimeoutInFrames (function(){image.content.mouseIn = false;}, 2);
sA("onEnterFrame", undefined);
//document.gE("debugBox", false).sS("display", "block");
//document.gE("debugBox", false).text = image.content.scrollSpeed + ' | ' + (image.content.mouseIntroFramesLeft);
}
}
catch (e) {
}
}
}
So what is this doing? First, we're adding styles to size the SWF to fill the stage.
Next we're defining the onLoaded interaction which will be called by the Frontal renderer when the SWF is loaded and initialized. In the interaction we're calling an ActionScript method that's been written and compiled into the ribbons SWF. There's nothing special about this - in scene 1 / frame 1 of the ribbons SWF is this ActionScript:
- Code: Select all
function registerBgLoadCallbackContainer (frontalContainer : Object) : void {
this.callbackContainer = frontalContainer;
if (bgsLoaded) this.callbackContainer.runInteractions("onBgsLoaded");
}
This function is receiving the pointer to the Frontal object associated with the img tag, saving it and then using it to make a call back into Frontal. In this case it is saying that if the ribbon background images are already loaded by the time Frontal registers with the ribbons SWF then the onBGsLoaded interaction (defined in the Frontal style sheet snippet above) should be run.
So as you can see, the Frontal script is able to make a call into a loaded SWF's compiled ActionScript and that SWF is able to make calls back into Frontal. That's the key.
Continuing with the style class above, the onBGsLoaded interaction reveals the Frontal menu. As mentioned, this interaction will always be initiated by the ribbons SWF.
The getImageDimensions interaction simply tells Frontal what dimensions to use for the ribbons SWF when determining scale factors. This is handy because Flash will report the size of a SWF based on its actual contents and not say its published stage size.
The onEnterFrame interaction is called every frame waiting until the ribbons SWF has achieved some state and then creating some convenience pointers in document.dynamic (a handy place to put document variables) . Once it's done, the onEnterFrame interaction is removed. I'm not positive why this work isn't part of the onLoaded interaction - I assume it's because the ribbons SWF has to do some internal processing that takes multiple frames before it is completely ready.
So now document.dynamic.canvas points to the loaded and initialized ribbons SWF. We should now search for that in styles.xml. We see that it's being used in three places to do one of two things. The first is to maintain a boolean variable called "mouseIn" inside the ribbons SWF. The ribbons SWF uses that boolean to decided if its ribbons should chase the mouse or stay the course.
The second is to decide if the ribbons should deactivate and the background scrolling should be stopped or resumed. That is, if you go to the site, you'll see that the ribbons stop when a section is selected and then start up again when the section is closed (which is achieved by going to the home section). That's being handled by an onSelect interaction associated with the manager handling all the sites' sections. This interaction is called whenever a section change is initiated. Here's the style rule set I'm referring to:
- Code: Select all
#contentMgr {
//deep-link: path;
@setDeepLinkTitle {
title = "J. Christopher Capital, LLC | New York + Shanghai | " + (next == null ? current.gA("name") : next.gA("name"));
}
@onSelect {
switch (next.gA("id")) {
case "philosophySection":
case "leadershipSection":
case "investmentSection":
case "currentHoldingsSection":
case "pastHoldingsSection":
raiseMenu();
break;
default:
lowerMenu();
}
switch (next.gA("id")) {
case "homeSection":
if (document.dynamic.canvas && document.dynamic.canvas.resume) {
document.dynamic.canvas.resume(new flash.geom.Point (document.dynamic.canvas.canvas.scrollRect.x, 420));
}
break;
default:
if (document.dynamic.canvas && document.dynamic.canvas.deactivate) {
document.dynamic.canvas.deactivate();
}
}
}
}
Ok, so that's pretty much it for the integration between the ribbons SWF and the Frontal document. Let me know if you have any questions.
Best,
Mike