Custom Video Interface
From Frontal Wiki
Here we will be using Frontal to create a video site. The functionality includes, content changing in corespondence with the video (This also adds video deep linking to the browser), a float based layout that changes uses traditional html techniques to have a layout that tweens to various set widths, via style tweens.
The nav is all on the map, the neighborhoods link to a video about them and the thumbnails deep link into the video. all that funtionality and how it was achieved is in the comments below:
<include rel="assets" type="application/x-shockwave-flash" src="assets/video_showcase_map.swf" /> <!--The above swf contains the assets for the map, it includes the map and the markers for the nav--> <style> // Global Styles document { base-url: http://www.frontalcode.com/; } * { style-tween-ease: fl.transitions.easing.Regular.easeOut; style-tween-duration: 8; style-tween-use-secs: false; } mgr { hide-unselected: true; tween-container-init: true; } text { font-family: Swift LT Std; color: black; } img { allow-smoothing: true; } video { @onSelect { enabled = true; } @onDeselect { enabled = false; } } document { scroll: auto; } /* Layout Styles The layout has two wrappers, one for the full site (.wrapper) and one for the left column (.leftColumn). The items housed within the left column are all set width 100% and is done so that when tweening styles we only have to tween the wrapper and the rest of the layout will adjust accordingly. */ .left { float: left; } .wrapper { width: 1000px; height: 620px; margin-left: 20px; } .leftColumn { width: 609px; z-index: 100; } .title { width: 100%; font-size: 30px; padding-top: 18px; letter-spacing: 1px; height: 50px; } .videoWrapper // Wraps .videoDiv and .controls for the full browser transition { width: 100%; height: 390px; z-index: 100; } .videoFullScreen { height: 100%; width: 100%; pin-to-stage: false; } .videoDiv { width: 100%; height: 100% leftover; layout: stack; background-color: #000000; } .controls { width: 100%; height: 45px; } .chromeWrapper { width: 100% leftover; margin-right: 20px; float: left; } .chrome { width: 100%; float: left; } .content { width: 600px; height: 144px; layout: stack; } .mapContainer { width: 379px; height: 600px; } .videoLink { top: 70px; left: 21px; width: 345px; height: 122px; padding-left: 10px; padding-top: 10px; layout: stack; } .mgr { hide-unselected: true; tween-container-init: true; } /* The following is the content placed within the divs styled above it includes the markers for the map navigation and the styles for all the other elements. */ .video { video-auto-play: true; video-skin: assets/skins/SkinUnderPlaySeekFullscreen.swf; width: 100%; height: 100%; video-skin-background-color: #959595; video-full-screen-background-color: #000000; resize-scale-origin: center middle; resize-scale: showall; } .locationTitle { font-size: 16px; letter-spacing: 2px; } .locationDescription { font-size: 11px; letter-spacing: 1.4px; leading: 2.5px; } .map { scale: .59; shadow-alpha: .15; shadow-angle: 166; shadow-distance: 1; shadow-strength: 1; shadow-blur: 25; shadow-quality: 1; } .thumbnail { width: 101px; height: 112px; margin-right: 10px; float: left; } .chelseaMarker { top: 270px; left: 120px; scale: .55; alpha: .5; shadow-alpha: 0; shadow-angle: 166; shadow-distance: 1; shadow-strength: 1; shadow-blur: 15; shadow-quality: 1; } .chelseaMarker:hover // These are built in psuedo classes in Frontal, they allow you to set styles that will be automatically tweened to { scale: .7; alpha: 1; shadow-alpha: .15; } .chelseaMarker:active { scale: .75; alpha: 1; shadow-alpha: .15; } .chelseaMarker:selected { scale: .75; alpha: 1; shadow-alpha: .15; } .eastVillageMarker { top: 358px; left: 270px; scale: .53; alpha: .5; shadow-alpha: 0; shadow-angle: 166; shadow-distance: 1; shadow-strength: 1; shadow-blur: 15; shadow-quality: 1; } .eastVillageMarker:hover { scale: .68; alpha: 1; shadow-alpha: .15; } .eastVillageMarker:active { scale: .73; alpha: 1; shadow-alpha: .15; } .eastVillageMarker:selected { scale: .73; alpha: 1; shadow-alpha: .15; } .lesMarker { top: 433px; left: 305px; scale: .5; } .tribecaMarker { top: 468px; left: 175px; scale: .55; } .frontalLink { top: 600px; left: 280px; } /* The following 3 styles take care of the layout tweening that allows the demo to have 3 different "sizes". 1. Small View designed for 1024x768 2. Large View Designed for larger monitors 3. Full Browser Window Video Each effect is accomplished by the same method of prepping style tweens and then tweening the styles on elements with ids. One interesting note is that we will only need to tween the wrapping containers as all their children are set to 100% and will therefore tween with them. The tweening is accomplished as follows. We first set a var to equal a getElement (gE) call. Then we call a prepStyleTween, which allows us to set styles (sS) afterwards without the style jumping to that value. Once all the styles we want to set for an element are set we call tweenStyles, which tweens the elements to there new values */ .smallView // Changes the width of the total wrap on site and the width of the left column - all children of the left column are set width 100% { float: right; padding-top: 13px; padding-right: 10px; alpha: 1; @onClick { /* These three lines are at the top of the layout changing on click interactions. They function as an easy way create a selected state for functionality that does not have an enabled or disabled state in Frontal by defailut. Another option is to keep them in a manager that has hide-unselected set to false to track there states. */ gE ( "smallView" ).sS('alpha', 1); gE ( "largeView" ).sS('alpha', .3); gE ( "fullBrowser" ).sS('alpha', .3); var wrapperSmall = gE ( "wrapper" ); wrapperSmall.prepStyleTween ( ); wrapperSmall.sS('width', 1000); wrapperSmall.sS('height', 620); wrapperSmall.tweenStyles ( ); var leftSmall = gE ( "leftColumn" ); leftSmall.prepStyleTween ( ); leftSmall.sS('width', 609); leftSmall.tweenStyles ( ); var videoWrapperSmall = gE ( "videoWrapper" ); videoWrapperSmall.prepStyleTween ( ); videoWrapperSmall.sS('height', 390); videoWrapperSmall.tweenStyles ( ); zoomVideo ( false ); } } .largeView // Changes the width of the total wrap on site and the width of the left column - all children of the left column are set width 100% { float: right; padding-top: 13px; padding-right: 10px; alpha: .3; @onClick { gE ( "smallView" ).sS('alpha', .3); gE ( "largeView" ).sS('alpha', 1); gE ( "fullBrowser" ).sS('alpha', .3); var wrapperLarge = gE ( "wrapper" ); wrapperLarge.prepStyleTween ( ); wrapperLarge.sS('width', 1330); wrapperLarge.sS('height', 775); wrapperLarge.tweenStyles ( ); var leftLarge = gE ( "leftColumn" ); leftLarge.prepStyleTween ( ); leftLarge.sS('width', 915); leftLarge.tweenStyles ( ); var videoWrapperLarge = gE ( "videoWrapper" ); videoWrapperLarge.prepStyleTween ( ); videoWrapperLarge.sS('height', 560); videoWrapperLarge.tweenStyles ( ); zoomVideo ( false ); } } .fullBrowser //takes care of the full browser video via a pin-to-stage switch { float: right; padding-top: 13px; padding-right: 10px; alpha: .3; @onClick { gE ( "smallView" ).sS('alpha', .3); gE ( "largeView" ).sS('alpha', .3); gE ( "fullBrowser" ).sS('alpha', 1); zoomVideo ( true ); } } /* This section takes care of the transition between content as the video plays. Using video cuePoints this technique could also be used for transitioning other items that could be context based (such as ads) and is not limited to a jumpTo function */ .chelseaVideo { @cuePoint1: 1, @oncuePoint1: gE ( "locationMgr" ).jumpTo ( 1 ); @cuePoint2: 7, @oncuePoint2: gE ( "locationMgr" ).jumpTo ( 2 ); @cuePoint3: 19, @oncuePoint3: gE ( "locationMgr" ).jumpTo ( 3 ); @cuePoint4: 28, @oncuePoint4: gE ( "locationMgr" ).jumpTo ( 1 ); } .eastVillageVideo { @cuePoint5: 1, @oncuePoint5: gE ( "locationMgr" ).jumpTo ( 4 ); @cuePoint6: 11, @oncuePoint6: gE ( "locationMgr" ).jumpTo ( 5 ); @cuePoint7: 22, @oncuePoint7: gE ( "locationMgr" ).jumpTo ( 6 ); @cuePoint8: 33, @oncuePoint8: gE ( "locationMgr" ).jumpTo ( 4 ); } /* In order to gain the ability we have expanded on the frMarker default class by adding multiple get element and jump to functions and added coresponding attributes (which can be made up on the fly in Frontal) to our markers in the layout */ .frMarker { is-link: true; is-marker: true; @onClick { gE ( gA ( "mgrId" ) ).jumpTo ( gA ( "elemNdx" ) ); gE ( gA ( "chromeId" ) ).jumpTo ( gA ( "chromeNdx" ) ); gE ( gA ( "thumbId" ) ).jumpTo ( gA ( "thumbNdx" ) ); } } .cuepointMarker { @onClick { var video = gE ( gA ( "videoId" ) ); video.processDeepLink ( video.getDeepLinkValue ( gA ( "cuepointNdx" ) ) ); } } </style> <script> // This helper function handles zooming the video in to fill the browser // and then out again to fit into the chosen layout. // var videoZoomedIn = false; function zoomVideo ( zoomIn ) { if ( videoZoomedIn == zoomIn ) return; var video = document.gE ( "videoFullScreen" ); if ( ! videoZoomedIn ) { // Switch to being pinned to the stage but set our // width, height and position so that the switch doesn't // alter our lay out. // video.sS ( 'pin-to-stage', true ); video.sS ( 'left', video.left ); video.sS ( 'top', video.top ); video.sS ( 'width', video.width ); video.sS ( 'height', video.height ); video.prepStyleTween ( ); video.sS ( 'left', 0 ); video.sS ( 'top', 0 ); video.sS ( 'width', '100%' ); video.sS ( 'height','100%' ); video.tweenStyles ( ); } else { // Turn off being pinned to the stage but set our width // and height (which are 100% and so highly dependent on // their parent Container) and position so that the // switch doesn't alter our lay out. // var pos = video.getFloatNormalPosition ( ); video.sS ( 'left', pos.left ); video.sS ( 'top', pos.top ); video.sS ( 'width', pos.width ); video.sS ( 'height', pos.height ); video.sS ( 'pin-to-stage', false ); video.prepStyleTween ( ); video.sS ( 'left', 0 ); video.sS ( 'top', 0 ); video.sS ( 'width', '100%' ); video.sS ( 'height','100%' ); video.tweenStyles ( ); } videoZoomedIn = zoomIn; } </script> <div id="wrapper" class="wrapper"> <div id="leftColumn" class="left leftColumn" style=""> <div id="title" class="left title"> NYC Video Tour: </div> <div id="videoWrapper" class="left videoWrapper"> <div id="videoFullScreen" class="left videoFullScreen"> <div class="videoDiv"> <manager id="videoSlideshow" class="mgr"> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="current" property="alpha" start="1" finish="0" duration="6" delay="0" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="next" property="alpha" start="0" finish="1" duration="6" delay="3" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> </manager> <video id="chelseaVideo" src="assets/video/chelsea.flv" class="video chelseaVideo" style="control-attacher-index: chelseaControls;"/> <video id="eastVillageVideo" src="assets/video/east_village.flv" class="video eastVillageVideo" style="control-attacher-index: eastVillageControls;" /> </div> <div class="controls"> <div class="chromeWrapper"> <manager id="chromeMgr" class="mgr"> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="current" property="alpha" start="1" finish="0" duration="6" delay="0" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="next" property="alpha" start="0" finish="1" duration="6" delay="3" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> </manager> <div id="chelseaControls" class="chrome" /> <div id="eastVillageControls" class="chrome" /> </div> <div style="float: right; width: 100px;"> <img id="smallView" symbol="smallView" class="smallView" /> <img id="largeView" symbol="largeView" class="largeView" /> <img id="fullBrowser" symbol="fullBrowser" class="fullBrowser" /> </div> </div> </div> </div> <div class="left content"> <manager id="locationMgr" class="mgr"> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="current" property="alpha" start="1" finish="0" duration="6" delay="0" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="next" property="alpha" start="0" finish="1" duration="6" delay="3" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> </manager> <div> <div id="chelseaPiers" class="locationTitle">Chelsea Piers</div> <div class="locationDescription">The piers are currently used by the Chelsea Piers Sports & Entertainment Complex. The new complex includes film and television production facilities, including those for CBS College Sports Network and Food Network, a health club, a day spa, the city's largest training center for gymnastics, two basketball courts, playing fields for indoor lacrosse and soccer, batting cages, a rock climbing wall and dance studios. In addition there is an AMF Bowling center, a golf club with multi-story driving range, and two full sized ice rinks for skating. It is located in the Chelsea neighborhood, on the northern edge of Greenwich Village and the Meatpacking District.</div> </div> <div> <div class="locationTitle">The Highline</div> <div class="locationDescription">The High Line is a 1.45-mile (2.33 km) section of the former elevated freight railroad of the West Side Line, in Chelsea along the lower west side of Manhattan. It runs from 34th Street near the Javits Convention Center to Gansevoort Street in the Meat Packing District of the West Village. The High Line was built in the early 1930s by the New York Central Railroad and was an active railway until 1980. In the 1990s, it became known for the wild grass and trees that grew on the abandoned railway. By 1999 Community support of public redevelopment of the High Line for pedestrian use grew, and funding was allocated in 2004.</div> </div> <div> <div class="locationTitle">Chelsea Market</div> <div class="locationDescription">Chelsea Market is an enclosed, urban food court and shopping mall in New York City. It was built within the former Nabisco factory complex where the Oreo cookie was invented and produced. The 22-building complex fills two entire blocks bounded by 9th and 11th Avenues and 15th to 16th Street. In addition to the retail concourse in the structure east of 10th Avenue, it also provides standard office space for tenants, including media and broadcasting companies such as Oxygen Network, Food Network, Mr Youth, MLB.com, EMI Music Publishing and the local New York City cable station NY1. Also, more recently, Google has moved into some of the second and fourth floors.</div> </div> <div> <div id="stMarks" class="locationTitle">St. Marks</div> <div class="locationDescription">St. Mark's Place is a street in the East Village neighborhood of the New York City borough of Manhattan. It is named after St Mark's Church in-the-Bowery, which was built on Stuyvesant Street but is now on 10th Street. St. Mark's Place once began at the intersection of the Bowery and Stuyvesant Street, but today the street runs from Third Avenue to Avenue A.</div> </div> <div> <div class="locationTitle">Cooper Square</div> <div class="locationDescription">Cooper Square is a junction of streets in Manhattan, New York City. It is at the confluence of the neighborhoods of The Bowery, the East Village and the Lower East Side. It is fed directly from the south by Bowery at East Fourth Street which becomes Third Avenue after Saint Mark's Place. The northeast corner borders Saint Mark's Place, while the northwest corner borders Astor Place.</div> </div> <div> <div class="locationTitle">Thompkin's Square Park</div> <div class="locationDescription">Tompkins Square Park is a 10.5 acre (42,000 m²) public park in the Alphabet City section of the East Village neighborhood in the borough of Manhattan in New York City. It is square in shape, and is bounded on the north by East 10th Street, on the east by Avenue B, on the south by East 7th Street, and on the west by Avenue A. St. Marks Place abuts the park to the west.</div> </div> </div> </div> <div id="map" class="left mapContainer"> <img symbol="map" class="map" /> <div class="videoLink"> <manager id="videoLinkMgr" class="mgr"> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="current" property="alpha" start="1" finish="0" duration="6" delay="0" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> <transitioner custom="com.frontalcode.transitions.TweenTransition" target="next" property="alpha" start="0" finish="1" duration="6" delay="3" style="tween-container-ease: fl.transitions.easing.Regular.easeOut;" /> </manager> <div id="chelseaThumbs"> <img src="assets/images/videothumb1.jpg" class="thumbnail cuepointMarker" videoId="chelseaVideo" cuepointNdx="cuePoint1" /> <img src="assets/images/videothumb2.jpg" class="thumbnail cuepointMarker" videoId="chelseaVideo" cuepointNdx="cuePoint2" /> <img src="assets/images/videothumb3.jpg" class="thumbnail cuepointMarker" videoId="chelseaVideo" cuepointNdx="cuePoint3" /> </div> <div id="eastVillageThumbs"> <img src="assets/images/videothumb4.jpg" class="thumbnail cuepointMarker" videoId="eastVillageVideo" cuepointNdx="cuePoint5" /> <img src="assets/images/videothumb5.jpg" class="thumbnail cuepointMarker" videoId="eastVillageVideo" cuepointNdx="cuePoint6" /> <img src="assets/images/videothumb6.jpg" class="thumbnail cuepointMarker" videoId="eastVillageVideo" cuepointNdx="cuePoint7" /> </div> </div> <img symbol="chelsea" class="frMarker chelseaMarker" mgrId="videoSlideshow" elemNdx="chelseaVideo" chromeId="chromeMgr" chromeNdx="chelseaControls" thumbId="videoLinkMgr" thumbNdx="chelseaThumbs" /> <img symbol="les" class="lesMarker" /> <img symbol="eastvillage" class="frMarker eastVillageMarker" mgrId="videoSlideshow" elemNdx="eastVillageVideo" chromeId="chromeMgr" chromeNdx="eastVillageControls" thumbId="videoLinkMgr" thumbNdx="eastVillageThumbs" /> <img symbol="tribeca" class="tribecaMarker" /> <text class="frLink frontalLink" href="http://frontalcode.com"><![CDATA[<font size="10">Created w/ Frontal</font>]]></text> </div> </div>