├── vid └── video.mp4 ├── img ├── poster.jpg ├── poster.psd └── resize.png ├── swf └── vidobject.swf ├── vidobject_source ├── VidObject.fla └── com │ └── johnpolacek │ ├── events │ ├── TrackEvent.as │ └── UIEvent.as │ ├── shapes │ ├── Frame.as │ ├── Line.as │ ├── BitmapNoiseRectangle.as │ ├── ArrowHead.as │ ├── ArrowBlock.as │ ├── EllipseShape.as │ ├── RectangleShape.as │ └── RectangleGradientShape.as │ ├── display │ ├── ContentDisplay.as │ ├── ImageDisplay.as │ ├── VideoDisplay.as │ ├── AudioDisplay.as │ └── ContentDisplayCreator.as │ ├── utils │ ├── StringUtils.as │ └── DisplayUtils.as │ ├── ui │ ├── BasicButton.as │ ├── PlayPauseButton.as │ ├── VolumeControl.as │ ├── FullScreenButton.as │ ├── ProgressBar.as │ └── FullScreenScrollbar.as │ └── media │ ├── VidObject.as │ └── VideoStreamPlayer.as ├── README.md ├── css └── main.css ├── index.html └── js └── simplevid.js /vid/video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpolacek/SimpleVid/HEAD/vid/video.mp4 -------------------------------------------------------------------------------- /img/poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpolacek/SimpleVid/HEAD/img/poster.jpg -------------------------------------------------------------------------------- /img/poster.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpolacek/SimpleVid/HEAD/img/poster.psd -------------------------------------------------------------------------------- /img/resize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpolacek/SimpleVid/HEAD/img/resize.png -------------------------------------------------------------------------------- /swf/vidobject.swf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpolacek/SimpleVid/HEAD/swf/vidobject.swf -------------------------------------------------------------------------------- /vidobject_source/VidObject.fla: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnpolacek/SimpleVid/HEAD/vidobject_source/VidObject.fla -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/events/TrackEvent.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.events { import flash.events.Event; /** * TrackEvent is used to dispatch google analytics tracking info * * @version 15 Jun 2010 * @author John Polacek, john@johnpolacek.com */ public class TrackEvent extends Event { public var trackAction:String; public var trackLabel:String; public static const TRACK:String = "TRACK"; public function TrackEvent(type:String, action:String, label:String, bubbles:Boolean = true, cancelable:Boolean = false) { super(type, bubbles,cancelable); trackAction = action; trackLabel = label; } public override function clone():Event { return new TrackEvent(type, this.trackAction, this.trackLabel, bubbles, cancelable); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/Frame.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * The Frame class is used to quickly create Rectangle sprites with a line, but no fill * * @example *
* Create a 50x50 frame with a 3-pixel black line. * var frame:Frame = new Frame(50); * * Create a 200x50 frame with a 1-pixel red line. * var frame:Frame = new Frame(200, 50, 0xFF0000, 1); * * @author John Polacek, john@johnpolacek.com */ public class Frame extends Sprite { public function Frame (w:Number, h:Number = 0, color:uint = 0x000000, thickness:int = 3) { var shape:Shape = new Shape(); addChild(shape); shape.graphics.lineStyle(thickness, color, 1, false, LineScaleMode.NONE); shape.graphics.lineTo(w, 0); shape.graphics.lineTo(w, h); shape.graphics.lineTo(0, h); shape.graphics.lineTo(0, 0); shape.x = shape.y = -.5; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/display/ContentDisplay.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.display { import flash.events.Event; import flash.events.IOErrorEvent; import flash.display.Sprite; /** * Abstract class for displaying various types of content (audio, video, images, flash) * in various ways (audio players, image slideshows, etc.) * * @see com.johnpolacek.display.ContentDisplayCreator * * @version * 16 Apr 2010 Improved error handling
* 7 Mar 2010 * @author John Polacek, john@johnpolacek.com */ public class ContentDisplay extends Sprite { public function ContentDisplay() { } /** Dispatches Event.COMPLETE */ public function onLoadComplete(event:Event):void { dispatchEvent(new Event(Event.COMPLETE)); } /** Catches IOError Events for broken filepaths */ public function onIOError(event:IOErrorEvent):void { dispatchEvent(event); trace("ContentDisplay Error: "+event.text); } /** Remove event listeners and clear children */ public function destroy():void { while (this.numChildren > 0) removeChildAt(0); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/Line.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * The Line class is used to quickly create Line sprites * * @example *
* Create a line 700 pixels wide. * var line:Line = new Line(700); * * Create a red line 700 pixels wide with a thickness of 3 pixels * and 50% transparency that is aligned to center. * var line:Line = new Line(700, 3, 0xFF0000, .5, true); * * @author John Polacek, john@johnpolacek.com */ public class Line extends Sprite { public function Line (w:Number, strokeThickness:int = 1, strokeColor:uint = 0x000000, strokeAlpha:Number = 1, alignToCenter:Boolean = false) { var shape:Shape = new Shape(); addChild(shape); if (strokeThickness > 0) shape.graphics.lineStyle(strokeThickness, strokeColor, strokeAlpha, false, LineScaleMode.NONE, null, JointStyle.MITER); shape.graphics.lineTo(w, 0); if (alignToCenter) shape.x -= w/2; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/BitmapNoiseRectangle.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * BitmapNoiseRectangle class is used to quickly create rectangles filled with Bitmap noise * * @example *
* Create a 80x50 rectangle filled with some noise * var noiseRect:BitmapNoiseRectangle = new BitmapNoiseRectangle(80, 50, 2); * * @author John Polacek, john@johnpolacek.com */ /** * @param w Width of rectangle * @param h Width of rectangle * @param n Noise level of rectangle. Default 1 */ public class BitmapNoiseRectangle extends Sprite { public function BitmapNoiseRectangle (w:Number, h:Number, n:Number = 1) { var bmd:BitmapData = new BitmapData(w / 2, h / 2); bmd.noise(1, 0, 0xFFFFFF, BitmapDataChannel.ALPHA, false); var bitmap:Bitmap = new Bitmap(bmd); bitmap.alpha = .04 * n; bitmap.scaleX = bitmap.scaleY = 2; addChild(bitmap); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/ArrowHead.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * ArrowHead class is used to quickly create arrowhead shapes * * @example *
* Create a 10x20 arrowhead shape * var arrowHead:ArrowHead = new ArrowHead(10, 20); * * Create a 10x20 6-pixel thick, red arrowhead shape, * with 50% transparency, aligned to center * var arrowHead:ArrowHead = new ArrowHead(10, 20, 6, 0xFF0000, .5, true); * * @author John Polacek, john@johnpolacek.com */ public class ArrowHead extends Sprite { public function ArrowHead (w:Number, h:Number, strokeThickness:int = 3, strokeColor:uint = 0x000000, strokeAlpha:Number = 1, alignToCenter:Boolean = false) { var line:Shape = new Shape(); line.graphics.lineStyle(strokeThickness, strokeColor); line.graphics.lineTo(w, h/2); line.graphics.lineTo(0, h); line.alpha = strokeAlpha; addChild(line); if (alignToCenter) { line.x = -w/2; line.y = -h/2; } } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/utils/StringUtils.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.utils { /** * Utilities for working with Strings * * @author John Polacek, john@johnpolacek.com */ public class StringUtils { /** Capitalizes the initial character of each word of a given string. */ public static function toTitleCase(str:String):String { var words:Array = str.split(" "); var n:int = words.length; for (var i:int = 0; i < n; i++) { words[i] = toInitialCap(words[i]); } return (words.join(" ")); } /** Capitalizes the initial character of the given string. */ public static function toInitialCap(original:String):String { return original.charAt(0).toUpperCase() + original.substr(1).toLowerCase(); } /** Returns the characters after the last (.) of a given string (e.g. .jpg). */ public static function getFileExtension(fileName:String):String { var ext:String = fileName.substr(fileName.lastIndexOf(".")+1); return ext; } /** Removes line breaks from string and then returns the string. */ public static function removeLineBreaks(txt:String):String { var lineBreaks:RegExp = /\n/g; txt = txt.replace(lineBreaks, ""); return txt; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/ArrowBlock.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * ArrowHead class is used to quickly create arrowhead shapes * * @example *
* Creates an arrow that fits in a square * var arrowBlock:ArrowBlock = new ArrowBlock(10); * * Create a 20x20 3-pixel thick, red arrow, * with 50% transparency, aligned to center * var arrowBlock:ArrowBlock = new ArrowBlock(20, 3, 0xFF0000, .5, true); * * @author John Polacek, john@johnpolacek.com */ public class ArrowBlock extends Sprite { public function ArrowBlock (size:Number, strokeThickness:int = 3, strokeColor:uint = 0x000000, strokeAlpha:Number = 1, alignToCenter:Boolean = false) { var head:Shape = new Shape(); head.graphics.lineStyle(strokeThickness, strokeColor); head.graphics.lineTo(size, 0); head.graphics.lineTo(size, size); head.alpha = strokeAlpha; addChild(head); var line:Shape = new Shape(); line.graphics.lineStyle(strokeThickness, strokeColor); line.graphics.moveTo(0, size); line.graphics.lineTo(size, 0); line.alpha = strokeAlpha; addChild(line); if (alignToCenter) line.x = line.y = head.x = head.y = -size/2; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/events/UIEvent.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.events { import flash.events.Event; /** * A UIEvent object is generated by media display components and can be used * to pass number values (e.g. progress percent) * * @version 4 Apr 2010 * @author John Polacek, john@johnpolacek.com */ public class UIEvent extends Event { /** Number passed via the UIEvent */ public var value:Number; public static const PROGRESS_UPDATE:String = "progressUpdate"; public static const LOAD_COMPLETE:String = "loadComplete"; public static const VOLUME_ADJUST:String = "volumeAdjust"; public static const PLAY_CLICK:String = "playClick"; public static const PAUSE_CLICK:String = "pauseClick"; public static const PLAYBACK_START:String = "playbackStart"; public static const PLAYBACK_FINISH:String = "playbackFinish"; public static const SCROLLBAR_MOVE:String = "scrollbarMove"; public static const BUTTON_SELECT:String = "buttonSelect"; public static const DROPDOWN_SELECT:String = "dropdownSelect"; public static const FULL_SCREEN_CONTENT:String = "fullScreenContent"; public static const FULL_SCREEN_CONTENT_ENTER:int = 1; public static const FULL_SCREEN_CONTENT_EXIT:int = 0; public function UIEvent(type:String, val:Number = 0, bubbles:Boolean = true, cancelable:Boolean = false) { super(type, bubbles,cancelable); value = val; } public override function clone():Event { return new UIEvent(type, this.value, bubbles, cancelable); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/EllipseShape.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * EllipseShape class is used to quickly create Elliptical sprites * * @example *
* Create a 50x50 circle * var circle:EllipseShape = new EllipseShape(50); * * Create a 200x50 ellipse with a 50% transparent black fill, * a 3-pixel red stroke, aligned to center * var ellipse:EllipseShape = new EllipseShape(200, 50, 0x000000, .5, 3, 0xFF0000, 1, true); * * @author John Polacek, john@johnpolacek.com */ public class EllipseShape extends Sprite { public function EllipseShape (w:Number, h:Number = 0, fillColor:uint = 0x000000, fillAlpha:Number = 1, strokeThickness:int = 0, strokeColor:uint = 0x000000, strokeAlpha:Number = 1, alignToCenter:Boolean = false) { var shape:Shape = new Shape(); if (h==0) h = w; addChild(shape); if (strokeThickness > 0) shape.graphics.lineStyle(strokeThickness, strokeColor, strokeAlpha, false, LineScaleMode.NONE, null, JointStyle.MITER); shape.graphics.beginFill(fillColor, fillAlpha); shape.graphics.drawEllipse(alignToCenter ? -w/2 : 0, alignToCenter ? -h/2 : 0, w, h); shape.graphics.endFill(); } public function alignToCenter():void { var shape:Shape = Shape(this.getChildAt(0)); shape.x = -shape.width/2; shape.y = -shape.height/2; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/display/ImageDisplay.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.display { import flash.display.Sprite; import flash.display.Loader; import flash.display.Bitmap; import flash.events.Event; import flash.events.MouseEvent; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.net.URLRequest; import flash.net.navigateToURL; import flash.system.LoaderContext; /** * Loads and displays images. (.jpg, .gif, .png) * * @version * 1 Apr 2010 Added contentInfo object property
* 7 Mar 2010 * @author John Polacek, john@johnpolacek.com */ public class ImageDisplay extends ContentDisplay { /** Object that can be used to store variables */ public var contentInfo = {}; private var imageLoader:Loader = new Loader(); /** * @param filepath url of the image. **/ public function ImageDisplay(filepath:String) { trace("ImageDisplay "+filepath); var loaderContext:LoaderContext = new LoaderContext(); loaderContext.checkPolicyFile = true; imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete); imageLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIOError); //imageLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress); imageLoader.load(new URLRequest(filepath), loaderContext); } /** Enables bitmap smoothing and dispatches Event.COMPLETE */ override public function onLoadComplete(event:Event):void { trace("ImageDisplay.onLoadComplete"); var bit:Bitmap = Bitmap(imageLoader.content); if (bit != null) { addChild(bit); bit.smoothing = true; } dispatchEvent(new Event(Event.COMPLETE)); } } } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #Responsive Video 2 | 3 | jQuery Plugin for a video player that scales to fit its container 4 | 5 | ##How to Use 6 | 7 | Add video element to your html inside a container div that is styled to scale with the size of the browser window 8 | 9 |
10 | 13 |
14 | 15 | First, link to jQuery and then to vidobject.js. Next, create a new vidobject and apply any custom settings to it. Last, use vidobject to target the video element(s) on the page. 16 | 17 | 18 | 19 | 30 | 31 | 32 | Parameters are: 33 | 34 | **player:** path to the vidobject.swf player 35 | **buttonColor:** video controls button color (default is '#FFFFFF') 36 | **accentColor:** video controls accent color (default is '#BBBBBB') 37 | **backgroundColor:** video controls background color (default is '#111111') 38 | **scaleVideo:** set to false if you don't want the video to scale 39 | **fullScreen:** set to false to disable full screen mode 40 | 41 | 42 | Responsive Video Object created by John Polacek 43 | Twitter: http://twitter.com/#!/johnpolacek 44 | Blog: http://johnpolacek.com 45 | -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/RectangleShape.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; /** * RectangleShape class is used to quickly create Rectangle sprites * * @example *
* Create a 50x50 square * var square:RectangleShape = new RectangleShape(50); * * Create a 200x50 rectangle with a 50% transparent black fill, * a 3-pixel red stroke that has 18-pixel rounded corners, aligned to center * var rect:RectangleShape = new RectangleShape(200, 50, 0x000000, .5, 3, 0xFF0000, 1, true, 18); * * @author John Polacek, john@johnpolacek.com */ public class RectangleShape extends Sprite { public function RectangleShape (w:Number, h:Number = 0, fillColor:uint = 0x000000, fillAlpha:Number = 1, strokeThickness:int = 0, strokeColor:uint = 0x000000, strokeAlpha:Number = 1, alignToCenter:Boolean = false, roundedCornerAmount = 0) { var shape:Shape = new Shape(); addChild(shape); if (h==0) h = w; if (strokeThickness > 0) shape.graphics.lineStyle(strokeThickness, strokeColor, strokeAlpha, false, LineScaleMode.NONE, null, JointStyle.MITER); shape.graphics.beginFill(fillColor, fillAlpha); if (roundedCornerAmount == 0) shape.graphics.drawRect(alignToCenter ? -w/2 : 0, alignToCenter ? -h/2 : 0, w, h); else shape.graphics.drawRoundRect(alignToCenter ? -w/2 : 0, alignToCenter ? -h/2 : 0, w, h, roundedCornerAmount); shape.graphics.endFill(); } public function alignToCenter():void { var shape:Shape = Shape(this.getChildAt(0)); shape.x = -shape.width/2; shape.y = -shape.height/2; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/shapes/RectangleGradientShape.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.shapes { import flash.display.GradientType; import flash.display.JointStyle; import flash.display.LineScaleMode; import flash.display.Shape; import flash.display.Sprite; import flash.geom.Matrix; /** * RectangleGradientShape class is used to quickly create Rectangle sprites with simple linear gradients. * * @example *
* Create a 80x50 rectangle gradient with a light gray vertical gradient, * 18-pixel rounded corners and a 2-pixel stroke around it. * var gradRect:RectangleGradientShape = new RectangleGradientShape(80, 50, 0xFFFFFF, 0xCCCCCC, 1, 1, 2, 0xAAAAAA, 1, false, Math.PI/2, 18); * * @author John Polacek, john@johnpolacek.com */ public class RectangleGradientShape extends Sprite { public function RectangleGradientShape (w:Number, h:Number = 0, fillColor1:uint = 0x000000, fillColor2:uint = 0xFFFFFF, fillAlpha1:Number = 1, fillAlpha2:Number = 1, strokeThickness:int = 0, strokeColor:uint = 0x000000, strokeAlpha:Number = 1, alignToCenter:Boolean = false, rotation:Number = Math.PI/2, roundedCornerAmount = 0) { var shape:Shape = new Shape(); addChild(shape); if (h==0) h = w; if (strokeThickness > 0) shape.graphics.lineStyle(strokeThickness, strokeColor, strokeAlpha, false, LineScaleMode.NONE, null, JointStyle.MITER); var colors:Array = [fillColor1, fillColor2]; var alphas:Array = [fillAlpha1, fillAlpha2]; var ratios:Array = [0, 255]; var matr:Matrix = new Matrix(); matr.createGradientBox(w, h, rotation); shape.graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matr); if (roundedCornerAmount == 0) shape.graphics.drawRect(alignToCenter ? -w/2 : 0, alignToCenter ? -h/2 : 0, w, h); else shape.graphics.drawRoundRect(alignToCenter ? -w/2 : 0, alignToCenter ? -h/2 : 0, w, h, roundedCornerAmount); shape.graphics.endFill(); } public function alignToCenter():void { var shape:Shape = Shape(this.getChildAt(0)); shape.x = -shape.width/2; shape.y = -shape.height/2; } } } -------------------------------------------------------------------------------- /css/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | color: #333; 3 | padding: 0; 4 | margin: 0; 5 | font-family: Georgia, serif; 6 | } 7 | 8 | #wrapper { 9 | margin: 0 auto; 10 | padding: 40px 40px 30px; 11 | width: 75%; 12 | text-align: center; 13 | } 14 | 15 | #container { 16 | width: 90%; 17 | background-color: #111; 18 | margin: 0 auto; 19 | } 20 | 21 | /* Remove firefox dotted focus outline */ 22 | a, a:hover, a:active, a:focus, object, embed { 23 | outline: 0; 24 | } 25 | 26 | h1, h2, h3 { 27 | margin: 5px 0; 28 | padding: 0; 29 | } 30 | 31 | h1 a, h2 a { 32 | text-decoration: none; 33 | } 34 | 35 | h1 { 36 | font-size: 40px; 37 | } 38 | 39 | h2 { 40 | font-size: 20px; 41 | } 42 | 43 | h2 small a { 44 | color: #999; 45 | font-weight: normal; 46 | text-decoration: underline; 47 | } 48 | 49 | h3 { 50 | font-size: 20px; 51 | font-weight: normal; 52 | font-style: italic; 53 | } 54 | 55 | h4 { 56 | font-size: 30px; 57 | text-align: center; 58 | } 59 | 60 | a { 61 | font-style: italic; 62 | color: #222; 63 | } 64 | 65 | .demo { 66 | border-top: dashed 1px #ccc; 67 | border-bottom: dashed 1px #ccc; 68 | } 69 | 70 | .demo p { 71 | padding: 20px; 72 | } 73 | 74 | .description { 75 | margin: 30px 0; 76 | } 77 | 78 | .guide { 79 | margin: 30px 0; 80 | } 81 | 82 | .parameters { 83 | list-style: none; 84 | font-size: 14px; 85 | text-align: left; 86 | width: 400px; 87 | margin: 0 auto; 88 | } 89 | 90 | blockquote { 91 | margin: 10px 0; 92 | text-align: left; 93 | padding: 10px 0 10px 20px; 94 | border: solid 1px #ddd; 95 | } 96 | 97 | pre { 98 | white-space: pre-wrap; 99 | white-space: -moz-pre-wrap; 100 | white-space: -pre-wrap; 101 | white-space: -o-pre-wrap; 102 | } 103 | 104 | .thanks { 105 | margin: 80px 0 20px; 106 | } 107 | .download, .github, .authors { 108 | margin: 40px 0 20px; 109 | font-size: 14px; 110 | font-style: italic; 111 | } 112 | 113 | .download-link, .github-link, .author-link { 114 | font-size: 18px; 115 | padding: 10px; 116 | color: #888; 117 | } 118 | 119 | .footer { 120 | border-top: dashed 1px #ccc; 121 | margin: 60px -30px 0; 122 | } 123 | 124 | .footer a, footer a:visited { 125 | color: #bbb; 126 | font-size: 36px; 127 | line-height: 1.6; 128 | padding: 20px; 129 | } 130 | 131 | .footer a:hover { 132 | color: #aaa; 133 | } 134 | 135 | #resize-graphic { 136 | position: fixed; 137 | bottom: 0; 138 | right: 0; 139 | opacity: .6; 140 | } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/ui/BasicButton.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.ui { import flash.display.BlendMode; import flash.display.Sprite; import flash.events.MouseEvent; import com.greensock.TweenLite; import com.greensock.plugins.TweenPlugin; import com.greensock.plugins.ColorTransformPlugin; /** * The BasicButton class is used to create basic buttons that * contain a buttonValue property that can be used to store a string value. * * For example, use BasicButton objects for creating a menu and on * click events use the buttonValue property to load new sections. * Or assign a filename to the buttonValue property to initiate lightbox content. * * By default, BasicButtons have MOUSE_OUT and MOUSE_OVER events * which toggle the transparency between .8(out) and 1(over) which * is deactivated if the select(true); method is called. * * @example * import com.johnpolacek.ui.BasicButton; * import com.johnpolacek.shapes.RectangleShape; * * var exampleButton:BasicButton = new BasicButton("A string stored by the button"); * var buttonShape:Sprite = new RectangleShape(50); * exampleButton.addChild(buttonShape); * * * @author John Polacek, john@johnpolacek.com */ public class BasicButton extends Sprite { public var buttonValue:String; public var baseAlpha:Number = .9; public var rolloverAlpha:Number = 1; public var rolloverColor:String; public var selectColor:String; private var isSelected:Boolean = false; public function BasicButton(val:String = "", enableSimpleRollovers:Boolean = true, ba:Number = .9, ra:Number = 1, rc:String = null, sc:String = null) { TweenPlugin.activate([ColorTransformPlugin]); buttonValue = val; this.buttonMode = true; this.blendMode = BlendMode.LAYER; if (enableSimpleRollovers) addSimpleRollovers(ba, ra, rc, sc); } public function addSimpleRollovers(ba:Number = .9, ra:Number = 1, rc:String = null, sc:String = null):void { baseAlpha = ba; rolloverAlpha = ra; rolloverColor = rc; selectColor = sc; this.alpha = baseAlpha; addEventListener(MouseEvent.MOUSE_OVER,onOver); addEventListener(MouseEvent.MOUSE_OUT,onOut); } private function onOver(event:MouseEvent):void { this.alpha = rolloverAlpha; if (rolloverColor) { TweenLite.to(this, 0, {colorTransform:{tint:uint(rolloverColor)}}); } } private function onOut(event:MouseEvent):void { if (!isSelected) this.alpha = baseAlpha; if (rolloverColor) TweenLite.to(this, 0, {colorTransform:{tintAmount:0}}); } public function select(sel:Boolean = true):void { isSelected = sel; if (isSelected) { this.alpha = rolloverAlpha; if (selectColor) TweenLite.to(this, 0, {colorTransform:{tint:uint(selectColor)}}); } else { this.alpha = baseAlpha; if (selectColor) TweenLite.to(this, 0, {colorTransform:{tintAmount:0}}); } } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/display/VideoDisplay.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.display { import flash.display.Sprite; import flash.display.Loader; import flash.events.Event; import flash.events.IOErrorEvent; import flash.net.URLRequest; import flash.net.navigateToURL; import com.johnpolacek.media.VideoStreamPlayer; /** * Loads and displays video via NetStream (flv and h264) * * @example *
* Basic usage: * import com.johnpolacek.display.VideoDisplay; * var video:VideoDisplay = new VideoDisplay(); * video.loadVideo("example.flv"); * * Example with styling: * * import com.johnpolacek.display.VideoDisplay; * var video:VideoDisplay = new VideoDisplay(); * video.autoPlay = false; * video.autoRewind = true; * video.buttonColor = 0xFFCC99; * video.backgroundColor = 0x333355; * video.loadVideo("example.flv"); * video.addPoster("poster.jpg"); * addChild(video); * * * @see com.johnpolacek.media.VideoStreamPlayer; * @version * 8 Mar 2010 * @author John Polacek, john@johnpolacek.com */ public class VideoDisplay extends ContentDisplay { /** The video player */ public var player:VideoStreamPlayer; /** Boolean for video controls visibility. Default is true. */ public var showControls:Boolean = true; /** Player button color. Default is 0xFFFFFF */ public var buttonColor:uint = 0xFFFFFF; /** Player background color. Default is 0x000000 */ public var backgroundColor:uint = 0x000000; /** Player accent color. Default is 0x000000 */ public var accentColor:uint = 0x999999; /** Default is true. */ public var autoPlay:Boolean = true; /** Default is false. */ public var autoRewind:Boolean = false; /** @param videoURL url of the video. **/ public function VideoDisplay() { player = new VideoStreamPlayer(); player.addEventListener(IOErrorEvent.IO_ERROR, onIOError); } /** @param videoURL url of the video. **/ public function loadVideo(videoURL:String) { player.autoRewind = autoRewind; player.buttonColor = buttonColor; player.backgroundColor = backgroundColor; player.accentColor = accentColor; player.loadVideo(videoURL, autoPlay); if (showControls) player.addController(); player.addEventListener(Event.COMPLETE, onLoadComplete); addChild(player); if (showControls) player.addController(); // adds default controls to player } /** Dispatches Event.COMPLETE */ override public function onLoadComplete(event:Event):void { dispatchEvent(new Event(Event.COMPLETE)); player.removeEventListener(IOErrorEvent.IO_ERROR, onIOError); player.removeEventListener(Event.COMPLETE, onLoadComplete); } /** @param posterURL url of the poster. **/ public function addPoster(posterURL:String):void { player.autoRewind = true; player.autoPlay = false; player.addPoster(posterURL); } override public function destroy():void { if (player) player.destroy(); while (this.numChildren > 0) removeChildAt(0); player = null; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/ui/PlayPauseButton.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.ui { import flash.events.MouseEvent; import flash.display.Shape; import flash.display.Sprite; import com.johnpolacek.events.UIEvent; import com.johnpolacek.shapes.RectangleShape; /** * Play/Pause Toggle Button UI Component * * @sends UIEvent.PAUSE_CLICK # On pause button click * @sends UIEvent.PLAY_CLICK # On play button click * * @author John Polacek, john@johnpolacek.com */ public class PlayPauseButton extends Sprite { private var playIcon:Sprite = new Sprite(); private var pauseIcon:Sprite = new Sprite(); private var playState:Boolean = true; /** * @param w Width (in pixels) of the PlayPauseButton sprite * @param h Height (in pixels) of the PlayPauseButton sprite * @param backgroundColor Background color of the PlayPauseButton sprite. Default 0x000000 * @param buttonColor Button color of the PlayPauseButton sprite. Default 0xFFFFFF */ public function PlayPauseButton(w:Number, h:Number, backgroundColor:uint = 0x000000, buttonColor:uint = 0xFFFFFF) { this.buttonMode = true; this.addEventListener(MouseEvent.CLICK, onClick); this.addEventListener(MouseEvent.MOUSE_OVER, onOver); this.addEventListener(MouseEvent.MOUSE_OUT, onOut); var bgr:Sprite = new RectangleShape(w, h, backgroundColor); var triangle:Shape = new Shape(); triangle.graphics.beginFill(buttonColor); triangle.graphics.lineTo(w/3, h/6); triangle.graphics.lineTo(0, w/3); triangle.graphics.lineTo(0,0); triangle.graphics.endFill(); triangle.x = -triangle.width/2; triangle.y = -triangle.height/2; playIcon.addChild(triangle); var rect1:Sprite = new RectangleShape(w/12, h/3, buttonColor); var rect2:Sprite = new RectangleShape(w/12, h/3, buttonColor); rect1.x = - rect1.width * 1.5; rect2.x = rect1.x + rect1.width * 2; rect1.y = rect2.y = -rect1.height/2; pauseIcon.addChild(rect1); pauseIcon.addChild(rect2); pauseIcon.x = playIcon.x = w/2; pauseIcon.y = playIcon.y = h/2; addChild(bgr); addChild(playIcon); addChild(pauseIcon); pauseIcon.alpha = playIcon.alpha = .9; pauseIcon.visible = false; } /** Toggles play/pause button visibility (does not transmit UIEvent) */ public function toggle():void { pauseIcon.visible = !pauseIcon.visible; playIcon.visible = !pauseIcon.visible; } /** Sets play state. A value of true shows pause button (does not transmit UIEvent) */ public function setPlayState(ps:Boolean):void { playState = ps; if (playState) { pauseIcon.visible = true; playIcon.visible = false; } else { pauseIcon.visible = false; playIcon.visible = true; } } /** Gets play state. A value of true means playback is occuring */ public function getPlayState():Boolean { return playState; } private function onOver(event:MouseEvent):void { pauseIcon.alpha = playIcon.alpha = 1; } private function onOut(event:MouseEvent):void { pauseIcon.alpha = playIcon.alpha = .9; } private function onClick(event:MouseEvent):void { if (playIcon.visible) dispatchEvent(new UIEvent(UIEvent.PLAY_CLICK)); else dispatchEvent(new UIEvent(UIEvent.PAUSE_CLICK)); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/ui/VolumeControl.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.ui { import flash.events.MouseEvent; import flash.display.Sprite; import com.johnpolacek.events.UIEvent; import com.johnpolacek.shapes.RectangleShape; /** * Volume Control UI Component * * @sends UIEvent.VOLUME_ADJUST # Transmits volume percentage value (from 0 to 1) on user interaction * * @author John Polacek, john@johnpolacek.com */ public class VolumeControl extends Sprite { private var container:Sprite = new Sprite(); private var volumeIcon:Sprite = new Sprite(); private var volumeBarsOn:Sprite = new Sprite(); private var volumeBarsOff:Sprite = new Sprite(); private var volumeMask:Sprite = new Sprite(); private var hotSpot:Sprite = new Sprite(); /** * @param w Width (in pixels) of the VolumeControl sprite * @param h Height (in pixels) of the VolumeControl sprite * @param backgroundColor Background color of the VolumeControl sprite. Default 0x000000 * @param buttonColor Button color of the VolumeControl sprite. Default 0xFFFFFF */ public function VolumeControl(w:Number, h:Number, backgroundColor:uint = 0x000000, buttonColor:uint = 0xFFFFFF, accentColor:uint = 0xFFFFFF) { var bgr:Sprite = new RectangleShape(w, h, backgroundColor); var blockSize:Number = h/6; var volumeIconSquare1:RectangleShape = new RectangleShape(blockSize, blockSize, buttonColor); var volumeIconSquare2:RectangleShape = new RectangleShape(blockSize, blockSize * 2, buttonColor); volumeIconSquare2.x = volumeIconSquare1.width + 2; volumeIconSquare2.y = -blockSize/2; volumeIcon.addChild(volumeIconSquare1); volumeIcon.addChild(volumeIconSquare2); for (var i:int = 0; i < 7; i++) { var volumeSquareOff:RectangleShape = new RectangleShape(blockSize, blockSize, buttonColor, .5); volumeSquareOff.x = (blockSize+1)*i; volumeBarsOff.addChild(volumeSquareOff); var volumeSquareOn:RectangleShape = new RectangleShape(blockSize, blockSize, accentColor); volumeSquareOn.x = (blockSize+1)*i; volumeBarsOn.addChild(volumeSquareOn); } volumeMask = new RectangleShape(volumeBarsOn.width, volumeBarsOn.height); volumeBarsOn.x = volumeBarsOff.x = volumeMask.x = blockSize * 3; volumeBarsOn.mask = volumeMask; addChild(bgr); addChild(container); container.addChild(volumeIcon); container.addChild(volumeBarsOff); container.addChild(volumeBarsOn); container.addChild(volumeMask); hotSpot = new RectangleShape(volumeBarsOn.width, h, backgroundColor, 0); hotSpot.x = volumeBarsOn.x + (blockSize * 2.5); container.x = (w - container.width)/2; container.y = (h - blockSize)/2; addChild(hotSpot); hotSpot.addEventListener(MouseEvent.MOUSE_DOWN, onDown); hotSpot.buttonMode = true; trace("h: "+h); trace("height: "+this.height); } /** Sets volume * @param v Volume level between 0 (mute) and 1 (max) */ public function setVolume(v:Number):void { if (v < 0) v = 0; if (v > 1) v = 1; volumeMask.scaleX = v; dispatchEvent(new UIEvent(UIEvent.VOLUME_ADJUST, v)); } private function onDown(event:MouseEvent):void { var newVolume:Number = event.localX/(hotSpot.width*.8); if (newVolume < .2) newVolume = 0; if (newVolume > .9) newVolume = 1; setVolume(newVolume); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/ui/FullScreenButton.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.ui { import flash.events.MouseEvent; import flash.display.Shape; import flash.display.Sprite; import com.johnpolacek.shapes.ArrowBlock; import com.johnpolacek.shapes.EllipseShape; import com.johnpolacek.shapes.Line; import com.johnpolacek.shapes.RectangleShape; /** * FullScreen Toggle Button UI Component * * Requires adding MouseEvent and handler to go full screen * * @author John Polacek, john@johnpolacek.com */ public class FullScreenButton extends Sprite { private var growIcon:Sprite = new Sprite(); private var shrinkIcon:Sprite = new Sprite(); private var fullScreenState:Boolean = false; private var iconSize:Number; private var iconColor:uint; private var blockSize:Number; /** * @param w Width (in pixels) of the PlayPauseButton sprite * @param h Height (in pixels) of the PlayPauseButton sprite. Optimized for 30 pixels. * @param backgroundColor Background color of the PlayPauseButton sprite. Default 0x000000 * @param buttonColor Button color of the PlayPauseButton sprite. Default 0xFFFFFF */ public function FullScreenButton(w:Number, h:Number, backgroundColor:uint = 0x000000, buttonColor:uint = 0xFFFFFF) { this.buttonMode = true; var bgr:Sprite = new RectangleShape(w, h, backgroundColor); buildGrowIcon(w/10); buildShrinkIcon(w/10); growIcon.x = shrinkIcon.x = w/2; growIcon.y = shrinkIcon.y = h/2 - 1; addChild(bgr); addChild(growIcon); addChild(shrinkIcon); shrinkIcon.visible = false; } private function buildGrowIcon(arrowSize:Number):void { var ulArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); ulArrow.rotation = -90; ulArrow.x = -arrowSize * 1.2; ulArrow.y = -arrowSize * 1.2; var urArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); urArrow.x = arrowSize * 1.2; urArrow.y = -arrowSize * 1.2; var llArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); llArrow.rotation = 180; llArrow.x = -arrowSize * 1.2; llArrow.y = arrowSize * 1.2; var lrArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); lrArrow.rotation = 90; lrArrow.x = arrowSize * 1.2; lrArrow.y = arrowSize * 1.2; var center:EllipseShape = new EllipseShape(2, 2, 0xFFFFFF, 1, 0, 0, 0, true); growIcon.addChild(ulArrow); growIcon.addChild(urArrow); growIcon.addChild(llArrow); growIcon.addChild(lrArrow); growIcon.addChild(center); } private function buildShrinkIcon(arrowSize:Number):void { var ulArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); ulArrow.rotation = 90; ulArrow.x = -arrowSize * 1.2; ulArrow.y = -arrowSize * 1.2; var urArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); urArrow.rotation = 180; urArrow.x = arrowSize * 1.2; urArrow.y = -arrowSize * 1.2; var llArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); llArrow.x = -arrowSize * 1.2; llArrow.y = arrowSize * 1.2; var lrArrow:ArrowBlock = new ArrowBlock(arrowSize, 1, 0xFFFFFF, 1, true); lrArrow.rotation = -90; lrArrow.x = arrowSize * 1.2; lrArrow.y = arrowSize * 1.2; var center:EllipseShape = new EllipseShape(2, 2, 0xFFFFFF, 1, 0, 0, 0, true); shrinkIcon.addChild(ulArrow); shrinkIcon.addChild(urArrow); shrinkIcon.addChild(llArrow); shrinkIcon.addChild(lrArrow); shrinkIcon.addChild(center); } /** Toggles full screen display state. */ public function toggleFullScreenState():void { setFullScreenState(!fullScreenState); } /** Sets play state. A value of true shows grow icon. (does not transmit UIEvent) */ public function setFullScreenState(fsState:Boolean):void { fullScreenState = fsState; if (fullScreenState) { growIcon.visible = false; shrinkIcon.visible = true; } else { growIcon.visible = true; shrinkIcon.visible = false; } } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/display/AudioDisplay.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.display { import flash.display.Sprite; import flash.events.Event; import flash.events.IOErrorEvent; import flash.text.Font; import flash.text.TextFormat; import com.johnpolacek.media.AudioPlayer; import com.johnpolacek.media.AudioPlayerMenu; /** * The AudioDisplay class creates audio players that load and * play mp3 files with optional title and subtitle text fields. * Includes a SoundSpectrum class that animates during playback. * * @example * import com.johnpolacek.display.AudioDisplay; * var filepaths:Array = ["example1.mp3","example2.mp3","example3.mp3"]; * var songs:Array = ["Song Title 1","Song Title 2","Song Title 3"]; * var artists:Array = ["Artist Name 1","Artist Name 2","Artist Name 3"]; * var mp3player:AudioDisplay = new AudioDisplay(); * mp3player.loadAudio(filepaths, songs, artists); * addChild(mp3player); * * * @see com.johnpolacek.media.AudioPlayer * @see com.johnpolacek.media.AudioPlayerMenu * @version * 12 Jul 2010 Added autoPlay parameter.
* 16 Apr 2010 Improved error handling
* 30 Mar 2010 AudioPlayers now use TextFormat objects for TextFields
* 27 Mar 2010 Added LightboxContentInfo and LightboxEvent classes
* 7 Mar 2010 * @author John Polacek, john@johnpolacek.com */ public class AudioDisplay extends ContentDisplay { private var players:Array = []; private var playersLoaded:int = 0; public var menu:AudioPlayerMenu; /** The TextFormat for the title TextField. **/ public var titleTextFormat:TextFormat; /** The TextFormat for the subtitle TextField. **/ public var subtitleTextFormat:TextFormat; /** Color of player background. Default is 0x000000 */ public var backgroundColor:uint = 0x000000; /** Color of player buttons. Default is 0xFFFFFF */ public var buttonColor:uint = 0xFFFFFF; /** Player track color. Default is 0x666666 */ public var trackColor:uint = 0x666666; /** Player track alpha. Default is 1 */ public var trackAlpha:Number = 1; /** Width (in pixels) of player. Default is 400 */ public var playerWidth:Number = 400; /** Height (in pixels) of player (not inluding progress bar). Default is 50 */ public var playerHeight:Number = 50; /** If true, top player in menu starts playback on load complete. Default is false */ public var autoPlay:Boolean = false; public function AudioDisplay() { menu = new AudioPlayerMenu(); addChild(menu); } public function loadAudio(urls:Array, titles:Array = null, subtitles:Array = null):void { for (var i:int = 0; i < urls.length; i++) { var player:AudioPlayer = new AudioPlayer(); player.backgroundColor = backgroundColor; player.buttonColor = buttonColor; player.trackColor = trackColor; player.playerWidth = playerWidth; player.playerHeight = playerHeight; player.addEventListener(IOErrorEvent.IO_ERROR, onIOError); if (titleTextFormat) player.titleTextFormat = titleTextFormat; if (subtitleTextFormat) player.subtitleTextFormat = subtitleTextFormat; if (titles) player.titleText = titles[i]; if (subtitles) player.subtitleText = subtitles[i]; players.push(player); player.load(urls[i], false); player.addEventListener(Event.COMPLETE, onAudioLoadComplete); menu.addPlayer(player); } } /** Remove event listeners and clear children */ override public function destroy():void { while (this.numChildren > 0) removeChildAt(0); } //-------------------------------------------------------------------------- // // EVENT HANDLERS // //-------------------------------------------------------------------------- private function onAudioLoadComplete(event:Event):void { event.target.removeEventListener(IOErrorEvent.IO_ERROR, onIOError); event.target.removeEventListener(Event.COMPLETE, onAudioLoadComplete); playersLoaded++; if (playersLoaded == players.length) onLoadComplete(null); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/ui/ProgressBar.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.ui { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.geom.Rectangle; import flash.utils.Timer; import com.johnpolacek.shapes.RectangleShape; import com.johnpolacek.events.UIEvent; /** * ProgressBar UI Component * * @sends UIEvent.PROGRESS_UPDATE # Transmits progress percentage value (from 0 to 1) on user interaction * * @author John Polacek, john@johnpolacek.com */ public class ProgressBar extends Sprite { /** The percent of progress (between 0 and 1) */ public var percent:Number; private var track:Sprite; private var scrub:Sprite; private var backgroundBar:Sprite; private var playProgressBar:Sprite; private var barWidth:Number; private var scrubTimer:Timer; private var scrubBounds:Rectangle; private var isScrubbing:Boolean = false; /** * @param w Width (in pixels) of the ProgressBar sprite * @param h Height (in pixels) of the ProgressBar sprite * @param backgroundColor Background color of the ProgressBar sprite. Default 0x000000 * @param buttonColor Button color of the VolumeControl sprite. Default 0xFFFFFF * @param accentColor Button color of the VolumeControl sprite. Default 0x999999 */ public function ProgressBar(w:Number, h:Number, backgroundColor:uint = 0x000000, buttonColor:uint = 0xFFFFFF, accentColor:uint = 0x999999) { percent = 0; barWidth = w; track = new RectangleShape(w, h, buttonColor, .25, 0, 0, 0, false); scrub = new RectangleShape(h, h, buttonColor); backgroundBar = new RectangleShape(w, h, buttonColor, .25, 0, 0, 0, false); playProgressBar = new RectangleShape(w, h, accentColor, 1, 0, 0, 0, false); backgroundBar.buttonMode = backgroundBar.useHandCursor = true; scrub.buttonMode = scrub.useHandCursor = true; playProgressBar.buttonMode = playProgressBar.useHandCursor = true; addChild(track); addChild(backgroundBar); addChild(playProgressBar); addChild(scrub); backgroundBar.addEventListener(MouseEvent.CLICK, onBarClick); playProgressBar.addEventListener(MouseEvent.CLICK, onProgressClick); scrub.addEventListener(MouseEvent.MOUSE_OVER, onScrubOver); scrub.addEventListener(MouseEvent.MOUSE_OUT, onScrubOut); scrub.addEventListener(MouseEvent.MOUSE_DOWN, onScrubDown); scrubBounds = new Rectangle(scrub.x, scrub.y, barWidth - scrub.width, 0); scrubTimer = new Timer(100); scrubTimer.addEventListener(TimerEvent.TIMER, onScrub); } /** Sets the progress of the bar */ public function setProgress(p:Number):void { percent = p; if (!isScrubbing) scrub.x = scrubBounds.width * percent; if (percent > 0) { playProgressBar.scaleX = percent; playProgressBar.visible = true; } else { playProgressBar.visible = false; } } private function updateProgress(p:Number):void { setProgress(p); dispatchEvent(new UIEvent(UIEvent.PROGRESS_UPDATE, p)); } private function onScrubOver(event:MouseEvent):void { scrub.alpha = 1; } private function onScrubOut(event:MouseEvent):void { scrub.alpha = .75; } private function onScrubDown(event:MouseEvent):void { startScrub(); } private function onScrubUp(event:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_UP, onScrubUp); stage.removeEventListener(Event.MOUSE_LEAVE, onScrubUp); stage.removeEventListener(MouseEvent.MOUSE_MOVE, onScrub); isScrubbing = false; scrub.stopDrag(); } private function startScrub():void { isScrubbing = true; scrub.startDrag(false, scrubBounds); stage.addEventListener(MouseEvent.MOUSE_UP, onScrubUp); stage.addEventListener(Event.MOUSE_LEAVE, onScrubUp); stage.addEventListener(MouseEvent.MOUSE_MOVE, onScrub); } private function onScrub(event:Event):void { updateProgress(scrub.x / scrubBounds.width); } private function onBarClick(event:MouseEvent):void { scrub.x = event.localX; onScrub(null); } private function onProgressClick(event:MouseEvent):void { scrub.x = event.localX * playProgressBar.scaleX; onScrub(null); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/utils/DisplayUtils.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.utils { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.CapsStyle; import flash.display.JointStyle; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.net.URLRequest; import flash.net.navigateToURL; import flash.text.Font; import flash.utils.Timer; /** * Utilities for Display Objects * * @author John Polacek, john@johnpolacek.com */ public class DisplayUtils { /** Removes all children of target sprite. */ public static function removeAllChildren(container:Sprite):void { if (container.numChildren!=0) { var i:int = container.numChildren; while(i--) { container.removeChildAt(i); } } } /** Sets visible property to false for all children of target sprite. */ public static function hideAllChildren(container:Sprite):void { var n:int = container.numChildren; for (var i:int = 0; i < n; i++) { container.getChildAt(i).visible = false; } } /** Scales target sprite to fit within a given width/height */ public static function scaleToFit(target:Sprite, scaleWidth:Number, scaleHeight:Number):void { target.width = scaleWidth; target.height = scaleHeight; if (target.scaleX < target.scaleY) target.scaleY = target.scaleX; else target.scaleX = target.scaleY; } /** Scales target sprite to fill a given width/height */ public static function scaleToFill(target:Sprite, scaleWidth:Number, scaleHeight:Number):void { target.width = scaleWidth; target.height = scaleHeight; if (target.scaleX < target.scaleY) target.scaleY = target.scaleX; else target.scaleX = target.scaleY; } /** Adds rectangle outline to the top level of a target sprite sized to its width/height */ public static function addOutline(target:Sprite, outlineColor = 0x000000, outlineAlpha = .5):void { var outline:Shape = new Shape; outline.graphics.lineStyle(0, outlineColor, outlineAlpha, false, LineScaleMode.NONE, CapsStyle.NONE, JointStyle.MITER, 10); outline.graphics.drawRect(0,0,target.width,target.height); target.addChild(outline); } /** Adds hyperlink to target sprite */ public static function addLink(target:Sprite, url:String, window:String = "_blank") { if (window != "_blank" && window!= "_self") window = "_blank"; target.addEventListener(MouseEvent.CLICK, function():void { navigateToURL(new URLRequest(url), "_blank"); } ); target.buttonMode = true; } /** Adds rectangle shape to bottom level target sprite */ public static function addBackgroundShapeBehind(target:Sprite, backgroundColor = 0x000000, backgroundAlpha = 1):void { var background:Shape = new Shape; background.graphics.beginFill(backgroundColor, backgroundAlpha); background.graphics.drawRect(0, 0, target.width, target.height); background.x = target.x; background.y = target.y; target.parent.addChild(background); target.parent.swapChildren(background, target); } /** Creates a trace output of the names of all fonts embedded at runtime */ public static function traceRuntimeFonts():void { var embeddedFonts:Array = Font.enumerateFonts(false); embeddedFonts.sortOn("fontName", Array.CASEINSENSITIVE); for each (var font:Font in embeddedFonts) { trace("Embedded Font: "+font.fontName); } } /** Creates a trace output of the names of all fonts embedded at runtime */ public static function getRuntimeFonts():Array { var embeddedFonts:Array = Font.enumerateFonts(false); embeddedFonts.sortOn("fontName", Array.CASEINSENSITIVE); var fontNames = []; for each (var font:Font in embeddedFonts) { fontNames.push(font.fontName); } return fontNames; } /** Corrects color codes to flash uintConverts #000000 to 0x000000 */ public static function getColorCodeFromString(colorString:String) :uint { // Credit to Glenn Gervais/rabidGadfly.com for fixColorCode method on which this is based var validColor:String; var pattern:RegExp = /#/; colorString = colorString.replace(pattern,""); pattern = /0x/; if (colorString.substring(0,2) != "0x") validColor = "0x"+colorString; else validColor = colorString; return uint(validColor); } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/media/VidObject.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.media { import flash.display.LoaderInfo; import flash.display.MovieClip; import flash.display.Stage; import flash.display.StageDisplayState; import flash.display.StageScaleMode; import flash.geom.Rectangle; import flash.events.Event; import flash.events.TimerEvent; import flash.external.ExternalInterface; import flash.net.LocalConnection; import flash.utils.Timer; import com.johnpolacek.display.VideoDisplay; import com.johnpolacek.events.UIEvent; import com.johnpolacek.utils.DisplayUtils; /** * VideoObject * * A Flash video player used for embedding video on a web page. * * Use swfobject to embed vidobject.swf on a web page and then pass the * video url through the FlashVars param: * * * * @see com.johnpolacek.display.VideoDisplay * @see com.johnpolacek.display.VideoStreamPlayer * * @version * 29 Mar 2010
* * @author John Polacek, john@johnpolacek.com */ public class VidObject extends MovieClip { private static const BASE_WIDTH:int = 640; private static const BASE_HEIGHT:int = 360; public var trackingEnabled:Boolean = false; public var videoURL:String; public var video:VideoDisplay; public var posterURL:String; private var paramObj:Object; private var videoAutoPlay:Boolean = false; private var videoAutoRewind:Boolean = true; private var aspect:Number; public function VidObject() { stage.scaleMode = StageScaleMode.NO_SCALE; // Get path to domain var domainURL:String = ""; if (ExternalInterface.available) domainURL += ExternalInterface.call("window.location.href.toString"); domainURL = domainURL.substring(0, domainURL.lastIndexOf("/")); domainURL += "/"; // Get parameters and set values var playerButtonColor:uint = 0xFFFFFF; var playerBackgroundColor:uint = 0x111111; var playerAccentColor:uint = 0xBBBBBB; var enableFullScreen:Boolean = true; if (LoaderInfo(this.root.loaderInfo)) { paramObj = LoaderInfo(this.root.loaderInfo).parameters; if (paramObj.video) { videoURL = paramObj.video; // if relative path, make absolute if (videoURL.indexOf("http:") == -1) videoURL = domainURL + videoURL; } if (paramObj.poster) posterURL = paramObj.poster; if (paramObj.tracking && ExternalInterface.available) trackingEnabled = paramObj.tracking=="true"; if (paramObj.buttonColor) playerButtonColor = DisplayUtils.getColorCodeFromString(paramObj.buttonColor); if (paramObj.accentColor) playerAccentColor = DisplayUtils.getColorCodeFromString(paramObj.accentColor); if (paramObj.backgroundColor) playerBackgroundColor = DisplayUtils.getColorCodeFromString(paramObj.backgroundColor); if (String(paramObj.enableFullScreen) == "false") enableFullScreen = false; videoAutoPlay = (String(paramObj.autoPlay) == "true"); videoAutoRewind = (String(paramObj.autoRewind) == "false"); } // Create VideoDisplay video = new VideoDisplay(); video.autoPlay = videoAutoPlay; video.autoRewind = videoAutoRewind; video.backgroundColor = playerBackgroundColor; video.buttonColor = playerButtonColor; video.accentColor = playerAccentColor; video.showControls = true; video.player.autoHideController(); video.player.enableFullScreen(enableFullScreen); video.addEventListener(Event.COMPLETE,onVideoLoadComplete, false, 0, true); if (videoURL) video.loadVideo(videoURL); if (posterURL) video.addPoster(posterURL); addChild(video); video.player.addEventListener(UIEvent.PLAYBACK_START, onPlaybackStart, false, 0, true); video.player.addEventListener(UIEvent.PLAYBACK_FINISH, onPlaybackFinish, false, 0, true); video.player.addEventListener(UIEvent.FULL_SCREEN_CONTENT, onPlayerFullScreen); stage.addEventListener(Event.RESIZE, onStageResize); } private function onPlaybackStart(event:UIEvent):void { if (trackingEnabled && ExternalInterface.available) ExternalInterface.call("pageTracker._trackPageview","/"+videoURL+"/play"); } private function onPlaybackFinish(event:UIEvent):void { if (trackingEnabled && ExternalInterface.available) ExternalInterface.call("pageTracker._trackPageview","/"+videoURL+"/finish"); } /** Repositions video to match actual width/height */ private function onVideoLoadComplete(event:Event):void { if (paramObj.width) { aspect = video.height / video.width; video.width = paramObj.width; video.height = video.width * aspect; } this.x -= (video.width - BASE_WIDTH) / 2; this.y -= (video.height - BASE_HEIGHT) / 2; video.removeEventListener(Event.COMPLETE,onVideoLoadComplete); } private function onPlayerFullScreen(event:UIEvent):void { if (event.value == UIEvent.FULL_SCREEN_CONTENT_ENTER) { stage.displayState = StageDisplayState.FULL_SCREEN; } else { stage.displayState = StageDisplayState.NORMAL; var adjustSizeTimer:Timer = new Timer(200, 1); adjustSizeTimer.addEventListener("timer", function() { updateSize(); }); adjustSizeTimer.start(); } } public function onStageResize(event:Event):void { updateSize(); } /** Scale size of video proportionally */ public function updateSize():void { var newScale = stage.stageWidth/BASE_WIDTH; video.width = BASE_WIDTH * newScale; video.scaleY = video.scaleX; this.x = -((video.width - BASE_WIDTH) / 2); this.y = -((video.height - BASE_HEIGHT) / 2); } } } -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | SimpleVid on GitHub 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Fork me on GitHub 25 | 26 | 27 |
28 | 29 |

30 | SimpleVid
31 |

32 |

by johnpolacek
@johnpolacek

33 | 34 |
35 |

jQuery Plugin for Fluid Video

36 |

Generally it is best to use services like YouTube, Vimeo or a CDN for hosting video, but sometimes it isn’t an option. SimpleVid is a free and easy way to host and embed your own fluid videos. It uses flash to for browsers that don’t support h.264, so you can encode once as a baseline h.264 mp4 and play anywhere.
37 | (Try FitVids.js if your video is on YouTube, etc.)

38 |
39 | 40 |
41 | 44 |
45 | 46 |
47 |

How to Use

48 |

Add video to your html in a container div styled to scale as you like.

49 |

 50 | <div id="container">
 51 |     <video id="myVideo" width="640" height="360" poster="img/poster.jpg" controls>
 52 |         <source src="vid/video.mp4" type="video/mp4"  />
 53 |     </video>
 54 | </div>

55 |

Link to jQuery and then simplevid.js. Then, initialize the plugin with the settings you want. Last, use the plugin to target video elements on the page.

56 |

 57 | <script src="http://code.jquery.com/jquery-1.7.min.js"></script>
 58 | <script src="js/simplevid.js"></script>
 59 | <script>
 60 |     var simplevid = new $.simplevid({
 61 |         player: 'swf/vidobject.swf',
 62 |         buttonColor: '#FFFFFF',
 63 |         accentColor: '#BBBBBB',
 64 |         backgroundColor: '#111111',
 65 |         scaleVideo: true,
 66 |         fullScreen: true
 67 |     });
 68 |     simplevid.embed("myVideo");
 69 | </script>

70 | 71 |

Parameters are:

72 | 80 |
81 | 82 |

83 | Download Plugin: 84 | zip 85 | tar 86 |

87 | 88 |

89 | Thanks to swfobject.js for some code, and Chris Coyier for inspiration. 90 |

91 | 92 |

93 | Other stuff by me: 94 | johnpolacek.github.com 95 |

96 | 97 | 103 |
104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 122 | 123 | 134 | 135 | 136 | 137 | -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/display/ContentDisplayCreator.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.display { import flash.display.Sprite; import flash.display.Shape; import flash.display.LineScaleMode; import flash.display.JointStyle; import flash.events.IOErrorEvent; import com.johnpolacek.utils.StringUtils; import com.johnpolacek.display.AutoSlideShowDisplay; import com.johnpolacek.display.ImageDisplay; import com.johnpolacek.display.VideoDisplay; import com.johnpolacek.display.AudioDisplay; import com.johnpolacek.display.FlashDisplay; /** * A Simple Factory class that constructs ContentDisplay sprites * Uses the ContentCreator simple Factory to generate content containers * * @example * import com.johnpolacek.display.ContentDisplay; * import com.johnpolacek.display.ContentDisplayCreator; * var example:ContentDisplay; * var creator:ContentDisplayCreator = new ContentCreator(); * example = creator.create("video.flv"); * * * @version * 4 Apr 2010 Changed class/package name. Renamed createContent() method to create()
* 29 Mar 2010 Updated contentInfo property names for audio
* 12 Mar 2010 Added contentPath property and background properties for FlashDisplay
* 6 Mar 2010 * @see com.johnpolacek.display.ContentDisplay * @author John Polacek, john@johnpolacek.com */ public class ContentDisplayCreator { private var contentURLs:Array; /** Constant for generating ImageDisplay sprites **/ public static const IMAGE:String = "image"; /** Constant for generating VideoDisplay sprites **/ public static const VIDEO:String = "video"; /** Constant for generating AudioDisplay sprites **/ public static const AUDIO:String = "audio"; /** Constant for generating AutoSlideShowDisplay sprites **/ public static const SLIDESHOW:String = "slideshow"; /** Constant for generating FlashDisplay sprites **/ public static const FLASH:String = "flash"; /** Constant for catching invalid content types **/ public static const INVALID:String = "invalid"; /** Can set to add a path to all createContent calls **/ public var contentPath:String = ""; /** Audio/Video player button color. Default is 0xFFFFFF */ public var playerButtonColor:uint = 0xFFFFFF; /** Audio/Video player accent color. Default is 0x999999 */ public var playerAccentColor:uint = 0xFFFFFF; /** Audio/Video player backgound color. Default: 0x00000000 **/ public var playerBackgroundColor:uint = 0x000000; public var videoAutoPlay:Boolean = true; /** Builds and returns a ContentDisplay sprite * * @param contentURL Filepath to the content * @param contentInfo Object that holds additional values for content. Default is null * @return If content is valid, returns a ContentDisplay sprite **/ public function create(contentURL:String, contentInfo:Object = null) { trace("ContentDisplayCreator.create url:"+contentURL); contentURL = contentURL.replace(" ",""); contentURLs = contentURL.split(","); var contentType:String = getContentType(contentURLs); var contentDisplay:Sprite; if (contentPath!="") { var n:int = contentURLs.length; for (var i:int = 0; i < n; i++) { contentURLs[i] = contentPath + String(contentURLs[i]); } } switch (contentType) { case IMAGE: { contentDisplay = new ImageDisplay(contentURLs[0]); break; } case VIDEO: { var video:VideoDisplay = new VideoDisplay(); video.backgroundColor = playerBackgroundColor; video.buttonColor = playerButtonColor; video.accentColor = playerAccentColor; video.loadVideo(contentURLs[0]); contentDisplay = video; break; } case AUDIO: { var audio:AudioDisplay = new AudioDisplay(); if (contentInfo) { if (!contentInfo.audioTitles) contentInfo.audioTitles = null; if (!contentInfo.audioSubtitles) contentInfo.audioSubtitles = null; if (contentInfo.audioTitleTextFormat) audio.titleTextFormat = contentInfo.audioTitleTextFormat; if (contentInfo.audioSubtitleTextFormat) audio.subtitleTextFormat = contentInfo.audioSubtitleTextFormat; if (contentInfo.audioPlayerHeight) audio.playerHeight = contentInfo.audioPlayerHeight; if (contentInfo.audioPlayerWidth) audio.playerWidth = contentInfo.audioPlayerWidth; audio.backgroundColor = playerBackgroundColor; audio.buttonColor = playerButtonColor; audio.trackColor = playerAccentColor; /////----- DEPRECATED, USE PLAYER PROPERTIES INSTEAD (i.e. playerButtonColor) if (contentInfo.audioBackgroundColor) audio.backgroundColor = contentInfo.audioBackgroundColor; if (contentInfo.audioButtonColor) audio.buttonColor = contentInfo.audioButtonColor; if (contentInfo.audioTrackColor) audio.trackColor = contentInfo.audioTrackColor; ///// audio.loadAudio(contentURLs, contentInfo.audioTitles, contentInfo.audioSubtitles); contentDisplay = audio; } else { audio.loadAudio(contentURLs); } contentDisplay = audio; break; } case SLIDESHOW: { contentDisplay = new AutoSlideShowDisplay(contentURLs); break; } case FLASH: { var flashWidth:Number = 0; var flashHeight:Number = 0; var flashBackgroundAlpha:Number = 0; var flashBackgroundColor:Number = 0xFFFFFF; if (contentInfo) { if (contentInfo.flashWidth) flashWidth = contentInfo.flashWidth; if (contentInfo.flashHeight) flashHeight = contentInfo.flashHeight; if (contentInfo.flashBackgroundColor) flashBackgroundColor = contentInfo.flashBackgroundColor; if (contentInfo.flashBackgroundAlpha) flashBackgroundColor = contentInfo.flashBackgroundAlpha; } contentDisplay = new FlashDisplay(contentURLs[0], flashWidth, flashHeight, flashBackgroundAlpha, flashBackgroundColor); break; } default: { trace("ContentType: "+contentType+" is not valid"); } } trace(contentDisplay + " created"); return contentDisplay; } private function getContentType(contentURLs:Array):String { var contentType:String; var ext:String = StringUtils.getFileExtension(contentURLs[0]); //---------------------------------- // create content for single parameter content types //---------------------------------- if (contentURLs.length == 1) { if (ext=="jpg" || ext=="gif" || ext=="png") contentType = IMAGE; else if (ext=="mov" || ext=="flv" || ext=="mp4") contentType = VIDEO; else if (ext=="mp3") contentType = AUDIO; else if (ext=="swf") contentType = FLASH; else contentType = INVALID; } //---------------------------------- // create content for multiple parameter content types //---------------------------------- else { // slideshow if (ext=="jpg" || ext=="gif" || ext=="png") contentType = SLIDESHOW; else if (ext=="mp3") contentType = AUDIO; else contentType = INVALID; } return contentType; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/ui/FullScreenScrollbar.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.ui { /** * Simple scrollbar class for full screen flash apps * * @example *
* Basic usage, where container sprite on stage is scrolled * import com.johnpolacek.ui.FullScreenScrollbar; * import com.johnpolacek.events.UIEvent; * * scrollbar = new FullScreenScrollbar(); * scrollbar.addEventListener(UIEvent.SCROLLBAR_MOVE, onScroll); * addChild(scrollbar); * * function onScroll(event:UIEvent):void * { * scrollbar.clickPercent = (stage.stageHeight/container.height) * .5; * var maxScroll:Number = container.height - stage.stageHeight + format.margin * 2; * var newY:Number = -(maxScroll * scrollbar.percent); * TweenLite.to(container, .5, {y:newY, ease:Expo.easeOut}); * } * * * To initiate scrolling, use the doScroll method. * For example, a CLICK event that causes the scrollbar to scroll 50%: * button.addEventListener(MouseEvent.CLICK, onClick); * function onClick(event:MouseEvent):void * { * scrollbar.doScroll(.5); * } * * * @see com.johnpolacek.events.UIEvent * @version 4 Apr 2010 * @author John Polacek, john@johnpolacek.com */ import flash.display.BlendMode; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.geom.Rectangle; import flash.ui.Keyboard; import flash.utils.Timer; import com.greensock.TweenLite; import com.greensock.easing.Expo; import com.earthbrowser.ebutils.MacMouseWheelHandler; import com.johnpolacek.shapes.RectangleShape; import com.johnpolacek.events.UIEvent; public class FullScreenScrollbar extends Sprite { /** Percent scrolled (0=none 1=max) **/ public var percent:Number = 0; /** Percent scrolled when track is clicked **/ public var clickPercent:Number = .2; /** When content is tweening, block clicks/scrubbing events **/ public var isTweening:Boolean = false; /** Toggled by transitionIn() and transitionOut() **/ public var isActive:Boolean = false; /** If true, listens for up/down keyboard commands. **/ public var isKeyboardEnabled:Boolean = true; private var scrubber:Sprite; private var track:Sprite; private var scrubberTimer:Timer; //activated when scrubbing, checks for scrub position, more reliable than MOUSE_MOVE private var boundRect:Rectangle; private var thickness:int; private var trackColor:uint; private var trackAlpha:Number; private var scrubberHeight:int; /** * @param scrubberColor Sets color of scrubber. Default is 0xFFFFFF * @param scrubberAlpha Sets alpha of scrubber. Default is .5 * @param tc Sets color of track. Default is 0x000000 * @param ta Sets alpha of track. Default is .25 * @param tc Sets thickness of track. Default is 16 pixels * @param sh Sets height of scrubber. Default is 80 pixels **/ public function FullScreenScrollbar(scrubberColor:uint = 0xFFFFFF, scrubberAlpha:Number = .5, tc:uint = 0x000000, ta:Number = .25, t:int = 16, sh:int = 80) { thickness = t; scrubberHeight= sh; trackColor = tc; trackAlpha = ta; this.visible = false; this.tabChildren = false; track = new RectangleShape(thickness, 100, trackColor, trackAlpha); scrubber = new RectangleShape(thickness, scrubberHeight, scrubberColor, scrubberAlpha); scrubberTimer = new Timer(100,0); track.buttonMode = scrubber.buttonMode=true; addChild(track); addChild(scrubber); addEventListener(Event.ADDED_TO_STAGE, onAddedToStage); } //-------------------------------------------------------------------------- // // Public Methods // //-------------------------------------------------------------------------- /** * Initiates scrolling * * @param p Sets percent to scroll to **/ public function doScroll(p:Number):void { if (p != percent) { isTweening = true; percent = p; if (percent > 1) percent = 1; if (percent < 0) percent = 0; var scrubY:Number = track.y + (percent * (track.height - scrubber.height)); TweenLite.to(scrubber, .5, {y:scrubY, ease:Expo.easeOut, onComplete:tweenComplete}); dispatchEvent(new UIEvent(UIEvent.SCROLLBAR_MOVE)); } } /** * Assigns percentage scrolled on a single track click (clickPercent value) * * @param cp Sets clickPercent value **/ public function setClickPercent(cp:Number):void { clickPercent = cp; } //-------------------------------------------------------------------------- // // Event Handling // //-------------------------------------------------------------------------- private function onAddedToStage(event:Event):void { removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage); track.addEventListener(MouseEvent.MOUSE_DOWN, trackClick); scrubber.addEventListener(MouseEvent.MOUSE_DOWN, scrubberClick); MacMouseWheelHandler.init(stage); stage.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheel); stage.addEventListener(Event.RESIZE, onStageResize); this.x = stage.stageWidth - this.width; if (isKeyboardEnabled) enableKeyCommands(); onStageResize(null); // transitionIn(); } private function mouseWheel(event:MouseEvent):void { if (!isTweening) { var scrollAmount:Number = (-event.delta/12) * track.height; var scrubY:Number = scrubber.y+scrollAmount; if (scrubYtrack.height+track.y) { scrubY=track.height+track.y;//prevent scroll beyond the track } doScroll((scrubY-track.y)/track.height); } } private function scrubberClick(event:MouseEvent):void { if (!isTweening) { scrubber.startDrag(false,boundRect); stage.addEventListener(MouseEvent.MOUSE_UP, scrubberRelease); scrubberTimer.addEventListener(TimerEvent.TIMER, scrubberTimerHandler); scrubberTimer.start(); } } private function trackClick(event:MouseEvent):void { var trackClickPercent:Number = event.localY / event.currentTarget.height * event.currentTarget.scaleY; if (trackClickPercent > percent) doScroll(percent + clickPercent); else doScroll(percent - clickPercent); } private function scrubberTimerHandler(event:Event):void { //check position of scrubber, if changed update scrolling var scrollPos:Number=scrubber.y-track.y; if (percent!=scrollPos/(track.height-scrubber.height)) { percent=scrollPos/(track.height-scrubber.height); dispatchEvent(new UIEvent(UIEvent.SCROLLBAR_MOVE)); } } private function scrubberRelease(event:Event):void { scrubber.stopDrag(); stage.removeEventListener(MouseEvent.MOUSE_UP, scrubberRelease); scrubberTimer.stop(); scrubberTimer.removeEventListener("timer", scrubberTimerHandler); } public function enableKeyCommands():void { if (!stage.hasEventListener(KeyboardEvent.KEY_DOWN)) stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyboard); } public function disableKeyCommands():void { if (stage.hasEventListener(KeyboardEvent.KEY_DOWN)) stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyboard); } private function onKeyboard(event:KeyboardEvent):void { if (event.keyCode == Keyboard.DOWN || event.keyCode == Keyboard.PAGE_DOWN) { doScroll(percent + clickPercent); } if (event.keyCode == Keyboard.UP || event.keyCode == Keyboard.PAGE_UP) { doScroll(percent - clickPercent); } } private function tweenComplete():void { isTweening=false; } public function onStageResize(event:Event):void { this.x = stage.stageWidth - this.width; track.height = stage.stageHeight; scrubber.y = percent * (track.height - scrubber.height); boundRect = new Rectangle(0, track.y, 0, track.height-scrubber.height); } //-------------------------------------------------------------------------- // // Transitions // //-------------------------------------------------------------------------- public function transitionIn():void { this.visible = true; scrubber.x += 45; track.x += 45; TweenLite.to(scrubber, .5, {x:0, ease:Expo.easeOut, delay:.5}); TweenLite.to(track, .5, {x:0, ease:Expo.easeOut, delay:.5}); isActive = true; } public function transitionOut() :void { TweenLite.to(scrubber, .5, {x:45, ease:Expo.easeInOut}); TweenLite.to(track, .5, {x:45, ease:Expo.easeInOut}); isActive = false; } } } -------------------------------------------------------------------------------- /vidobject_source/com/johnpolacek/media/VideoStreamPlayer.as: -------------------------------------------------------------------------------- 1 | package com.johnpolacek.media { import flash.display.DisplayObject; import flash.display.Sprite; import flash.display.Loader; import flash.display.StageDisplayState; import flash.events.Event; import flash.events.IOErrorEvent; import flash.events.AsyncErrorEvent; import flash.events.MouseEvent; import flash.events.TimerEvent; import flash.events.NetStatusEvent; import flash.events.SecurityErrorEvent; import flash.media.SoundTransform; import flash.media.Video; import flash.net.NetConnection; import flash.net.NetStream; import flash.net.URLRequest; import flash.utils.Timer; import com.johnpolacek.display.ImageDisplay; import com.johnpolacek.events.UIEvent; import com.johnpolacek.shapes.RectangleShape; import com.johnpolacek.ui.FullScreenButton; import com.johnpolacek.ui.ProgressBar; import com.johnpolacek.ui.PlayPauseButton; import com.johnpolacek.ui.VolumeControl; /** * * @example * import com.johnpolacek.media.VideoStreamPlayer; * var player:AudioPlayer new VideoStreamPlayer(); * player.playVideo("example.flv"); * player.addController(); // adds default controls to player * player.addPoster("poster.jpg"); * player.autoRewind = true; * player.autoPlay = false; * addChild(player); * * * * @see com.johnpolacek.ui.ProgressBar * @see com.johnpolacek.ui.PlayPauseButton * @see com.johnpolacek.ui.VolumeControl * * @sends Event.COMPLETE # When load is complete. * @sends UIEvent.PLAYBACK_START # When playback starts. * @sends UIEvent.PLAYBACK_FINISH # When playback finishes. * * @version * 20 Mar 2010 Now dispatches UIEvent.PLAYBACK_START
* 19 Mar 2010 Switched poster and controls objects to public vars. Enlarged controls.
* 7 Mar 2010 * @author John Polacek, john@johnpolacek.com */ public class VideoStreamPlayer extends Sprite { /** Color of player buttons. Default is 0xFFFFFF */ public var buttonColor:uint = 0xFFFFFF; /** Color of player background. Default is 0x000000 */ public var backgroundColor:uint = 0x000000; /** Color of player accent color. Default is 0x999999 */ public var accentColor:uint = 0x999999; /** Default is false */ public var autoPlay:Boolean = false; /** Default is true */ public var autoRewind:Boolean = true; /** Optional poster image that displays before video is played */ public var poster:Sprite = new Sprite(); /** Video controls sprite */ public var controls:Sprite = new Sprite(); /** Boolean determines if controller is inside or outside the video. Default is false. */ public var controlsOutside:Boolean = false; /** Video stream */ public var video:Video; private var fullScreenButton:FullScreenButton; private var connection:NetConnection; private var stream:NetStream; private var videoData:Object; private var playControl:PlayPauseButton; private var progressBar:ProgressBar; private var fullScreenMode:Boolean = false; private var volumeControl:VolumeControl; private var controlsEnabled:Boolean = false; private var fullScreenEnabled:Boolean = true; private var isPlaying:Boolean = false; private var progressTimer:Timer; // timer for updating progress bar during playback /** Buffer time for the video in seconds. */// public static const BUFFER_TIME:Number = 8; /** Default volume for player. */// public static const DEFAULT_VOLUME:Number = 0.6; /** Progress update delay in milliseconds. */// public static const PROGRESS_TIMER_DELAY:int = 50; public function VideoStreamPlayer() { connection = new NetConnection(); connection.connect(null); stream = new NetStream(connection); stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, aSyncErrorHandler, false, 0, true); var customClient:Object = new Object(); customClient.onMetaData = metaDataHandler; stream.client = customClient; stream.bufferTime = BUFFER_TIME; video = new Video(); video.attachNetStream(stream); video.smoothing = true; // configure stage // this.visible = false; addChild(video); addChild(poster); addChild(controls); progressTimer = new Timer(PROGRESS_TIMER_DELAY, 0); progressTimer.addEventListener(TimerEvent.TIMER, onProgressTimer, false, 0, true); // configure event listeners // connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false, 0, true); stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true); addEventListener(Event.REMOVED_FROM_STAGE, onRemoved, false, 0, true); poster.addEventListener(MouseEvent.CLICK, onPosterClick, false, 0, true); } //-------------------------------------------------------------------------- // // CONTROLS // //-------------------------------------------------------------------------- /** Loads video from url. * * @param url Video url * @param autoPlay Sets autoPlay boolean */ public function loadVideo(url:String, videoAutoPlay:Boolean = false):void { autoPlay = videoAutoPlay; playVideo(url); if (!autoPlay) rewindVideo(); autoHideController(); } /** Starts playback. * * @param url Video url (only used when no video is loaded) */ public function playVideo(url:String = null):void { if (!url) { if (!videoData) trace("No video loaded."); else resumeVideo(); } else { stream.play(url); isPlaying = true; if (playControl) playControl.setPlayState(true); if (progressBar) progressTimer.start(); } poster.visible = false; } /** Pauses playback. */ public function pauseVideo():void { stream.pause(); if (playControl) playControl.setPlayState(false); progressTimer.stop(); isPlaying = false; } /** Resumes playback. */ public function resumeVideo():void { stream.resume(); if (playControl) playControl.setPlayState(true); if (progressBar) progressTimer.start(); isPlaying = true; poster.visible = false; } /** Returns and pauses playback to start of video. */ public function rewindVideo():void { stream.seek(0); pauseVideo(); poster.visible = true; if (progressBar) progressBar.setProgress(0); } /** Sets playhead to a percentage of the video's duration. * * @param p Percentage of video duration */ public function seekVideo(p:Number):void { stream.seek(p); poster.visible = false; } //-------------------------------------------------------------------------- // // OBJECT CREATION // //-------------------------------------------------------------------------- private function initPlayer():void { this.visible = true; video.height = videoData.height; video.width = videoData.width; if (controlsEnabled && controls.numChildren == 0) createControls(); setControlsPosition(); if (poster.numChildren > 0) { poster.width = videoData.width; poster.height = videoData.height; } dispatchEvent(new Event(Event.COMPLETE)); } private function setControlsPosition():void { if (fullScreenMode) { controls.x = controls.width/2; controls.y = video.y + video.height - controls.height; } else { controls.x = 0; controls.y = video.height; if (!controlsOutside) controls.y -= controls.height; } } public function addPoster(filepath:String):void { var image:ImageDisplay = new ImageDisplay(filepath); poster.addChild(image); poster.buttonMode = true; } public function addController():void { controlsEnabled = true; } public function createControls():void { var bgr:Sprite = new RectangleShape(videoData.width, 30, backgroundColor); var shine:Sprite = new RectangleShape(videoData.width, 15, buttonColor, .1); playControl = new PlayPauseButton(30, 30, backgroundColor, buttonColor); volumeControl = new VolumeControl(80, 30, backgroundColor, buttonColor); volumeControl.x = video.width - volumeControl.width; fullScreenButton = new FullScreenButton(30, 30, backgroundColor, buttonColor); fullScreenButton.x = volumeControl.x - fullScreenButton.width; fullScreenButton.visible = fullScreenEnabled; progressBar = new ProgressBar(video.width - playControl.width - volumeControl.width - fullScreenButton.width - 30, 6, backgroundColor, buttonColor, accentColor); progressBar.x = playControl.width + 15; progressBar.y = (bgr.height - progressBar.height) / 2; progressBar.setProgress(0); controls.addChild(bgr); controls.addChild(playControl); controls.addChild(progressBar); controls.addChild(volumeControl); controls.addChild(fullScreenButton); progressBar.addEventListener(UIEvent.PROGRESS_UPDATE, onProgressBarUpdate, false, 0, true); playControl.addEventListener(UIEvent.PLAY_CLICK, onPlayClick, false, 0, true); playControl.addEventListener(UIEvent.PAUSE_CLICK, onPauseClick, false, 0, true); volumeControl.addEventListener(UIEvent.VOLUME_ADJUST, onVolumeAdjust, false, 0, true); fullScreenButton.addEventListener(MouseEvent.CLICK, onFullScreenClick); volumeControl.setVolume(DEFAULT_VOLUME); if (isPlaying) progressTimer.start(); playControl.setPlayState(isPlaying); } /** Moves controller inside the video player and hides on MOUSE_OUT **/ public function autoHideController():void { controlsOutside = false; controls.y = video.height - controls.height; addEventListener(MouseEvent.MOUSE_OVER, showControls); addEventListener(MouseEvent.MOUSE_OUT, hideControls); if (autoPlay) controls.alpha = 0; } public function destroy():void { stream.pause(); progressBar.removeEventListener(UIEvent.PROGRESS_UPDATE, onProgressBarUpdate); playControl.removeEventListener(UIEvent.PLAY_CLICK, onPlayClick); playControl.removeEventListener(UIEvent.PAUSE_CLICK, onPauseClick); volumeControl.removeEventListener(UIEvent.VOLUME_ADJUST, onVolumeAdjust); stream.removeEventListener(AsyncErrorEvent.ASYNC_ERROR, aSyncErrorHandler); removeEventListener(MouseEvent.MOUSE_OVER, showControls); removeEventListener(MouseEvent.MOUSE_OUT, hideControls); connection.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler); stream.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler); removeEventListener(Event.REMOVED_FROM_STAGE, onRemoved); poster.removeEventListener(MouseEvent.CLICK, onPosterClick); fullScreenButton.removeEventListener(MouseEvent.CLICK, onFullScreenClick); } //-------------------------------------------------------------------------- // // EVENTS HANDLERS // //-------------------------------------------------------------------------- private function netStatusHandler(event:NetStatusEvent):void { if (event.info.code.toString() == "NetStream.Play.Start" && autoPlay) dispatchEvent(new UIEvent(UIEvent.PLAYBACK_START)); if (event.info.code.toString() == "NetStream.Play.Stop") onVideoFinish(); if (event.info.code.toString() == "NetStream.Play.StreamNotFound") dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, false, false, "Video Stream not found")); } private function securityErrorHandler(event:SecurityErrorEvent):void { trace("VideoStreamPlayer securityErrorHandler: " + event); } private function metaDataHandler(data:Object):void { if (data) { videoData = data; initPlayer(); } } private function aSyncErrorHandler(event:AsyncErrorEvent):void { trace(event.text); } private function onRemoved(event:Event):void { stream.close(); } public function onVideoFinish():void { if (autoRewind) rewindVideo(); if (fullScreenMode) toggleFullScreenMode(); dispatchEvent(new UIEvent(UIEvent.PLAYBACK_FINISH)); } private function onPlayClick(event:UIEvent = null):void { dispatchEvent(new UIEvent(UIEvent.PLAYBACK_START)); resumeVideo(); } private function onPauseClick(event:UIEvent = null):void { pauseVideo(); } private function onFullScreenClick(event:MouseEvent):void { toggleFullScreenMode(); } private function toggleFullScreenMode():void { fullScreenButton.toggleFullScreenState(); fullScreenMode = !fullScreenMode; if (fullScreenMode) { dispatchEvent(new UIEvent(UIEvent.FULL_SCREEN_CONTENT, UIEvent.FULL_SCREEN_CONTENT_ENTER)); video.addEventListener(MouseEvent.CLICK, onFullScreenClick); seekVideo(0); if (!isPlaying) onPlayClick(); controls.scaleX = controls.scaleY = 1/(stage.stageWidth/video.width); } else { controls.scaleX = controls.scaleY = 1; dispatchEvent(new UIEvent(UIEvent.FULL_SCREEN_CONTENT, UIEvent.FULL_SCREEN_CONTENT_EXIT)); video.removeEventListener(MouseEvent.CLICK, onFullScreenClick); } setControlsPosition(); } private function onPosterClick(event:MouseEvent):void { if(videoData) playVideo(); } private function onVideoClick(event:MouseEvent):void { if(isPlaying) onPauseClick(); else onPlayClick(); } private function showControls(event:MouseEvent):void { controls.alpha = 1; } private function hideControls(event:MouseEvent):void { controls.alpha = 0; } private function onProgressBarUpdate(event:UIEvent):void { seekVideo(event.value * videoData.duration); } private function onProgressTimer(event:TimerEvent):void { if (videoData) { var p:Number = stream.time / videoData.duration; progressBar.setProgress(stream.time / videoData.duration); } } private function onVolumeAdjust(event:UIEvent):void { var transform:SoundTransform = stream.soundTransform; transform.volume = event.value; stream.soundTransform = transform; } public function enableFullScreen(enable:Boolean):void { if (fullScreenButton) fullScreenButton.visible = enable; fullScreenEnabled = enable; } } } -------------------------------------------------------------------------------- /js/simplevid.js: -------------------------------------------------------------------------------- 1 | /* 2 | vidobject.js 3 | by John Polacek (@johnpolacek) 4 | 5 | Docs: http://johnpolacek.github.com/ResponsiveVideo/ 6 | 7 | License: http://www.opensource.org/licenses/mit-license.php 8 | */ 9 | 10 | (function($) { 11 | 12 | $.simplevid = function(options) { 13 | 14 | // swfobject 2.2 - http://code.google.com/p/swfobject/ 15 | var swfobject = function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y0){for(var af=0;af0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad'}}aa.outerHTML='"+af+"";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab