Version 0.2b :

- Intro Screen
- Share buttons (Twitter/Facebook)
- SoundManager
- Add audio files
- Some CleanUp
This commit is contained in:
Guillaume DE LA RUE 2011-02-13 13:28:40 +01:00
parent 03e56e1ffe
commit 28e7b63568
262 changed files with 27079 additions and 271 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,4 +1,4 @@
/* BASICS */
/* GOOGLE FONT */
.orbitron {
font-family: 'Orbitron', serif;
font-style: normal;
@ -11,6 +11,7 @@
line-height: 1.2;
}
/* Global Container */
.container {
width: 100%;
height: 100%;
@ -110,14 +111,8 @@
height: 68px;
}
/* Ennemies */
/*#game .ennemy { border: 1px solid blue; } */
/* The HUD */
#hud {
z-index: 90;
}
#hud { z-index: 90; display: none; }
#hud #score {
font-size:36px;
@ -138,7 +133,7 @@
font-weight: bold;
text-shadow: 0 0 5px rgba(115, 171, 255, 0.4) ;
position: absolute;
display: block;
display: none;
top:100px;
right: 30px;
}
@ -155,13 +150,53 @@
right: 30px;
}
/* Debug Panel */
/* GameIntro Panel */
#game-intro {
position: absolute;
display: block;
left: 0px;
top: 50%;
margin-top: -150px;
color:#fff;
z-index: 1000;
width:100%;
text-align: center;
}
#game-intro .text {
position: relative;
display: block;
font-size: 64px;
}
#game-intro #start-game {
position: relative;
display: block;
margin: 20px auto;
width: 300px;
-moz-border-radius: 10px;
-webkit-border-radius: 10px;
border-radius: 10px;
border: 5px solid rgba(0,0,0, 0.3);
padding: 15px 0 10px;
font-size: 24px;
background: rgba(0,0,0, 0.1);
}
#game-intro #start-game.hover {
cursor: pointer;
background: rgba(0,0,0, 0.2);
box-shadow: 0 0 20px rgba(27, 161, 255, 0.5) ;
-moz-box-shadow: 0 0 20px rgba(27, 161, 255, 0.5) ;
}
/* GameOver Panel */
#game-over {
position: absolute;
display: none;
left: 0px;
top: 50%;
margin-top: -100px;
margin-top: -150px;
color:#fff;
z-index: 1000;
width:100%;
@ -191,9 +226,34 @@
#game-over #restart-game.hover {
cursor: pointer;
background: rgba(0,0,0, 0.2);
box-shadow: 0 0 10px rgba(27, 161, 255, 0.5) ;
box-shadow: 0 0 20px rgba(27, 161, 255, 0.5) ;
-moz-box-shadow: 0 0 20px rgba(27, 161, 255, 0.5) ;
}
#game-over #share-buttons {
position: relative;
display: block;
text-align: center;
padding: 10px 0;
}
#game-over #share-buttons div {
display: inline-block;
margin: 0 10px;
position: relative;
}
#game-over #share-buttons a {
position: relative;
display: block;
opacity: 0.1;
outline: none;
}
#game-over #share-buttons a img { border:none; outline: none; }
#game-over #share-buttons a:hover { opacity: 0.9; cursor: pointer; }
/* Credits */
#credits {
position: absolute;
@ -207,11 +267,7 @@
font-family: "Lucida Grande", Verdana;
}
#credits a {
text-decoration: none;
color: #1ba1ff;
}
#credits a:hover {
text-decoration: underline;
}
#credits a { text-decoration: none; color: #1ba1ff; }
#credits a:hover { text-decoration: underline; }
#credits a.author { color: #baff58; }
#credits a.quote { color: #fa8100; }

BIN
images/facebook_button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
images/twitter_button.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

View file

@ -4,30 +4,48 @@
xmlns:fb="http://www.facebook.com/2008/fbml">
<head>
<!-- Google Chrome Frame Compatibility -->
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- Facebook Meta Tags -->
<!-- SEO Friendly -->
<title>Wyrian - A clone Game of Tyrian in HTML5</title>
<meta property="og:type" content="game" />
<meta property="og:title" content="Wyrian - A clone Game of Tyrian in HTML5" />
<meta property="og:site_name" content="Wyrian" />
<meta property='og:url' content='http://www.html5place.com/lab/wyrian/' />
<meta property="fb:admins" content="100001668966106,582526084,100001643794747"/>
<meta property="og:description" content="An alpha version clone of the Tyrian Game. Developed during the HTML5 Game Jam 2011 at Paris."/>
<meta name="description" content="Wyrian : An awesome clone Game of Tyrian. Developed during the HTML5 Game Jam 2011 at Paris by Guillaume DE LA RUE." />
<!-- Facebook Meta Tags -->
<meta property="og:type" content="game" />
<meta property="og:title" content="Wyrian - An awesome clone Game of Tyrian in HTML5" />
<meta property="og:site_name" content="Wyrian" />
<meta property="og:url" content="http://www.html5place.com/lab/wyrian/" />
<meta property="og:description" content="Wyrian : An awesome clone Game of Tyrian. Developed during the HTML5 Game Jam 2011 at Paris."/>
<!-- Stylesheets -->
<link rel="stylesheet" media="all" href="css/style.css" />
<link href="http://fonts.googleapis.com/css?family=Orbitron:400,500,700,900" rel="stylesheet" type="text/css" >
</head>
<body>
<!-- Game Intro -->
<div id="game-intro">
<div class="text orbitron">Wyrian</div>
<div id="start-game" class="orbitron">Play</div>
</div>
<!-- Game Over -->
<div id="game-over">
<div class="text orbitron">GAME OVER</div>
<div id="restart-game" class="orbitron">Restart</div>
<div id="share-buttons">
<div class="twitter">
<a href="http://twitter.com/?status=RT%20%40html5place%20%3A%20Wyrian%20-%20An%20awesome%20clone%20Game%20of%20Tyrian%20in%20%23html5%20http%3A%2F%2Fbit.ly%2FgpObfX%20%23pgj2011%20%23game" target="_blank" title="Share on Twitter"><img src="images/twitter_button.png" width="122" height="42"></a>
</div>
<div id="credits" class="">
<strong>HTML5 Game Jam 2011</strong><br>
<strong><a href="https://github.com/glenux/wyrian" target="_blank" title="View Project on GitHub">Wyrian</a> v0.2a</strong> | <a href="http://www.html5place.com/" title="View my Website">Guillaume DE LA RUE</a><br>Thanks to <a href="https://github.com/glenux" target="_blank" title="View profile of Glenux on GitHub">Glenux</a> for design and Matthieu Bosquet and all people presents :)
<div class="facebook">
<a href="http://www.facebook.com/sharer.php?u=http://www.html5place.com/lab/wyrian/" target="_blank" title="Share on Facebook"><img src="images/facebook_button.png" width="122" height="42"></a>
</div>
</div>
</div>
<!-- Scene -->
<div class="container" id="GameContainer">
<div id="background" class="layout"></div>
<div id="ground" class="layout"></div>
@ -50,10 +68,30 @@
</div>
</div>
<!-- The footer... -->
<footer id="credits" class="">
<strong>HTML5 Game Jam 2011</strong><br>
<strong><a href="https://github.com/glenux/wyrian" target="_blank" title="View Project on GitHub" class="game">..:: Wyrian v<span id="version">0.2a</span> ::..</a></strong> | <a href="http://www.html5place.com/" title="View my Website" class="author">Guillaume DE LA RUE</a><br>Thanks to <a href="https://github.com/glenux" target="_blank" title="View profile of Glenux on GitHub" class="quote">Glenux</a> for design and Matthieu Bosquet<br>And everyone present at the HTML5 Game Jam :)
</footer>
<script type="text/javascript" src="js/jquery-1.5.js"></script>
<script type="text/javascript" src="js/require.js"></script>
<!-- Main JS Libs -->
<script type="text/javascript" src="js/libs/jquery-1.5.js"></script>
<script type="text/javascript" src="js/libs/require.js"></script>
<script type="text/javascript" src="js/GameClass.js"></script>
<script type="text/javascript" src="js/Wyrian.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<!-- ANalytics Tracking -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-12891268-4']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

BIN
js/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -68,7 +68,7 @@ app.prototype.log = function(txt) {
app.prototype.loopAnimation = function() {
// -- Search for elements that have to be updated
Wyrian.activeElements = 0 ;
Game.activeElements = 0 ;
for ( var i in Layouts ) {
var _layout = Layouts[i] ;
if ( _layout && _layout.running ) {
@ -77,7 +77,7 @@ app.prototype.loopAnimation = function() {
}
// -- Get level
Level = Math.floor((Wyrian.score||0)/1000) ;
Level = Math.floor((Game.score||0)/1000) ;
// -- Create ennemies if needed
var numEnnemies = 0 ;
@ -90,10 +90,10 @@ app.prototype.loopAnimation = function() {
}
// -- Init loops counter
Wyrian.loops = Wyrian.loops||0 ;
Game.loops = Game.loops||0 ;
// -- Init vars
if ( Wyrian.loops == 0 ) {
if ( Game.loops == 0 ) {
this.frameCount = 0;
this.fps = 0;
this.maxfps = 1 / (FPS / 1000);
@ -111,11 +111,11 @@ app.prototype.loopAnimation = function() {
this.frameCount++;
// -- Increase loop counter
Wyrian.loops++ ;
Game.loops++ ;
// -- Refresh Scores and HUD informations
$('#score span').html(Wyrian.score) ;
$('#activeElements span').html(Wyrian.activeElements) ;
$('#score span').html(Game.score) ;
$('#activeElements span').html(Game.activeElements) ;
$('#fpsCounter span').html(this.fps) ;
}

View file

@ -1,112 +0,0 @@
/**************************************************************************
* Init Game Bootstrap
***************************************************************************/
Wyrian = new app({
'libs': [
'order!jquery.transform-0.9.3.min',
'order!LayoutClass'
],
'layers': [
'order!layouts/BgLayer',
'order!layouts/PlayerLayer',
'order!layouts/Ennemies'
],
'wrapper': $('#GameContainer')
}) ;
// Init Application and bind all games events
jQuery(document).ready(function() {
/**************************************************************************
* Load Dependencies & Create Application
***************************************************************************/
require({
baseUrl: "js/",
urlArgs: "bust=" + Wyrian.version
}, Wyrian.settings.libs,
// -- All objects are loaded => can run
function() {
// -- Init Stage or show IE popup
if ( ! $.browser.msie ) {
Wyrian.init() ;
} else {
$.facebox.settings.opacity = 0.8 ;
$.facebox.settings.closeImage = '/common/img/facebox/apple-close.png' ;
$(document).unbind('close.facebox') ;
$.facebox({ajax: '/popup-ie/'}, 'popup-ie' ) ;
}
}
);
/**************************************************************************
* Game Controls Events
***************************************************************************/
// -- Game is loaded
$(document).bind('gameLoaded', function(e, res) {
if ( timers.loopGame ) clearInterval(timers.loopGame) ;
timers.loopGame = setInterval(Wyrian.loopAnimation, 1000/FPS) ;
});
// -- Init Game
$(document).bind('gameInit', function(e, res) {
$(document).trigger('gameReset') ;
}) ;
// -- Game Reset
$(document).bind('gameReset', function(e, res) {
Wyrian.score = 0 ;
Wyrian.loops = 0 ;
Layouts.Ennemies.els = [] ;
$('.sprite').remove() ;
$.each(Layouts, function(key, val){
Layouts[key].running = true ;
$.each(val.els, function(key2, val2){
if ( Layouts[key].els.length && Layouts[key].els[key2] ) {
Layouts[key].els[key2].x = Layouts[key].els[key2].settings.origin.x ;
Layouts[key].els[key2].y = Layouts[key].els[key2].settings.origin.y ;
}
}) ;
}) ;
if ( timers.loopGame ) clearInterval(timers.loopGame) ;
timers.loopGame = setInterval(Wyrian.loopAnimation, 1000/FPS) ;
}) ;
// -- Start Animation
$(document).bind('gameStart', function(e, res) {
}) ;
// -- On Complete Launch
$(document).bind('gameComplete', function(e, res) {
// -- Stop layouts running
$('.sprite').not('.explosion').remove() ;
Layouts.Ennemies.running = false ;
Layouts.Background.running = false ;
// -- Show game over overlay
$('#game-over:hidden').fadeIn(500) ;
// -- Stop loopAnimation
if ( timers.loopGame ) clearInterval(timers.loopGame) ;
}) ;
// -- Bind Restart Screen controls
$('#game-over #restart-game').click(function() {
$('#game-over:visible').fadeOut(500, function() {
$(document).trigger('gameReset') ;
}) ;
}).hover(function() {
$(this).addClass('hover') ;
}, function() {
$(this).removeClass('hover') ;
}) ;
}) ;

View file

@ -4,13 +4,14 @@ Layouts.Ennemies = new Layout({
// -- Define elements to draw with options
el: [],
images: ['images/sprites/alien_1.png?_=1', 'images/sprites/alien_2.png?_=1', 'images/sprites/explosion-sprite.png' ],
// -- Define current Speed
speed: 7,
direction: 1,
// -- Define canvas parent
dom: $('div#game')
dom: $('div#ground')
}) ;
@ -32,13 +33,13 @@ Layouts.Ennemies.createRandom = function(opts) {
{
width: 80,
height: 80,
imageSrc: 'images/sprites/alien_1.png?_=1',
imageSrc: self.settings.images[0],
sprites: [0,1,2,3]
},
{
width: 80,
height: 80,
imageSrc: 'images/sprites/alien_2.png?_=1',
imageSrc: self.settings.images[1],
sprites: [0]
}
] ;
@ -60,8 +61,8 @@ Layouts.Ennemies.createRandom = function(opts) {
obj.box.hide(0);
obj = self.reinitObj(obj);
Wyrian.score = Wyrian.score || 0 ;
Wyrian.score += obj.settings.power ;
Game.score = Game.score || 0 ;
Game.score += obj.settings.power ;
} ;
alien.animate = function (obj) {
if ( obj.explosing ) {
@ -87,7 +88,7 @@ Layouts.Ennemies.createExplosion = function(object) {
type: 'neutral',
width:330,
height:330,
imageSrc: 'images/sprites/explosion-sprite.png',
imageSrc: self.settings.images[2],
sprites: [0,1,2],
origin: {x: object.x-330/2+object.width/2, y: object.y-330/2+object.height/2},
animate: function(obj) {

View file

@ -34,34 +34,6 @@ var Layout = function(opts) {
return this;
};
// -- Return or set settings
Layout.prototype.option = function(optName, optValue) {
// No params => return all settings
if ( typeof optName == 'undefined' ) return this.settings;
// If optName and optValue set => modify it
else if ( typeof optValue != 'undefined' ) this.settings[optName] = this.settings ;
// In other cases, simply return the setting value
else return this.settings[optName] ;
};
// -- Return an object by name
Layout.prototype.getObj = function(name) {
this.cache = this.cache || {} ;
if ( this.cache[name] ) return this.cache[name] ;
for ( var i in this.els ) {
if ( this.els[i].settings.name == name ) {
this.cache[name] = this.els[i] ;
return this.cache[name] ;
}
}
}
// -- Update elements into layout
Layout.prototype.update = function() {
for ( var j in this.els ) {
@ -100,7 +72,7 @@ Layout.prototype.createObj = function(opts) {
// -- Store options
this.parent = self ;
this.name = settingsObj.name || 'default' ;
this.id = settingsObj.id || 'element_'+Wyrian.uniqId++ ;
this.id = settingsObj.id || 'element_'+Game.uniqId++ ;
this.width = settingsObj.width ? settingsObj.width : self.width ;
this.height = settingsObj.height ? settingsObj.height : self.height ;
this.settings = settingsObj ;
@ -118,36 +90,42 @@ Layout.prototype.createObj = function(opts) {
// -- Create a DOM object
this.box = $('#'+this.id) ;
this.dynamic = false ;
this.cssObj = {} ;
if ( ! this.box.length ) {
this.box = $('<div>', {
class:'sprite '+this.name,
id: this.id,
css:{
id: this.id
}) ;
this.cssObj = {
position: 'absolute',
display: 'block',
top: 0,
left: 0,
display: 'block',
backgroundColor: settingsObj.backgroundColor,
backgroundRepeat: settingsObj.backgroundRepeat,
backgroundPosition: settingsObj.backgroundPosition,
backgroundImage: settingsObj.imageSrc ? 'url('+settingsObj.imageSrc+')' : ''
}
}).appendTo(self.dom) ;
} else {
this.box.show(0) ;
} ;
this.dynamic = true ;
}
// -- Apply CSS
this.box.css({
width: this.width,
height: this.height
}) ;
this.cssObj.width = this.width ;
this.cssObj.height = this.height ;
// -- Move
if ( ! this.settings.nomove ) {
this.box.transform({'translate': this.x+'px, '+this.y+'px'}) ;
this.cssObj.translate = this.x+'px, '+this.y+'px' ;
}
// -- Apply CSS Append and display
this.box.css(this.cssObj) ;
if ( this.dynamic ) this.box.appendTo(self.dom) ;
} ;
// -- Init
@ -163,14 +141,14 @@ Layout.prototype.createObj = function(opts) {
// -- Draw object into scene
Obj.prototype.draw = function() {
if ( (this.y >= -2*this.height) && (this.y <= (Wyrian.height+this.height)) && this.x >= -this.width && this.x <= (Wyrian.width+this.width) ) {
if ( (this.y >= -2*this.height) && (this.y <= (Game.height+this.height)) && this.x >= -this.width && this.x <= (Game.width+this.width) ) {
Wyrian.activeElements++ ;
Game.activeElements++ ;
// -- Set sprite to display
if ( this.settings.sprites ) {
this.lastSprite = this.lastSprite || 0 ;
if ( (Wyrian.loops%(this.settings.spriteMod||1)) == 0 ) this.lastSprite++ ;
if ( (Game.loops%(this.settings.spriteMod||1)) == 0 ) this.lastSprite++ ;
if ( typeof this.settings.sprites[this.lastSprite] == 'undefined' ) this.lastSprite = 0 ;
this.box.css({'backgroundPosition': -1*this.settings.sprites[this.lastSprite]*this.settings.width+'px 0'}) ;
}
@ -270,7 +248,7 @@ Layout.prototype.createObj = function(opts) {
this.settings.explode(this) ;
}
Wyrian.log('█▬█ █ ▀█▀') ;
Game.log('█▬█ █ ▀█▀') ;
}
}

View file

@ -11,8 +11,8 @@ Layouts.Player = new Layout({
type: 'human',
sprites: [0,1],
origin: {
x: Wyrian.width/2 - 80,
y: Wyrian.height-220
x: Game.width/2 - 80,
y: Game.height-220
},
fireInterval: 300,
explode: function(obj) {
@ -24,23 +24,23 @@ Layouts.Player = new Layout({
animate: function(obj) {
// -- KEY up /down
if ( Wyrian.input.keyboard.up ) {
if ( Game.input.keyboard.up ) {
if ( obj.y > 0 ) obj.y -= obj.parent.settings.speed ;
}
if ( Wyrian.input.keyboard.down && (obj.y < (Wyrian.height-obj.height) ) ) {
if ( Game.input.keyboard.down && (obj.y < (Game.height-obj.height) ) ) {
obj.y += obj.parent.settings.speed;
}
// -- Left/Right move : choose sprite sequence to display
if ( Wyrian.input.keyboard.left && (obj.x > 0)) {
if ( Game.input.keyboard.left && (obj.x > 0)) {
obj.x -= obj.parent.settings.speed;
}
if ( Wyrian.input.keyboard.right && (obj.x < Wyrian.width-obj.width) ) {
if ( Game.input.keyboard.right && (obj.x < Game.width-obj.width) ) {
obj.x += obj.parent.settings.speed;
}
// -- Press Space : fire
if ( Wyrian.input.keyboard.space ) {
if ( Game.input.keyboard.space ) {
obj.parent.fire(obj) ;
}
@ -56,7 +56,7 @@ Layouts.Player = new Layout({
animate: function(obj) {
obj.settings.spriteMod = 3 ;
obj.settings.sprites = [0,1] ;
if ( Wyrian.input.keyboard.up ) {
if ( Game.input.keyboard.up ) {
obj.settings.sprites = [2,3,4] ;
}
}
@ -124,7 +124,7 @@ Layouts.Player.bulletLib = function(obj, bulletType) {
if ( obj.deleteAfter ) return false;
if ( obj.explosing ) {
Wyrian.log(obj) ;
Game.log(obj) ;
return false ;
}
obj.y += obj.settings.speed*obj.settings.direction ;

View file

@ -0,0 +1,98 @@
== SoundManager 2: JavaScript Sound for the Web
By wrapping and extending HTML5 and Flash Audio APIs, SoundManager 2 brings reliable cross-platform audio to JavaScript.
== HTML5 Audio() Support (Beta-ish)
* 100% Flash-free MP3 + MP4/AAC where supported, compatible with Apple iPad 3.2, iPhone/iOS 4
* Fallback to Flash for MP3/MP4 support, as needed
* SM2 API is unchanged, transparent; HTML5/flash switching handled internally
* HTML5 API support approximates Flash 8 API features, minus ID3, plus buffering
* Some other formats (WAV/OGG) supported via HTML5, depending on browser
* See soundManager.useHTML5Audio for implementation details.
== Basic API Features (Flash 8)
* Load, stop, play, pause, mute, seek, pan and volume control of sounds from Javascript
* Events: onload, whileloading, whileplaying, onfinish and more
* ID3V1 and ID3V2 tag support for MP3s (title, artist, genre etc.)
== Shiny Flash 9 Features
* RTMP / Flash Media Server streaming support (new, experimental)
* MPEG-4 (AAC, HE-AAC, H.264) audio support
* "MultiShot" play (layered/chorusing effects)
* Waveform/frequency spectrum data
* Peak (L/R channel volume) data
* Audio buffering state/event handling
== General Tech Stuff
* Full API Documentation with examples and notes
* console.log()-style debug output and troubleshooting tools
* Community-based discussion/support
== As heard on The Internets
A few nifty sites that have implemented SM2 for driving audio:
* Muxtape
* SoundCloud / The Cloud Player
* 8tracks
* Last.fm
* Opera (media player component)
* Discogs
* Mixcrate
== Project home, documentation, live demos etc.:
http://www.schillmania.com/projects/soundmanager2/
== Merged fork ( kjvarga: http://github.com/kjvarga/SoundManager2/ )
This SM2 fork contains the SoundManager2 implementation that is used on http://www.kazaa.com.
We added RTMP support to SM2 which is now part of the SM2 (experimental) branch as of V2.96a.20100606.
Downloads: http://www.schillmania.com/projects/soundmanager2/doc/download/
For more background on the addition of RTMP check out http://getsatisfaction.com/schillmania/topics/soundmanager_doesnt_support_rtmp
Our old branch of development has been moved to http://github.com/kjvarga/SoundManager2/tree/pre_merge.
== Changes
In addition to the documented SM2 options, we have added the following.
New options to SM2:
* <tt>ondebuglog</tt> callback called with every debugging message. Useful if you need to programatically have access to the debug logs. We use this in our automated reporting of stream failures for QA.
New options to createSound:
* <tt>bufferTimes</tt> optional array of buffer times for double/multiple-buffering. Just specify an array of incrementing buffer sizes (in seconds) e.g. [0.5, 2, 8] for a half-second, then 2 second, then 8 second buffer. Buffers increment when full and reset to the smallest buffer when empty, or when starting to play an unbuffered portion of the stream.
* <tt>onstats</tt> callback called with statistics including how long it took to connect to the server, and how long it took to play (useful for QA).
Our FMS server has some peculiarities that we have to deal with:
* bytesLoaded is always 0 for a streaming sound
* NetStream.Play.Stop is sent when it shouldn't
* We cannot get the stream length using a typical <tt>getStreamLength</tt> call
* We cannot get bandwidth information
== Debugging
1. Set <tt>soundManager.debugFlash = true;</tt>
2. Use a debug version of the SWF e.g. soundmanager2_flash9_debug.swf
3. Open the Flash IDE. Open the SM2 source code files. Start a remote debugging session.
4. Refresh the application in the browser (make sure caching is off).
5. The SWF should connect to Flash and allow you to step through the source.
If it doesn't:
1. Make sure that the Flash version you have installed supports debugging
2. Make sure that the Flash debugger application is using the same version of Flash.
== SM2
Project home, documentation, live demos etc.:
http://www.schillmania.com/projects/soundmanager2/

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 445 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 333 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 501 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 B

View file

@ -0,0 +1,100 @@
/* larger canvas, spectrum + EQ visualization and other items */
.ui360,
.sm2-360ui {
/* size of the container for the circle, etc. */
width:256px;
height:256px;
}
.ui360 {
position:relative;
/* a little extra spacing */
padding-top:1px;
padding-bottom:1px;
margin-bottom:-18px; /* approximate "line height" we want */
padding-left:248px;
margin-left:0px;
background-position:22.6% 50%; /* (~109px) initial play button position */
}
.ui360 a {
font:14px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
white-space:nowrap;
line-height:256px;
}
.sm2-360ui {
margin-left:-256px;
}
.ui360 .sm2-timing {
line-height:256px;
}
.ui360 .sm2-timing {
font:bold 24px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
color:#333;
text-align:center;
line-height:256px;
text-indent:0px;
}
.sm2-inline-list .ui360,
.sm2-inline-list .sm2-360ui {
margin-left:0px;
}
.sm2-inline-list .ui360 {
margin:8px 13px 7px 0px;
padding-left:0px;
background-position:50% 50%; /* initial play button position */
}
.sm2-inline-list .sm2-360ui {
border:1px solid #eee;
/* offset the border */
margin-left:-1px;
margin-top:-1px;
}
.sm2-inline-list .ui360 a {
position:absolute;
display:inline;
left:0px;
bottom:0px;
width:100%; /* 2px padding in box */
height:100%;
*height:256px; /* IE is dumb. */
overflow:hidden;
font-size:small;
font-weight:300;
color:#333;
margin:0px;
padding:0px;
line-height:488px; /* bottom vertical alignment for text */
*line-height:480px; /* IE again */
text-align:center;
-moz-border-radius:0px;
-khtml-border-radius:0px;
border-radius:0px;
}
.sm2-inline-list .ui360:hover {
background-color:#fbfbfb;
}
.sm2-inline-list .ui360 a.sm2_link:hover,
.sm2-inline-list .ui360 a:focus,
.sm2-inline-list .ui360 a:active {
background-color:transparent;
}
/* Use a bigger loading image for this layout */
.ui360:hover .sm2-360btn-default {
background:transparent url(360-button-play-light.png) no-repeat 50% 50%;
_background:transparent url(360-button-play.gif) no-repeat 50% 50%;
cursor:pointer;
}

View file

@ -0,0 +1,251 @@
/* General warning: Beta-ish. Code could be a bit cleaner. */
.ui360,
.sm2-360ui {
/* size of the container for the circle, etc. */
width:50px;
height:50px;
}
.ui360 {
position:relative;
/* a little extra spacing */
padding-top:1px;
padding-bottom:1px;
margin-bottom:-18px; /* approximate "line height" we want */
padding-left:42px; /* 50px, with a few off - margin used for visualization UI */
width:auto;
}
.ui360,
.ui360 * {
position:relative;
vertical-align:middle;
}
.ui360 a {
line-height:50px;
}
.sm2-360ui {
position:relative;
display:inline-block; /* firefox 3 et al */
float:left; /* firefox 2 needs this, inline-block would work with fx3 and others */
*float:left; /* IE 6+7 */
*display:inline;
*clear:left;
margin-left:-50px;
}
.sm2-360ui.sm2_playing,
.sm2-360ui.sm2_paused {
/* bump on top when active */
z-index:10;
}
.ui360 a.sm2_link { /* this class added to playable links by SM2 */
position:relative;
}
.ui360 a {
color:#000;
text-decoration:none;
}
.ui360 a,
.ui360 a:hover,
.ui360 a:focus {
padding:2px;
margin-left:-2px;
margin-top:-2px;
}
.ui360 a:hover,
.ui360 a:focus {
background:#eee;
-moz-border-radius:3px;
-webkit-border-radius:3px;
-khtml-border-radius:3px;
border-radius:3px;
outline:none;
}
.ui360 .sm2-canvas {
position:absolute;
left:0px;
top:0px;
}
.ui360 .sm2-timing {
position:absolute;
display:block;
left:0px;
top:0px;
width:100%;
height:100%;
margin:0px;
font:11px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
color:#666;
text-align:center;
line-height:50px;
}
.ui360 .sm2-timing.alignTweak {
text-indent:1px; /* devious center-alignment tweak for Safari (might break things for others.) */
}
.ui360 .sm2-cover {
position:absolute;
left:0px;
top:0px;
width:100%;
height:100%;
z-index:2;
display:none;
}
.ui360 .sm2-360btn {
position:absolute;
top:50%;
left:50%;
width:22px;
height:22px;
margin-left:-11px;
margin-top:-11px;
cursor:pointer;
z-index:3;
}
.ui360 .sm2-360btn-default {
}
.ui360 .sm2-360data {
display:inline-block;
font-family:helvetica;
}
.ui360 .sm2-360ui.sm2_playing .sm2-cover,
.ui360 .sm2-360ui.sm2_paused .sm2-cover {
display:block;
}
/* this could be optimized a fair bit. */
.ui360,
.ui360 .sm2-360btn-default {
background:transparent url(360-button-play.png) no-repeat 50% 50%;
_background:transparent url(360-button-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */
cursor:pointer;
}
.ui360 {
/*
"fake" button shown before SM2 has started, non-JS/non-SM2 case etc.
background image will be removed via JS, in threeSixyPlayer.init()
*/
background-position:6px 50%;
}
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
background:transparent url(360-button-play.png) no-repeat 50% 50%;
_background:transparent url(360-button-play.gif) no-repeat 50% 50%;
cursor:pointer;
}
.ui360 .sm2-360btn-default:hover,
.ui360 .sm2-360ui.sm2_paused .sm2-360btn:hover {
background:transparent url(360-button-play-light.png) no-repeat 50% 50%;
_background:transparent url(360-button-play.gif) no-repeat 50% 50%;
cursor:pointer;
}
.ui360 .sm2-360ui.sm2_playing .sm2-360btn:hover,
.ui360 .sm2-360btn-playing:hover {
background:transparent url(360-button-pause-light.png) no-repeat 50% 50%;
_background:transparent url(360-button-pause-light.gif) no-repeat 50% 50%;
cursor:pointer;
}
.ui360 .sm2-360ui.sm2_playing .sm2-timing {
visibility:visible;
}
.ui360 .sm2-360ui.sm2_buffering .sm2-timing {
visibility:hidden;
}
.ui360 .sm2-360ui .sm2-timing,
.ui360 .sm2-360ui .sm2-360btn:hover + .sm2-timing,
.ui360 .sm2-360ui.sm2_paused .sm2-timing {
visibility:hidden;
}
.ui360 .sm2-360ui.sm2_dragging .sm2-timing,
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover + .sm2-timing {
/* paused + dragging */
visibility:visible;
}
.ui360 .sm2-360ui.sm2_playing .sm2-360btn,
x.ui360 .sm2-360btn-playing,
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn,
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn:hover,
.ui360 .sm2-360ui.sm2_dragging .sm2-360btn-playing:hover {
/* don't let pause button show on hover when dragging (or paused and dragging) */
background:transparent;
cursor:auto;
}
.ui360 .sm2-360ui.sm2_buffering .sm2-360btn,
.ui360 .sm2-360ui.sm2_buffering .sm2-360btn:hover {
background:transparent url(icon_loading_spinner.gif) no-repeat 50% 50%;
opacity:0.5;
visibility:visible;
}
/* inline list style */
.sm2-inline-list .ui360,
.sm2-inline-block .ui360 {
position:relative;
display:inline-block;
float:left;
_display:inline;
margin-bottom:-15px;
}
.sm2-inline-list .ui360 {
margin-bottom:0px;
}
.sm2-inline-block .ui360 {
margin-right:8px;
}
.sm2-inline-list .ui360 a {
display:none;
}
/* annotations */
ul.ui360playlist {
list-style-type:none;
}
ul.ui360playlist,
ul.ui360playlist li {
margin:0px;
padding:0px;
}
div.ui360 div.metadata {
display:none;
}
div.ui360 a span.metadata,
div.ui360 a span.metadata * {
/* name of track, note etc. */
vertical-align:baseline;
}

View file

@ -0,0 +1,125 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>360&deg; MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization, basic example</title>
<meta name="description" content="Basic example of 360-degree circular control for MP3 links, with EQ and spectrum visualization options" />
<!-- demo: make the fonts nicer etc. -->
<link rel="stylesheet" type="text/css" href="../index.css" />
<!-- soundManager.useFlashBlock: related CSS -->
<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />
<!-- required -->
<link rel="stylesheet" type="text/css" href="360player.css" />
<link rel="stylesheet" type="text/css" href="360player-visualization.css" />
<!-- special IE-only canvas fix -->
<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->
<!-- Apache-licensed animation library -->
<script type="text/javascript" src="script/berniecode-animator.js"></script>
<!-- the core stuff -->
<script type="text/javascript" src="../../script/soundmanager2.js"></script>
<script type="text/javascript" src="script/360player.js"></script>
<script type="text/javascript">
soundManager.url = '../../swf/'; // path to directory containing SM2 SWF
soundManager.useFastPolling = true; // increased JS callback frequency, combined with useHighPerformance = true
threeSixtyPlayer.config.scaleFont = (navigator.userAgent.match(/msie/i)?false:true);
threeSixtyPlayer.config.showHMSTime = true;
// enable some spectrum stuffs
threeSixtyPlayer.config.useWaveformData = true;
threeSixtyPlayer.config.useEQData = true;
// enable this in SM2 as well, as needed
if (threeSixtyPlayer.config.useWaveformData) {
soundManager.flash9Options.useWaveformData = true;
}
if (threeSixtyPlayer.config.useEQData) {
soundManager.flash9Options.useEQData = true;
}
if (threeSixtyPlayer.config.usePeakData) {
soundManager.flash9Options.usePeakData = true;
}
// favicon is expensive CPU-wise, but can be enabled.
threeSixtyPlayer.config.useFavIcon = false;
</script>
<link rel="stylesheet" type="text/css" href="demo.css" />
<style type="text/css">
#left h2 {
padding-top:0px;
margin-bottom:0.25em;
color:#666;
}
pre.block {
margin-top:0.5em;
}
/* special case */
#left {
width:auto;
max-width:100%;
}
</style>
</head>
<body>
<div id="left">
<h1><a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360&deg; Player Demo</a> - Visualization Example, Basic Template</h1>
<p class="note" style="color:#666;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: No EQ/spectrum support for IE (too slow.) Data not available in HTML5.</b></p>
<div style="clear:left"></div>
<div id="sm2-container">
<!-- sm2 flash goes here -->
</div>
<!-- here are the MP3 links, which are decorated with the 360 canvas element/UI etc. -->
<h2 style="margin-top:1em">Inline list</h2>
<div class="sm2-inline-list"> <!-- remove this class to have one item per line -->
<div class="ui360"><a href="../../demo/mpc/audio/CRASH_1.mp3">Crash 1</a></div>
<div class="ui360"><a href="../../demo/mpc/audio/CRASH_5.mp3">Crash 5</a></div>
<div class="ui360"><a href="../../demo/mpc/audio/CRASH_6.mp3">Crash 6</a></div>
<div class="ui360"><a href="../../demo/mpc/audio/CHINA_1.mp3">China 1</a></div>
</div>
<h2 style="clear:both;padding-top:1em">Block list</h2>
<div>
<div class="ui360"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: LOUD)</a></div>
<div class="ui360"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: LOUD)</a></div>
</div>
</div>
<p style="margin-left:1em">
<a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)
</p>
</div>
</body>
</html>

View file

@ -0,0 +1,334 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>360&deg; MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization</title>
<meta name="description" content="Javascript + Canvas + SoundManager 2: 360-degree circular control / jog wheel example for playing MP3 links, with EQ and spectrum visualization options" />
<!-- demo, make the fonts nicer etc. -->
<link rel="stylesheet" type="text/css" href="../index.css" />
<!-- soundManager.useFlashBlock: related CSS -->
<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />
<!-- required -->
<link rel="stylesheet" type="text/css" href="360player.css" />
<link rel="stylesheet" type="text/css" href="360player-visualization.css" />
<!-- special IE-only canvas fix -->
<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->
<!-- Apache-licensed animation library -->
<script type="text/javascript" src="script/berniecode-animator.js"></script>
<!-- the core stuff -->
<script type="text/javascript" src="../../script/soundmanager2.js"></script>
<script type="text/javascript" src="script/360player.js"></script>
<script type="text/javascript">
soundManager.url = '../../swf/'; // path to directory containing SM2 SWF
soundManager.useFastPolling = true; // increased JS callback frequency, combined with useHighPerformance = true
threeSixtyPlayer.config.scaleFont = (navigator.userAgent.match(/msie/i)?false:true);
threeSixtyPlayer.config.showHMSTime = true;
// enable some spectrum stuffs
threeSixtyPlayer.config.useWaveformData = true;
threeSixtyPlayer.config.useEQData = true;
// enable this in SM2 as well, as needed
if (threeSixtyPlayer.config.useWaveformData) {
soundManager.flash9Options.useWaveformData = true;
}
if (threeSixtyPlayer.config.useEQData) {
soundManager.flash9Options.useEQData = true;
}
if (threeSixtyPlayer.config.usePeakData) {
soundManager.flash9Options.usePeakData = true;
}
// favicon is expensive CPU-wise, but can be used.
if (window.location.href.match(/hifi/i)) {
threeSixtyPlayer.config.useFavIcon = true;
}
if (window.location.href.match(/html5/i)) {
// for testing IE 9, etc.
soundManager.useHTML5Audio = true;
}
</script>
<!-- DEMO only, customization UI: Yahoo! YUI colorpicker stuff -->
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/slider/assets/skins/sam/slider.css" />
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.7.0/build/colorpicker/assets/skins/sam/colorpicker.css" />
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/animation/animation-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/dragdrop/dragdrop-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/slider/slider-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/element/element-min.js"></script>
<script type="text/javascript" src="http://yui.yahooapis.com/2.7.0/build/colorpicker/colorpicker-min.js"></script>
<link rel="stylesheet" type="text/css" href="demo.css" />
<style type="text/css">
#left h2 {
padding-top:0px;
margin-bottom:0.25em;
color:#666;
}
pre.block {
margin-top:0.5em;
}
/* special case */
#left {
width:auto;
max-width:100%;
}
</style>
<!-- demo configuration stuff, you don't need this -->
<link rel="stylesheet" type="text/css" href="demo-slider-controls.css" />
<script type="text/javascript" src="demo-slider-controls.js"></script>
</head>
<body>
<div id="left">
<h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 player project home">SoundManager 2</a> / <a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360&deg; Player Demo</a>: JS + Canvas Visualization</h1>
<p class="note" style="color:#666;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: Spectrum/EQ visualizations disabled for IE (too slow.) Data is not currently available under HTML5.</b></p>
<p class="note" style="color:#666;margin-bottom:0.5em">You can also <a href="#debug=1" onclick="window.location.href = this.href;window.location.reload()" title="Enable debug mode, show frames per second">show FPS</a><span id="config-link"> or <a href="#customize" onclick="window.location.href=this.href;window.location.reload()">customize the UI</a></span><span id="hifi">, or see the <a href="#hifi=1" onclick="window.location.href=this.href;window.location.reload()">hi-fi version</a></span>. Check the <a href="canvas-visualization-basic.html">basic template</a> for a minimal code example; also see the <a href="../360-player/" title="360&deg; player UI">default 360&deg; UI</a>.</p>
<!-- customization crap -->
<div id="config-ui" style="clear:both;position:relative;max-width:1110px;margin-top:1em;display:none">
<div style="position:relative">
<form action="#" method="get">
<div id="controls">
<div class="checkbox">
<div>
<input id="use-waveform" type="checkbox" checked="checked" title="Enable waveform feature." onclick="controller.updateExample();controller.updateExampleCode()" value="Apply" /> Waveform
<input id="disabled-1" type="checkbox" title="Enable EQ (spectrum) feature." onclick="controller.updateExample();controller.updateExampleCode()" value="Apply" style="margin-left:1em" checked="checked" /> EQ
<input type="checkbox" name="use-amplifier" id="use-amplifier" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()" style="margin-left:1em"> Amplifier
</div>
</div>
<div style="clear:left"></div>
<dl class="col">
<dt>Circle Diameter</dt>
<dd class="title">Size</dd>
<dd>1-256</dd>
<dd class="control">
<div class="bar" title="Click to move here"></div>
<div class="slider" title="Size of circle"></div>
</dd>
<dt>Waveform Thickness</dt>
<dd class="title">thickness</dd>
<dd>1-100</dd>
<dd class="control">
<div class="bar" title="Click to move here"></div>
<div class="slider" title="Thickness of line"></div>
</dd>
<dt>Wave Downsample</dt>
<dd class="title">(Scale)</dd>
<dd>1-16</dd>
<dd class="control">
<div class="bar" title="Click to move here"></div>
<div class="slider" title="Primary (inner circle) colour"></div>
</dd>
<dt>EQ Thickness</dt>
<dd class="title">thickness</dd>
<dd>1-50</dd>
<dd class="control">
<div class="bar" title="Click to move here"></div>
<div class="slider" title="Thickness of line"></div>
</dd>
<dt>EQ Downsample</dt>
<dd class="title">(Scale)</dd>
<dd>1-16</dd>
<dd class="control">
<div class="bar" title="Click to move here"></div>
<div class="slider" title="Primary (inner circle) colour"></div>
</dd>
</dl>
<div id="options" class="col">
<div>
Waveform position:
<input type="radio" name="waveform-inside" id="waveform-inside" value="true" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()"> Inside | <input type="radio" name="waveform-inside" id="waveform-inside" value="false" onclick="controller.updateExample();controller.updateExampleCode()"> Outside
</div>
<div>
EQ position:
<input type="radio" name="eq-inside" id="eq-inside" value="true" onclick="controller.updateExample();controller.updateExampleCode()"> Inside | <input type="radio" name="eq-inside" id="eq-inside" value="false" checked="checked" onclick="controller.updateExample();controller.updateExampleCode()"> Outside
</div>
<div>
Waveform color:
<input type="text" name="waveform-color" id="waveform-color" value="#000000" onclick="createCP(this,setWaveformColor)" />
</div>
<div>
EQ color:
<input type="text" name="eq-color" id="eq-color" value="#000000" onclick="createCP(this,setEQColor)" />
</div>
<div>
Loaded ring color:
<input type="text" name="loaded-ring-color" id="loaded-ring-color" value="#000000" onclick="createCP(this,setLoadedRingColor)" />
</div>
<div>
Progress ring color:
<input type="text" name="progress-ring-color" id="progress-ring-color" value="#000000" onclick="createCP(this,setProgressRingColor)" />
</div>
<div>
Background ring color:
<input type="text" name="bg-ring-color" id="bg-ring-color" value="#000000" onclick="createCP(this,setBackgroundRingColor)" />
</div>
<p class="compact">
<input type="button" onclick="controller.randomize()" value="Randomize controls" title="Assign random control values" style="font-size:x-small" />
</p>
</form>
</div>
<div id="cp-container">
<!-- color picker stuff goes here -->
</div>
<div id="config-code-block" style="float:right;display:inline;margin-left:1em;margin-top:-0.7em">
<!--
<pre id="config-link" class="block"><code style="cursor:pointer" onclick="document.getElementById('config-link').style.display='none';document.getElementById('config-pre-block').style.display='block';return false"> [click to show code] </code></pre>
-->
<pre id="config-pre-block" class="block"><code id="config-code">Code goes here</code></pre>
</div>
</div>
</div>
<p style="clear:left">Get a sound playing, then adjust the values to see real-time updates.</p>
</div>
<!-- here are the MP3 links, which are decorated with the 360 canvas element/UI etc. -->
<div id="sm2-container">
<!-- sm2 flash goes here -->
</div>
<h2 style="margin-top:1em">Inline list</h2>
<div class="sm2-inline-list"> <!-- remove this class to have one item per line -->
<div class="ui360"><a href="http://freshly-ground.com/data/audio/sm2/Adrian%20Glynn%20-%20Blue%20Belle%20Lament.mp3">Adrian Glynn - Blue Belle Lament</a></div>
<div class="ui360"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3">SonReal - I Tried</a></div>
<div class="ui360"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3">SonReal - People Asking</a></div>
<div class="ui360"><a href="http://freshly-ground.com/data/audio/mpc/20060826%20-%20Armstrong.mp3">20060826 - Armstrong Groove</a></div>
</div>
<p class="note medium-note" style="clear:both"><b>Artist thank-yous</b>: "Blue Belle Lament" courtesy of <a href="http://www.adrianglynn.com/" title="Adrian Glynn, Vancouver-based Singer/Songwriter">Adrian Glynn</a>. "I Tried" and "People Asking" courtesy of <a href="http://sonreal.bandcamp.com/album/the-lightyear-mixtape" title="The Lightyear Mixtape from SonReal, Vancouver-based hip-hop artist">SonReal</a>.</p>
<h2 style="clear:left;padding-top:1em">Block list</h2>
<div>
<div class="ui360"><a href="http://freshly-ground.com/data/audio/mpc/20090207%20-%20Loverman.mp3">20090207 - Loverman</a></div>
<div class="ui360"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
<div class="ui360"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
</div>
<div style="clear:left"></div>
<h2 style="clear:left;padding-top:1em">Variant: Annotations/meta-data</h2>
<ul class="ui360playlist">
<li>
<div class="ui360">
<a href="http://freshly-ground.com/data/audio/binaural/A%20Virtual%20Haircut%20in%20San%20Francisco%20%283%20Scenes%29.mp3">A Virtual Haircut (3 scenes)</a>
<div class="metadata">
<div class="duration">4:43</div> <!-- total track time (for positioning while loading, until determined -->
<ul>
<li><p>Electric razor</p><span>0:00</span></li> <!-- first scene -->
<li><p>Water, scissors</p><span>2:41</span></li> <!-- start time of second scene -->
<li><p>More razor work</p><span>4:00</span></li>
</ul>
</div>
</div>
</li>
<li>
<div class="ui360">
<a href="http://freshly-ground.com/data/audio/binaural/Rubber%20Chicken%20Launch%20%28office%29.mp3">Rubber Chicken Launch (Office)</a>
<div class="metadata">
<div class="duration">0:47</div>
<ul>
<li><p>First attempt</p><span>0:00</span></li>
<li><p>Fire!</p><span>0:02</span></li>
<li><p>"Too much angle"</p><span>0:05</span></li>
<li><p>Random chicken noise</p><span>0:18</span></li>
<li><p>"Wait a second"</p><span>0:31</span></li>
<li><p>Derrr..</p><span>0:34</span></li>
<li><p>Launch attempt #2</p><span>0:36</span></li>
<li><p>"Wrong angle"</p><span>0:39</span></li>
<li><p>"Fail"</p><span>0:42</span></li>
</ul>
</div>
</div>
</li>
</ul>
<div style="clear:both"></div>
<p style="margin-left:1em">
<a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)
</p>
<script type="text/javascript">
if (window.location.toString().match(/#customize/i)) {
document.getElementById('config-link').style.display = 'none';
document.getElementById('config-ui').style.display = 'block';
}
</script>
</div>
</body>
</html>

View file

@ -0,0 +1,179 @@
#cp-container { position:relative;float:left;display:inline; margin-left:1em;padding: 6px; background-color: #f6f6f6; border:1px solid #eee; width: 320px; height:180px;z-index:2; }
.yui-picker-controls li,
.yui-picker-controls input {
font-size:1em;
font-family:"helvetica neue",helvetica,arial,verdana;
}
#controls {
position:relative;
margin-top:1.5em;
font-size:0.85em;
}
#options {
float:left;
display:inline;
margin-bottom:0.5em;
margin-top:-1.2em;
}
#controls .checkbox {
float:left;
display:inline;
width:21.2em;
margin-right:2.5em;
}
#controls .checkbox div {
/* tab */
width:auto;
padding:0.4em;
border:1px solid #ddd;
border-bottom:none;
background:#eee;
}
#controls .checkbox div,
#controls .checkbox input {
font-family:arial,tahoma,verdana,"sans serif";
font-size:1em;
vertical-align:middle;
}
#controls dl {
width:21em;
}
#controls dl.col {
position:relative;
float:left;
display:inline;
margin:0px;
margin-right:1em;
padding:0.75em;
/*
height:12.4em;
*/
height:auto;
border:1px solid #ddd;
background:#f6f6f6;
}
#controls .disabled {
color:#ccc;
}
#controls .disabled dt,
#controls .disabled dd {
color:#999;
opacity:0.5;
}
#controls dl dd p {
margin:0px;
padding:0px;
}
#controls dt,
#controls dd {
margin:0px;
padding:0px;
}
#controls dt {
border-bottom:none;
}
#controls dt {
float:left;
display:inline;
background:transparent;
padding-right:0.7em;
margin-right:0.7em;
border-right:1px solid #ccc;
font-size:1.1em;
color:#333;
font-family:"helvetica neue",helvetica,verdana,arial,"sans serif";
}
#controls dd {
margin:0px;
padding:0px;
font-size:0.9em;
vertical-align:middle;
color:#666;
}
#controls .title {
float:left;
display:inline;
margin-right:0.6em;
color:#333;
}
/* those slider bits you might be wondering about */
#controls .control {
position:relative;
border-left:0px;
width:214px;
height:20px;
}
#controls .control .bar {
position:absolute;
left:0px;
top:0px;
width:214px;
height:20px;
background:transparent url(../_image/slider-bar.gif) no-repeat 0px 9px;
cursor:pointer;
cursor:hand;
}
#controls .control .slider {
position:absolute;
left:0px;
top:0px;
width:20px;
height:20px;
background:transparent url(../_image/slider.png) no-repeat 0px 0px;
*background:none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider.png');
cursor:pointer;
cursor:hand;
}
#controls .control .slider:hover {
background:transparent url(../_image/slider-1.png) no-repeat 0px 0px;
*background:none;
}
#controls .control .slider.hover {
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-1.png');
}
#controls .disabled .control .slider {
background:transparent url(../_image/slider-disabled.png) no-repeat 0px 0px;
*background:none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled.png');
}
#controls .disabled .control .slider:hover {
background:transparent url(../_image/slider-disabled-1.png) no-repeat 0px 0px;
*background:none;
}
#controls .disabled .control .slider.hover {
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,sizingMethod=crop,src='../_image/slider-disabled-1.png');
}
#controls input[type=text] {
width:5em;
}
#options div {
margin-bottom:0.25em;
}

View file

@ -0,0 +1,714 @@
/*
Ancient fireworks slider control code (2005)
http://schillmania.com/projects/fireworks/
--------------------------------------------
Not required for your use!
*/
function Animator2() {
var self = this;
this.tweens = [];
this.tweens['default'] = [1,2,3,4,5,6,7,8,9,10,9,8,7,6,5,4,3,2,1];
this.tweens['blast'] = [12,12,11,10,10,9,8,7,6,5,4,3,2,1];
this.tweens['fade'] = [10,10,10,10,10,10,10,10,10,10];
this.queue = [];
this.queue.IDs = [];
this.active = false;
this.timer = null;
this.createTween = function(start,end,type) {
// return array of tween coordinate data (start->end)
type = type||'default';
var tween = [start];
var tmp = start;
var diff = end-start;
var x = self.tweens[type].length;
for (var i=0; i<x; i++) {
tmp += diff*self.tweens[type][i]*0.01;
tween[i] = new Object();
tween[i].data = tmp;
tween[i].event = null;
}
return tween;
}
this.enqueue = function(o,fMethod,fOnComplete) {
// add object and associated methods to animation queue
// writeDebug('animator.enqueue()');
if (!fMethod) {
// writeDebug('animator.enqueue(): missing fMethod');
}
if (typeof(self.queue.IDs[o.oID])=='undefined') {
// writeDebug('animator.enqueue(): added '+o.oID);
var i = self.queue.length;
self.queue.IDs[o.oID] = i;
self.queue[i] = o;
} else {
// writeDebug('animator.enqueue(): '+o.oID+' already queued');
var i = self.queue.IDs[o.oID]; // retrieve queue index
self.queue[i].active = true;
self.queue[i].frame = 0;
}
o.active = true; // flag for animation
self.queue[i]._method = fMethod;
self.queue[i]._oncomplete = fOnComplete?fOnComplete:null;
}
this.animate = function() {
var active = 0;
for (var i=self.queue.length; i--;) {
if (self.queue[i].active) {
self.queue[i]._method();
active++;
}
}
if (active==0 && self.timer) {
// all animations finished
self.stop();
} else {
// writeDebug(active+' active');
}
}
this.start = function() {
if (self.timer || self.active) {
// writeDebug('animator.start(): already active');
return false;
}
// writeDebug('animator.start()'); // report only if started
self.active = true;
self.timer = setInterval(self.animate,mc.intervalRate);
}
this.stop = function() {
// writeDebug('animator.stop()',true);
clearInterval(self.timer);
self.timer = null;
self.active = false;
self.queue = [];
self.queue.IDs = [];
}
}
function MainController() {
var self = this;
this.intervalRate = 20; // rate (ms) to run animation at, general best default = 20
this.DEBUG = true; // debug mode disabled by default
this.oFW = null;
this.isIE = (navigator.appVersion.indexOf('MSIE')+1);
this.isOpera = (navigator.userAgent.toLowerCase().indexOf('opera')+1);
if (this.isOpera) this.isIE = false; // no impersonation allowed here!
this.animator = null;
this.gOID = 0; // global object ID counter (for animation queue)
this.particleTypes = 6;
this.particleXY = 10;
this.tweenFade = [100,90,80,70,60,50,40,30,20,10,0];
this.isSafari = (navigator.appVersion.toLowerCase().indexOf('safari')+1?1:0);
this.canvasX = null;
this.canvasY = null;
this.screenY = null; // screen area (not entire page)
self.scrollY = null;
self.getWindowCoords = function() {
self.canvasX = (document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth);
self.canvasY = (document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight);
self.screenY = self.canvasY;
self.scrollY = parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop);
self.canvasY += self.scrollY;
}
this.getWindowCoordsAlt = function() {
self.canvasX = window.innerWidth;
self.canvasY = window.innerHeight;
self.screenY = self.canvasY;
self.scrollY = parseInt(window.scrollY||document.documentElement.scrollTop||document.body.scrollTop);
self.canvasY += self.scrollY;
}
this.getPanX = function(x) {
x = parseInt(x);
var pos = x/self.canvasX;
if (pos<0.4) {
pos *= -1;
} else if (pos >= 0.4 && pos <= 0.6) {
pos = 0.5;
}
pos = parseInt(pos*100);
// writeDebug('getPanX('+x+'): '+pos+'%');
return pos;
}
this.isEmpty = function(o) {
// needs further hacking
return (typeof(o)=='undefined'||(o==null&&o!=0)||(o==''&&o!=0)||o=='null');
}
this.init = function() {
// self.oFW = document.getElementById('fw');
// self.oFP = document.getElementById('fp');
// if (typeof(enableDebugMode)!='undefined' && (self.DEBUG||window.location.toString().toLowerCase().indexOf('debug')>=0)) enableDebugMode();
self.getWindowCoords();
self.animator = new Animator2();
}
this.destructor = function() {
/*
for (var i=self.fireworks.length; i--;) {
self.fireworks[i] = null;
}
self.fireworks = null;
if (soundManager) {
soundManager.destructor();
soundManager = null;
}
*/
}
if (this.isSafari || this.isOpera) this.getWindowCoords = this.getWindowCoordsAlt;
}
function Controller(o) {
var self = this;
this.o = o;
this.controls = [];
this.cb = [];
this.options = [];
this.functionExample = document.getElementById('function-example');
this.fbIE = null;
this.randomize = function() {
for (var i=1; i<self.controls.length; i++) {
setTimeout(self.controls[i].randomize,20+(20*i+1));
}
}
this.cbClick = function(nIndex) {
document.getElementById('controls').getElementsByTagName('dl')[nIndex].className = 'col'+(this.checked==false||this.checked==''?' disabled':'');
self.updateExample();
self.updateExampleCode();
}
this.updateExample = function() {
if (threeSixtyPlayer) {
var val = self.controls[0].value;
threeSixtyPlayer.config.circleDiameter = self.controls[0].value;
threeSixtyPlayer.config.circleRadius = self.controls[0].value/2;
// update some stuff
// set the cover width/height to match the canvas
if (threeSixtyPlayer.lastSound) {
// always set cover to max area?
// threeSixtyPlayer.lastSound._data.oCover.style.width = 250+'px';
// threeSixtyPlayer.lastSound._data.oCover.style.height = 250+'px';
// threeSixtyPlayer.lastSound._data.oCover.style.width = threeSixtyPlayer.config.circleDiameter+'px';
// threeSixtyPlayer.lastSound._data.oCover.style.height = threeSixtyPlayer.config.circleDiameter+'px';
threeSixtyPlayer.refreshCoords(threeSixtyPlayer.lastSound);
}
threeSixtyPlayer.config.waveformDataLineRatio = (self.controls[1].value/100)*2;
threeSixtyPlayer.config.waveformDataDownsample = (self.controls[2].value);
threeSixtyPlayer.config.eqDataLineRatio = parseInt((self.controls[3].value/100)*3*1000)/1000;
threeSixtyPlayer.config.eqDataDownsample = (self.controls[4].value);
threeSixtyPlayer.config.useEQData = (document.getElementById('disabled-1').checked?true:false);
// radio buttons
threeSixtyPlayer.config.useWaveformData=(document.getElementById('use-waveform').checked?true:false);
threeSixtyPlayer.config.waveformDataOutside = document.getElementById('waveform-inside').checked?false:true;
threeSixtyPlayer.config.eqDataOutside = document.getElementById('eq-inside').checked?false:true;
threeSixtyPlayer.config.useAmplifier = (document.getElementById('use-amplifier').checked?true:false);
// threeSixtyPlayer.refreshCoords();
}
}
this.updateExampleCode = function() {
// set innerHTML
document.getElementById('config-code').innerHTML = "\
// 360player.js, config section\n\
\n\
this.config = {\n\
\n\
playNext: <span>"+threeSixtyPlayer.config.playNext+"</span>,\n\
autoPlay: <span>"+threeSixtyPlayer.config.autoPlay+"</span>,\n\
allowMultiple: <span>"+threeSixtyPlayer.config.allowMultiple+"</span>,\n\
loadRingColor: <span>'"+threeSixtyPlayer.config.loadRingColor+"'</span>,\n\
playRingColor: <span>'"+threeSixtyPlayer.config.playRingColor+"'</span>,\n\
backgroundRingColor: <span>'"+threeSixtyPlayer.config.backgroundRingColor+"'</span>,\n\
circleDiameter: <span>"+threeSixtyPlayer.config.circleDiameter+"</span>,\n\
circleRadius: <span>"+threeSixtyPlayer.config.circleRadius+"</span>,\n\
imageRoot: <span>'"+threeSixtyPlayer.config.imageRoot+"'</span>,\n\
animDuration: <span>"+threeSixtyPlayer.config.animDuration+"</span>,\n\
animTransition: <span>Animator.tx.bouncy</span>,\n\
showHMSTime: <span>"+threeSixtyPlayer.config.showHMSTime+"</span>,\n\
\n\
useWaveformData: <span>"+threeSixtyPlayer.config.useWaveformData+"</span>,\n\
waveformDataColor: <span>'"+threeSixtyPlayer.config.waveformDataColor+"'</span>,\n\
waveformDataDownsample: <span>"+threeSixtyPlayer.config.waveformDataDownsample+"</span>,\n\
waveformDataOutside: <span>"+threeSixtyPlayer.config.waveformDataOutside+"</span>,\n\
waveformDataConstrain: <span>false</span>,\n\
waveformDataLineRatio: <span>"+threeSixtyPlayer.config.waveformDataLineRatio+"</span>,\n\
\n\
useEQData: <span>"+threeSixtyPlayer.config.useEQData+"</span>,\n\
eqDataColor: <span>'"+threeSixtyPlayer.config.eqDataColor+"'</span>,\n\
eqDataDownsample: <span>"+threeSixtyPlayer.config.eqDataDownsample+"</span>,\n\
eqDataOutside: <span>"+threeSixtyPlayer.config.eqDataOutside+"</span>,\n\
eqDataLineRatio: <span>"+threeSixtyPlayer.config.eqDataLineRatio+"</span>,\n\
\n\
usePeakData: <span>"+threeSixtyPlayer.config.usePeakData+"</span>,\n\
peakDataColor: <span>'"+threeSixtyPlayer.config.peakDataColor+"'</span>,\n\
peakDataOutside: <span>"+threeSixtyPlayer.config.peakDataOutside+"</span>,\n\
peakDataLineRatio: <span>"+threeSixtyPlayer.config.peakDataLineRatio+"</span>,\n\
\n\
useAmplifier: <span>"+threeSixtyPlayer.config.useAmplifier+"</span>\n\
\n\
}";
document.getElementById('config-code').style.display = 'block'; // weird Fx fix
}
this.createCustomFirework = function() {
}
this.destructor = function() {
for (var i=self.controls.length; i--;) {
self.controls[i].destructor();
}
for (i=self.cb.length; i--;) {
self.cb.onclick = null;
self.cb[i] = null;
}
for (i=self.options.length; i--;) {
self.options[i] = null;
}
if (navigator.userAgent.match(/msie/i)) {
self.fbIE.onmouseover = null;
self.fbIE.onmouseout = null;
self.fbIE = null;
}
self.cb = null;
self.options = null;
self.controls = null;
self.functionExample = null;
self.o = null;
}
var items = parseInt(this.o.length/3);
for (var i=0; i<items; i++) {
this.controls[this.controls.length] = new Slider(this.o[(3*i)+2].getElementsByTagName('div')[1],this.o[(3*i)+1],this.o[(3*i)+2].getElementsByTagName('div')[0]);
}
this.cb = [document.getElementById('disabled-0'),document.getElementById('disabled-1')];
/*
for (i=this.cb.length; i--;) {
this.cb[i]._index = i;
this.cb[i].onclick = this.cbClick;
}
*/
this.options = [];
/*
this.cb[1].checked = false;
this.options = [document.getElementById('opt-random0'),document.getElementById('opt-random1')];
this.options[0].checked = false;
this.options[1].checked = true;
if (navigator.userAgent.match(/msie/i)) {
this.fbIE = document.getElementById('fireButton');
this.fbIE.onmouseover = function() {this.className='hover';}
this.fbIE.onmouseout = function() {this.className='';}
}
*/
setTimeout(function(){
var values = [
256,
65,
40,
72,
48
];
for (var i=0; i<values.length; i++) {
self.controls[i].setValue(values[i]); // defaults
}
},1);
}
function Slider(o,oV,oB) {
var self = this;
this.o = o;
this.oV = oV;
this.oB = oB;
this.scale = parseInt(oV.innerHTML.toString().substr(2));
this.oID = 'sc'+(gOID++);
this.offX = 0;
this.x = 0;
this.xMin = 0-10;
this.xMax = self.o.parentNode.offsetWidth-10;
this.value = 0;
this.timer = null;
this._className = this.o.className;
this.tween = [];
this.frame = 0;
this.over = function() {
this.className = self._className+' hover';
event.cancelBubble=true;
return false;
}
this.out = function() {
this.className = self._className;
event.cancelBubble=true;
return false;
}
this.down = function(e) {
var e = e?e:event;
self.offX = e.clientX-self.o.offsetLeft;
addEvent(document,'mousemove',self.move);
addEvent(document,'mouseup',self.up);
return false;
}
this.barClick = function(e) {
var e=e?e:event;
self.slide(self.x,e.clientX-self.o.parentNode.parentNode.offsetLeft-self.o.offsetWidth);
}
this.move = function(e) {
var e=e?e:event;
var x = e.clientX-self.offX;
if (x>self.xMax) {
x = self.xMax;
} else if (x<self.xMin) {
x = self.xMin;
}
if (x != self.x) {
self.moveTo(x);
self.doUpdate();
controller.updateExample();
controller.updateExampleCode();
}
e.stopPropgation?e.stopPropagation():e.cancelBubble=true;
return false;
}
this.up = function(e) {
removeEvent(document,'mousemove',self.move);
removeEvent(document,'mouseup',self.up);
// controller.updateExample();
controller.updateExampleCode();
}
this.slide = function(x0,x1) {
self.tween = mc.animator.createTween(x0,x1);
mc.animator.enqueue(self,self.animate,function(){
controller.updateExample()
controller.updateExampleCode();
});
mc.animator.start();
}
this.moveTo = function(x) {
self.x = x;
self.o.style.marginLeft = x+'px';
}
this.animate = function() {
self.moveTo(self.tween[self.frame].data);
self.doUpdate(50);
controller.updateExample();
if (self.frame++>=self.tween.length-1) {
self.active = false;
self.frame = 0;
if (self._oncomplete) self._oncomplete();
// self.doUpdate();
return false;
}
self.doUpdate();
return true;
}
this.doUpdate = function(t) {
// if (!self.timer) self.timer = setTimeout(self.update,t||20);
self.update();
}
this.update = function() {
self.timer = null;
self.value = 1+parseInt(self.x/self.xMax*(self.scale-1));
if (self.value<1) self.value = 1;
// if (self.oV.innerHTML != self.value) self.oV.innerHTML = self.value;
// self.oV.innerHTML = self.value;
}
this.setValue = function(x) {
self.slide(self.x,Math.min(self.xMax,x));
}
this.randomize = function() {
self.slide(self.x,parseInt(Math.random()*self.xMax));
}
this.destructor = function() {
self.o.onmouseover = null;
self.o.onmouseout = null;
self.o.onmousedown = null;
self.o = null;
self.oV = null;
self.oB.onclick = null;
self.oB = null;
}
if (soundManager.isIE) {
// IE is lame, no :hover
this.o.onmouseover = this.over;
this.o.onmouseout = this.out;
}
this.o.onmousedown = this.down;
this.oB.onclick = this.barClick;
self.update();
}
var gOID = 0;
function demoInit() {
controller = new Controller(document.getElementById('controls').getElementsByTagName('dd'));
}
function demoDestuctor() {
controller.destructor();
controller = null;
}
var controller = null;
var mc = new MainController();
// create null objects if APIs not present
function createCP(oInput,oHandler) {
var Event = YAHOO.util.Event;
cpHandler = oHandler;
if (picker != null) {
// picker.showcontrols(true);
var c = oInput.value.substr(1);
picker.setValue(hex2decArray([c.substr(0,2),c.substr(2,2),c.substr(4,2)]),true); // be silent
return false;
}
Event.onDOMReady(function() {
picker = new YAHOO.widget.ColorPicker("cp-container", {
showhsvcontrols: true,
showhexcontrols: true,
images: {
PICKER_THUMB: "../_image/picker_thumb.png",
HUE_THUMB: "../_image/hue_thumb.png"
}
});
// picker.showcontrols(false);
//a listener for logging RGB color changes;
//this will only be visible if logger is enabled:
var onRgbChange = function(o) {
/*o is an object
{ newValue: (array of R, G, B values),
prevValue: (array of R, G, B values),
type: "rgbChange"
}
*/
cpHandler(o.newValue);
controller.updateExampleCode();
}
//subscribe to the rgbChange event;
picker.on("rgbChange", onRgbChange);
//use setValue to reset the value to white:
Event.on("reset", "click", function(e) {
picker.setValue([255, 255, 255], false); //false here means that rgbChange
//wil fire; true would silence it
});
//use the "get" method to get the current value
//of one of the Color Picker's properties; in
//this case, we'll get the hex value and write it
//to the log:
Event.on("gethex", "click", function(e) {
console.log("Current hex value: " + picker.get("hex"));
});
});
}
var picker = null;
cpHandler = function() {
}
// hex -> dec / dec -> hex
// http://www.southwest.com.au/~jfuller/binary/converter.htm
function dec2hex(cval) {
if (cval > 255) cval = 255;
var hexascii = "0123456789ABCDEF";
var cval0 = Math.floor(cval/16);
var cval1 = cval-(cval0*16);
var c1 = hexascii.charAt(cval0);
var c2 = hexascii.charAt(cval1);
return (c1+c2);
}
function hex2dec(cval) {
cval = cval.toUpperCase();
var tval = 0;
var hexascii = "0123456789ABCDEF";
var mychar, ch;
for (var c=0; c<cval.length; c++) {
mychar = cval.charAt(c);
for (ch=0; ch<16; ch++) {
if (mychar == hexascii.charAt(ch)) {
tval += ch;
if (c<cval.length-1) tval *= 16;
}
}
}
return tval;
}
function hex2decArray(hArray) {
var result = [];
for (var i=0,j=hArray.length; i<j; i++) {
result[i] = hex2dec(hArray[i]);
}
return result;
}
function dec2hexArray(dArray) {
var result = [];
for (var i=0,j=dArray.length; i<j; i++) {
result[i] = dec2hex(dArray[i]);
}
return result;
}
/*
threeSixtyPlayer.config.waveformDataColor = '#'+dec2hexArray([self.controls[5].value,self.controls[6].value,self.controls[7].value]).join('');
threeSixtyPlayer.config.eqDataColor = '#'+dec2hexArray([self.controls[8].value,self.controls[9].value,self.controls[10].value]).join('');
threeSixtyPlayer.config.loadRingColor = '#'+dec2hexArray([self.controls[11].value,self.controls[12].value,self.controls[13].value]).join('');
threeSixtyPlayer.config.playRingColor = '#'+dec2hexArray([self.controls[14].value,self.controls[15].value,self.controls[16].value]).join('');
threeSixtyPlayer.config.waveformDataLineRatio = (self.controls[1].value/100)*2;
threeSixtyPlayer.config.waveformDataDownsample = (self.controls[2].value);
threeSixtyPlayer.config.eqDataLineRatio = (self.controls[3].value/100)*3;
threeSixtyPlayer.config.eqDataDownsample = (self.controls[4].value);
*/
function _id(sID) {
return document.getElementById(sID);
}
function setWaveformColor(sColor) {
var value = '#'+(dec2hexArray(sColor).join(''));
threeSixtyPlayer.config.waveformDataColor = value;
_id('waveform-color').value = value;
}
function setEQColor(sColor) {
var value = '#'+dec2hexArray(sColor).join('');
_id('eq-color').value = value;
threeSixtyPlayer.config.eqDataColor = value;
}
function setLoadedRingColor(sColor) {
var value = '#'+dec2hexArray(sColor).join('');
_id('loaded-ring-color').value = value;
threeSixtyPlayer.config.loadRingColor = value;
}
function setProgressRingColor(sColor) {
var value = '#'+dec2hexArray(sColor).join('');
_id('progress-ring-color').value = value;
threeSixtyPlayer.config.playRingColor = value;
}
function setBackgroundRingColor(sColor) {
var value = '#'+dec2hexArray(sColor).join('');
_id('bg-ring-color').value = value;
threeSixtyPlayer.config.backgroundRingColor = value;
}
function addEvent(o,evtName,evtHandler) {
typeof(attachEvent)=='undefined'?o.addEventListener(evtName,evtHandler,false):o.attachEvent('on'+evtName,evtHandler);
}
function removeEvent(o,evtName,evtHandler) {
typeof(attachEvent)=='undefined'?o.removeEventListener(evtName,evtHandler,false):o.detachEvent('on'+evtName,evtHandler);
}
if (window.location.toString().match(/#customize/i)) {
addEvent(window,'resize',mc.getWindowCoords);
addEvent(window,'scroll',mc.getWindowCoords);
addEvent(window,'load',mc.init);
addEvent(window,'load',demoInit);
}
if (window.location.toString().match(/hifi/i)) {
soundManager.onready(function(){
document.getElementById('hifi').style.display = 'none';
threeSixtyPlayer.config = {
playNext: false,
autoPlay: false,
loadRingColor: '#ccc',
playRingColor: '#000',
backgroundRingColor: '#eee',
circleDiameter: 256,
circleRadius: 128,
imageRoot: '',
animDuration: 500,
animTransition: Animator.tx.bouncy,
showHMSTime: true,
useWaveformData: true,
waveformDataColor: '#0099ff',
waveformDataDownsample: 1,
waveformDataOutside: true,
waveformDataConstrain: false,
waveformDataLineRatio: 0.56,
useEQData: true,
eqDataColor: '#339933',
eqDataDownsample: 1,
eqDataOutside: true,
eqDataLineRatio: 0.72,
usePeakData: true,
peakDataColor: '#ff33ff',
peakDataOutside: true,
peakDataLineRatio: 0.5,
useAmplifier: true
}
});
}

View file

@ -0,0 +1,75 @@
/*
-------------------------------------------------------------
In-page demo CSS - see external CSS for actual relevant stuff.
--------------------------------------------------------------
*/
#soundmanager-debug {
/* SM2 debug container (optional, makes debug more useable) */
position:absolute;position:fixed;*position:absolute;bottom:10px;right:10px;width:50em;height:18em;overflow:auto;background:#fff;margin:1em;padding:1em;border:1px solid #999;font-family:"lucida console",verdana,tahoma,"sans serif";font-size:x-small;line-height:1.5em;opacity:0.9;filter:alpha(opacity=90);
}
body {
font:75% normal verdana,arial,tahoma,"sans serif";
}
h1, h2, h3 {
font:3em arial,tahoma,verdana;
font-weight:normal;
margin-bottom:0px;
}
h1 {
margin-top:0.25em;
}
h1, h2 {
letter-spacing:-1px; /* zomg web x.0! ;) */
}
h2 {
font-size:2em;
margin-top:0px;
margin-bottom:0.1em;
}
h3 {
font-size:1.5em;
margin-bottom:1em;
}
h1 a,
h1 a:hover {
color:#000;
text-decoration:none;
}
h1 a:hover {
text-decoration:underline;
}
ul.notes {
margin-left:0px;
padding-left:1.5em;
}
.note {
margin-top:0px;
font-style:italic;
color:#999;
margin-bottom:0px;
}
pre {
font-size:1.2em;
_font-size:1em;
}
#left {
max-width:56em;
margin-left:1em;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,167 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>360&deg; MP3 player UI demo (SoundManager 2)</title>
<meta name="robots" content="noindex" />
<meta name="description" content="Javascript-driven sound, canvas-based MP3 player UI demo: 360-degree circular control / jog wheel example for playing MP3 links using SoundManager 2, Javascript and Canvas.">
<!-- required -->
<link rel="stylesheet" type="text/css" href="360player.css" />
<!-- special IE-only canvas fix -->
<!--[if IE]><script type="text/javascript" src="script/excanvas.js"></script><![endif]-->
<!-- Apache-licensed animation library -->
<script type="text/javascript" src="script/berniecode-animator.js"></script>
<!-- the core stuff -->
<script type="text/javascript" src="../../script/soundmanager2.js"></script>
<script type="text/javascript" src="script/360player.js"></script>
<script type="text/javascript">
soundManager.url = '../../swf/';
</script>
<!-- stuff you don't need -->
<!-- makes the fonts nicer etc. -->
<link rel="stylesheet" type="text/css" href="../index.css" />
<link rel="stylesheet" type="text/css" href="demo.css" />
<!-- soundManager.useFlashBlock: related CSS -->
<link rel="stylesheet" type="text/css" href="../flashblock/flashblock.css" />
<style type="text/css">
/* Demo page, general layout */
#left {
position:relative;
width:950px;
max-width:100%;
}
#left h2 {
padding-top:0px;
margin-bottom:0.25em;
color:#666;
}
pre.block {
margin-top:0.5em;
}
</style>
</head>
<body>
<div id="left">
<h1><a href="http://www.schillmania.com/projects/soundmanager2/" title="Javascript MP3 player project home">SoundManager 2</a> / <a href="http://schillmania.com/projects/soundmanager2/demo/360-player/">360&deg; Player</a>: JS + Canvas UI</h1>
<p class="note" style="color:#666;margin-bottom:0.5em">Canvas-based UI. Load progress, seek, play/pause etc. Also see <a href="canvas-visualization.html" title="Javascript canvas visualization with waveform/eq data">360&deg; UI visualization</a> demo.</p>
<div id="sm2-container">
<!-- flash movie is added here -->
</div>
<div style="margin-top:1.25em">
<div style="float:left;display:inline"> <!-- float is just for this demo layout, you don't need it. -->
<div class="ui360" style="margin-top:-0.55em"><a href="../_mp3/rain.mp3">Rain</a></div>
<div class="ui360"><a href="http://freshly-ground.com/data/audio/mpc/20090119%20-%20Untitled%20Groove.mp3">20090119 - Untitled Groove</a></div>
</div>
<div style="float:left;display:inline;margin-left:40px;border-left:1px solid #ccc;padding-left:30px;width:140px">
<p style="margin-top:1em;margin-bottom:0px">Alternate style: inline</p>
<div class="sm2-inline-list" style="margin-bottom:10px"> <!-- note the CSS class, changes the layout -->
<div class="ui360"><a href="http://www.freshly-ground.com/data/audio/binaural/Mak.mp3">Angry cow sound?</a></div>
<div class="ui360"><a href="http://www.freshly-ground.com/data/audio/binaural/Things that open, close and roll.mp3">Things that open, close and roll</a></div>
<div class="ui360"><a href="http://www.freshly-ground.com/misc/music/20060826%20-%20Armstrong.mp3">20060826 - Armstrong</a></div>
</div>
</div>
</div>
<div style="clear:both"></div>
<h3>How This Works</h3>
<p>The script looks for a container element matching <code>div.<span>ui360</span></code>, and then the first link inside of it.</p>
<div>
<pre class="block"><code>&lt;div class="<span>ui360</span>"&gt;
&lt;a href="/path/to/an.mp3"&gt;
&lt;/div&gt;</code></pre>
</div>
<p>When the link is clicked, the script adds a <code>UI</code> template to the block, prepending it in front of the MP3 link:</p>
<pre class="block"><code>&lt;div class="<span>ui360</span>"&gt;
<span><span>&lt;-- dynamically-inserted block --&gt;</span></span>
&lt;div class="<span>ui</span>"&gt;
&lt;canvas class="<span>sm2-canvas</span>"&gt;&lt;/canvas&gt;
&lt;img class="<span>sm2-360btn</span>" /&gt;
&lt;div class="<span>sm2-timing</span>"&gt;&lt;/div&gt;
&lt;div class="<span>sm2-cover</span>"&gt;&lt;/div&gt;
&lt;/div&gt;
<span><span>&lt;-- /UI --&gt;</span></span>
&lt;a href="<span>/path/to/an.mp3</span>"&gt;
&lt;/div&gt;</code></pre>
<h3>Customizing the UI</h3>
<p>The player's default 50x50-pixel canvas is defined both within JavaScript and CSS. For an example with different values, see this <a href="canvas-visualization.html" title="360&deg; UI: larger version">larger version</a>.</p>
<pre class="block"><code>threeSixtyPlayer.config = {
playNext: <span>false</span>, <span><span>// stop after one sound, or play through list until end</span></span>
autoPlay: <span>false</span>, <span><span>// start playing the first sound right away</span></span>
allowMultiple: <span>true</span>, <span><span>// let many sounds play at once (false = one at a time)</span></span>
loadRingColor: <span>'#ccc',</span> <span><span>// amount of sound which has loaded</span></span>
playRingColor: <span>'#000'</span>, <span><span>// amount of sound which has played</span></span>
backgroundRingColor: <span>'#eee', </span><span><span>// "default" color shown underneath everything else</span></span>
imageRoot: <span>''</span>,</span> <span><span>// path to prepend for empty.gif used for play/pause button
animDuration: <span>500</span>,
animTransition: <span>Animator.tx.bouncy</span> <span><span>// http://www.berniecode.com/writing/animator.html</span></span>
}</code></pre>
<p>The CSS for the canvas UI block is a bit ugly, but JavaScript reads the width of the <code>.sm2-360ui</code> element in the DOM as set by CSS and uses that to later draw and update the canvas element while playing.</p>
<pre class="block"><code>.ui360,
.sm2-360ui {
<span><span>/* size of the container for the circle, etc. */</span></span>
width:<span>50px</span>;</span>
height:<span>50px</span>;</span>
}
</code></pre>
<h3>Third-party Components</h3>
<p>This demo includes use of <a href="http://www.berniecode.com/writing/animator.html">Bernie's Better Animation Class</a> (Apache licensed) for some animation effects.</p>
<p>Also, some loader/spinner icons from <a href="http://ajaxload.info">ajaxload.info</a> are used for showing loading/buffering states.</p>
<hr />
<p>
<a href="http://www.schillmania.com/projects/soundmanager2/" title="SoundManager 2 home">SoundManager 2 project page</a> (not an MP3 link)
</p>
</div>
</body>
</html>

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,674 @@
/*
Animator.js 1.1.9
This library is released under the BSD license:
Copyright (c) 2006, Bernard Sumption. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. Redistributions in binary
form must reproduce the above copyright notice, this list of conditions and
the following disclaimer in the documentation and/or other materials
provided with the distribution. Neither the name BernieCode nor
the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/
// http://www.berniecode.com/writing/animator.html
// Applies a sequence of numbers between 0 and 1 to a number of subjects
// construct - see setOptions for parameters
function Animator(options) {
this.setOptions(options);
var _this = this;
this.timerDelegate = function(){_this.onTimerEvent()};
this.subjects = [];
this.subjectScopes = [];
this.target = 0;
this.state = 0;
this.lastTime = null;
};
Animator.prototype = {
// apply defaults
setOptions: function(options) {
this.options = Animator.applyDefaults({
interval: 20, // time between animation frames
duration: 400, // length of animation
onComplete: function(){},
onStep: function(){},
transition: Animator.tx.easeInOut
}, options);
},
// animate from the current state to provided value
seekTo: function(to) {
this.seekFromTo(this.state, to);
},
// animate from the current state to provided value
seekFromTo: function(from, to) {
this.target = Math.max(0, Math.min(1, to));
this.state = Math.max(0, Math.min(1, from));
this.lastTime = new Date().getTime();
if (!this.intervalId) {
this.intervalId = window.setInterval(this.timerDelegate, this.options.interval);
}
},
// animate from the current state to provided value
jumpTo: function(to) {
this.target = this.state = Math.max(0, Math.min(1, to));
this.propagate();
},
// seek to the opposite of the current target
toggle: function() {
this.seekTo(1 - this.target);
},
// add a function or an object with a method setState(state) that will be called with a number
// between 0 and 1 on each frame of the animation
addSubject: function(subject,scope) {
this.subjects[this.subjects.length] = subject;
this.subjectScopes[this.subjectScopes.length] = scope;
return this;
},
// remove all subjects
clearSubjects: function() {
this.subjects = [];
this.subjectScopes = [];
},
// forward the current state to the animation subjects
propagate: function() {
var value = this.options.transition(this.state);
for (var i=0; i<this.subjects.length; i++) {
if (this.subjects[i].setState) {
this.subjects[i].setState(value);
} else {
this.subjects[i].apply(this.subjectScopes[i],[value]);
}
}
},
// called once per frame to update the current state
onTimerEvent: function() {
var now = new Date().getTime();
var timePassed = now - this.lastTime;
this.lastTime = now;
var movement = (timePassed / this.options.duration) * (this.state < this.target ? 1 : -1);
if (Math.abs(movement) >= Math.abs(this.state - this.target)) {
this.state = this.target;
} else {
this.state += movement;
}
try {
this.propagate();
} finally {
this.options.onStep.call(this);
if (this.target == this.state) {
window.clearInterval(this.intervalId);
this.intervalId = null;
this.options.onComplete.call(this);
}
}
},
// shortcuts
play: function() {this.seekFromTo(0, 1)},
reverse: function() {this.seekFromTo(1, 0)},
// return a string describing this Animator, for debugging
inspect: function() {
var str = "#<Animator:\n";
for (var i=0; i<this.subjects.length; i++) {
str += this.subjects[i].inspect();
}
str += ">";
return str;
}
}
// merge the properties of two objects
Animator.applyDefaults = function(defaults, prefs) {
prefs = prefs || {};
var prop, result = {};
for (prop in defaults) result[prop] = prefs[prop] !== undefined ? prefs[prop] : defaults[prop];
return result;
}
// make an array from any object
Animator.makeArray = function(o) {
if (o == null) return [];
if (!o.length) return [o];
var result = [];
for (var i=0; i<o.length; i++) result[i] = o[i];
return result;
}
// convert a dash-delimited-property to a camelCaseProperty (c/o Prototype, thanks Sam!)
Animator.camelize = function(string) {
var oStringList = string.split('-');
if (oStringList.length == 1) return oStringList[0];
var camelizedString = string.indexOf('-') == 0
? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
: oStringList[0];
for (var i = 1, len = oStringList.length; i < len; i++) {
var s = oStringList[i];
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
}
return camelizedString;
}
// syntactic sugar for creating CSSStyleSubjects
Animator.apply = function(el, style, options) {
if (style instanceof Array) {
return new Animator(options).addSubject(new CSSStyleSubject(el, style[0], style[1]));
}
return new Animator(options).addSubject(new CSSStyleSubject(el, style));
}
// make a transition function that gradually accelerates. pass a=1 for smooth
// gravitational acceleration, higher values for an exaggerated effect
Animator.makeEaseIn = function(a) {
return function(state) {
return Math.pow(state, a*2);
}
}
// as makeEaseIn but for deceleration
Animator.makeEaseOut = function(a) {
return function(state) {
return 1 - Math.pow(1 - state, a*2);
}
}
// make a transition function that, like an object with momentum being attracted to a point,
// goes past the target then returns
Animator.makeElastic = function(bounces) {
return function(state) {
state = Animator.tx.easeInOut(state);
return ((1-Math.cos(state * Math.PI * bounces)) * (1 - state)) + state;
}
}
// make an Attack Decay Sustain Release envelope that starts and finishes on the same level
//
Animator.makeADSR = function(attackEnd, decayEnd, sustainEnd, sustainLevel) {
if (sustainLevel == null) sustainLevel = 0.5;
return function(state) {
if (state < attackEnd) {
return state / attackEnd;
}
if (state < decayEnd) {
return 1 - ((state - attackEnd) / (decayEnd - attackEnd) * (1 - sustainLevel));
}
if (state < sustainEnd) {
return sustainLevel;
}
return sustainLevel * (1 - ((state - sustainEnd) / (1 - sustainEnd)));
}
}
// make a transition function that, like a ball falling to floor, reaches the target and/
// bounces back again
Animator.makeBounce = function(bounces) {
var fn = Animator.makeElastic(bounces);
return function(state) {
state = fn(state);
return state <= 1 ? state : 2-state;
}
}
// pre-made transition functions to use with the 'transition' option
Animator.tx = {
easeInOut: function(pos){
return ((-Math.cos(pos*Math.PI)/2) + 0.5);
},
linear: function(x) {
return x;
},
easeIn: Animator.makeEaseIn(1.5),
easeOut: Animator.makeEaseOut(1.5),
strongEaseIn: Animator.makeEaseIn(2.5),
strongEaseOut: Animator.makeEaseOut(2.5),
elastic: Animator.makeElastic(1),
veryElastic: Animator.makeElastic(3),
bouncy: Animator.makeBounce(1),
veryBouncy: Animator.makeBounce(3)
}
// animates a pixel-based style property between two integer values
function NumericalStyleSubject(els, property, from, to, units) {
this.els = Animator.makeArray(els);
if (property == 'opacity' && window.ActiveXObject) {
this.property = 'filter';
} else {
this.property = Animator.camelize(property);
}
this.from = parseFloat(from);
this.to = parseFloat(to);
this.units = units != null ? units : 'px';
}
NumericalStyleSubject.prototype = {
setState: function(state) {
var style = this.getStyle(state);
var visibility = (this.property == 'opacity' && state == 0) ? 'hidden' : '';
var j=0;
for (var i=0; i<this.els.length; i++) {
try {
this.els[i].style[this.property] = style;
} catch (e) {
// ignore fontWeight - intermediate numerical values cause exeptions in firefox
if (this.property != 'fontWeight') throw e;
}
if (j++ > 20) return;
}
},
getStyle: function(state) {
state = this.from + ((this.to - this.from) * state);
if (this.property == 'filter') return "alpha(opacity=" + Math.round(state*100) + ")";
if (this.property == 'opacity') return state;
return Math.round(state) + this.units;
},
inspect: function() {
return "\t" + this.property + "(" + this.from + this.units + " to " + this.to + this.units + ")\n";
}
}
// animates a colour based style property between two hex values
function ColorStyleSubject(els, property, from, to) {
this.els = Animator.makeArray(els);
this.property = Animator.camelize(property);
this.to = this.expandColor(to);
this.from = this.expandColor(from);
this.origFrom = from;
this.origTo = to;
}
ColorStyleSubject.prototype = {
// parse "#FFFF00" to [256, 256, 0]
expandColor: function(color) {
var hexColor, red, green, blue;
hexColor = ColorStyleSubject.parseColor(color);
if (hexColor) {
red = parseInt(hexColor.slice(1, 3), 16);
green = parseInt(hexColor.slice(3, 5), 16);
blue = parseInt(hexColor.slice(5, 7), 16);
return [red,green,blue]
}
if (window.DEBUG) {
alert("Invalid colour: '" + color + "'");
}
},
getValueForState: function(color, state) {
return Math.round(this.from[color] + ((this.to[color] - this.from[color]) * state));
},
setState: function(state) {
var color = '#'
+ ColorStyleSubject.toColorPart(this.getValueForState(0, state))
+ ColorStyleSubject.toColorPart(this.getValueForState(1, state))
+ ColorStyleSubject.toColorPart(this.getValueForState(2, state));
for (var i=0; i<this.els.length; i++) {
this.els[i].style[this.property] = color;
}
},
inspect: function() {
return "\t" + this.property + "(" + this.origFrom + " to " + this.origTo + ")\n";
}
}
// return a properly formatted 6-digit hex colour spec, or false
ColorStyleSubject.parseColor = function(string) {
var color = '#', match;
if(match = ColorStyleSubject.parseColor.rgbRe.exec(string)) {
var part;
for (var i=1; i<=3; i++) {
part = Math.max(0, Math.min(255, parseInt(match[i])));
color += ColorStyleSubject.toColorPart(part);
}
return color;
}
if (match = ColorStyleSubject.parseColor.hexRe.exec(string)) {
if(match[1].length == 3) {
for (var i=0; i<3; i++) {
color += match[1].charAt(i) + match[1].charAt(i);
}
return color;
}
return '#' + match[1];
}
return false;
}
// convert a number to a 2 digit hex string
ColorStyleSubject.toColorPart = function(number) {
if (number > 255) number = 255;
var digits = number.toString(16);
if (number < 16) return '0' + digits;
return digits;
}
ColorStyleSubject.parseColor.rgbRe = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
ColorStyleSubject.parseColor.hexRe = /^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
// Animates discrete styles, i.e. ones that do not scale but have discrete values
// that can't be interpolated
function DiscreteStyleSubject(els, property, from, to, threshold) {
this.els = Animator.makeArray(els);
this.property = Animator.camelize(property);
this.from = from;
this.to = to;
this.threshold = threshold || 0.5;
}
DiscreteStyleSubject.prototype = {
setState: function(state) {
var j=0;
for (var i=0; i<this.els.length; i++) {
this.els[i].style[this.property] = state <= this.threshold ? this.from : this.to;
}
},
inspect: function() {
return "\t" + this.property + "(" + this.from + " to " + this.to + " @ " + this.threshold + ")\n";
}
}
// animates between two styles defined using CSS.
// if style1 and style2 are present, animate between them, if only style1
// is present, animate between the element's current style and style1
function CSSStyleSubject(els, style1, style2) {
els = Animator.makeArray(els);
this.subjects = [];
if (els.length == 0) return;
var prop, toStyle, fromStyle;
if (style2) {
fromStyle = this.parseStyle(style1, els[0]);
toStyle = this.parseStyle(style2, els[0]);
} else {
toStyle = this.parseStyle(style1, els[0]);
fromStyle = {};
for (prop in toStyle) {
fromStyle[prop] = CSSStyleSubject.getStyle(els[0], prop);
}
}
// remove unchanging properties
var prop;
for (prop in fromStyle) {
if (fromStyle[prop] == toStyle[prop]) {
delete fromStyle[prop];
delete toStyle[prop];
}
}
// discover the type (numerical or colour) of each style
var prop, units, match, type, from, to;
for (prop in fromStyle) {
var fromProp = String(fromStyle[prop]);
var toProp = String(toStyle[prop]);
if (toStyle[prop] == null) {
if (window.DEBUG) alert("No to style provided for '" + prop + '"');
continue;
}
if (from = ColorStyleSubject.parseColor(fromProp)) {
to = ColorStyleSubject.parseColor(toProp);
type = ColorStyleSubject;
} else if (fromProp.match(CSSStyleSubject.numericalRe)
&& toProp.match(CSSStyleSubject.numericalRe)) {
from = parseFloat(fromProp);
to = parseFloat(toProp);
type = NumericalStyleSubject;
match = CSSStyleSubject.numericalRe.exec(fromProp);
var reResult = CSSStyleSubject.numericalRe.exec(toProp);
if (match[1] != null) {
units = match[1];
} else if (reResult[1] != null) {
units = reResult[1];
} else {
units = reResult;
}
} else if (fromProp.match(CSSStyleSubject.discreteRe)
&& toProp.match(CSSStyleSubject.discreteRe)) {
from = fromProp;
to = toProp;
type = DiscreteStyleSubject;
units = 0; // hack - how to get an animator option down to here
} else {
if (window.DEBUG) {
alert("Unrecognised format for value of "
+ prop + ": '" + fromStyle[prop] + "'");
}
continue;
}
this.subjects[this.subjects.length] = new type(els, prop, from, to, units);
}
}
CSSStyleSubject.prototype = {
// parses "width: 400px; color: #FFBB2E" to {width: "400px", color: "#FFBB2E"}
parseStyle: function(style, el) {
var rtn = {};
// if style is a rule set
if (style.indexOf(":") != -1) {
var styles = style.split(";");
for (var i=0; i<styles.length; i++) {
var parts = CSSStyleSubject.ruleRe.exec(styles[i]);
if (parts) {
rtn[parts[1]] = parts[2];
}
}
}
// else assume style is a class name
else {
var prop, value, oldClass;
oldClass = el.className;
el.className = style;
for (var i=0; i<CSSStyleSubject.cssProperties.length; i++) {
prop = CSSStyleSubject.cssProperties[i];
value = CSSStyleSubject.getStyle(el, prop);
if (value != null) {
rtn[prop] = value;
}
}
el.className = oldClass;
}
return rtn;
},
setState: function(state) {
for (var i=0; i<this.subjects.length; i++) {
this.subjects[i].setState(state);
}
},
inspect: function() {
var str = "";
for (var i=0; i<this.subjects.length; i++) {
str += this.subjects[i].inspect();
}
return str;
}
}
// get the current value of a css property,
CSSStyleSubject.getStyle = function(el, property){
var style;
if(document.defaultView && document.defaultView.getComputedStyle){
style = document.defaultView.getComputedStyle(el, "").getPropertyValue(property);
if (style) {
return style;
}
}
property = Animator.camelize(property);
if(el.currentStyle){
style = el.currentStyle[property];
}
return style || el.style[property]
}
CSSStyleSubject.ruleRe = /^\s*([a-zA-Z\-]+)\s*:\s*(\S(.+\S)?)\s*$/;
CSSStyleSubject.numericalRe = /^-?\d+(?:\.\d+)?(%|[a-zA-Z]{2})?$/;
CSSStyleSubject.discreteRe = /^\w+$/;
// required because the style object of elements isn't enumerable in Safari
/*
CSSStyleSubject.cssProperties = ['background-color','border','border-color','border-spacing',
'border-style','border-top','border-right','border-bottom','border-left','border-top-color',
'border-right-color','border-bottom-color','border-left-color','border-top-width','border-right-width',
'border-bottom-width','border-left-width','border-width','bottom','color','font-size','font-size-adjust',
'font-stretch','font-style','height','left','letter-spacing','line-height','margin','margin-top',
'margin-right','margin-bottom','margin-left','marker-offset','max-height','max-width','min-height',
'min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding',
'padding-top','padding-right','padding-bottom','padding-left','quotes','right','size','text-indent',
'top','width','word-spacing','z-index','opacity','outline-offset'];*/
CSSStyleSubject.cssProperties = ['azimuth','background','background-attachment','background-color','background-image','background-position','background-repeat','border-collapse','border-color','border-spacing','border-style','border-top','border-top-color','border-right-color','border-bottom-color','border-left-color','border-top-style','border-right-style','border-bottom-style','border-left-style','border-top-width','border-right-width','border-bottom-width','border-left-width','border-width','bottom','clear','clip','color','content','cursor','direction','display','elevation','empty-cells','css-float','font','font-family','font-size','font-size-adjust','font-stretch','font-style','font-variant','font-weight','height','left','letter-spacing','line-height','list-style','list-style-image','list-style-position','list-style-type','margin','margin-top','margin-right','margin-bottom','margin-left','max-height','max-width','min-height','min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding','padding-top','padding-right','padding-bottom','padding-left','pause','position','right','size','table-layout','text-align','text-decoration','text-indent','text-shadow','text-transform','top','vertical-align','visibility','white-space','width','word-spacing','z-index','opacity','outline-offset','overflow-x','overflow-y'];
// chains several Animator objects together
function AnimatorChain(animators, options) {
this.animators = animators;
this.setOptions(options);
for (var i=0; i<this.animators.length; i++) {
this.listenTo(this.animators[i]);
}
this.forwards = false;
this.current = 0;
}
AnimatorChain.prototype = {
// apply defaults
setOptions: function(options) {
this.options = Animator.applyDefaults({
// by default, each call to AnimatorChain.play() calls jumpTo(0) of each animator
// before playing, which can cause flickering if you have multiple animators all
// targeting the same element. Set this to false to avoid this.
resetOnPlay: true
}, options);
},
// play each animator in turn
play: function() {
this.forwards = true;
this.current = -1;
if (this.options.resetOnPlay) {
for (var i=0; i<this.animators.length; i++) {
this.animators[i].jumpTo(0);
}
}
this.advance();
},
// play all animators backwards
reverse: function() {
this.forwards = false;
this.current = this.animators.length;
if (this.options.resetOnPlay) {
for (var i=0; i<this.animators.length; i++) {
this.animators[i].jumpTo(1);
}
}
this.advance();
},
// if we have just play()'d, then call reverse(), and vice versa
toggle: function() {
if (this.forwards) {
this.seekTo(0);
} else {
this.seekTo(1);
}
},
// internal: install an event listener on an animator's onComplete option
// to trigger the next animator
listenTo: function(animator) {
var oldOnComplete = animator.options.onComplete;
var _this = this;
animator.options.onComplete = function() {
if (oldOnComplete) oldOnComplete.call(animator);
_this.advance();
}
},
// play the next animator
advance: function() {
if (this.forwards) {
if (this.animators[this.current + 1] == null) return;
this.current++;
this.animators[this.current].play();
} else {
if (this.animators[this.current - 1] == null) return;
this.current--;
this.animators[this.current].reverse();
}
},
// this function is provided for drop-in compatibility with Animator objects,
// but only accepts 0 and 1 as target values
seekTo: function(target) {
if (target <= 0) {
this.forwards = false;
this.animators[this.current].seekTo(0);
} else {
this.forwards = true;
this.animators[this.current].seekTo(1);
}
}
}
// an Accordion is a class that creates and controls a number of Animators. An array of elements is passed in,
// and for each element an Animator and a activator button is created. When an Animator's activator button is
// clicked, the Animator and all before it seek to 0, and all Animators after it seek to 1. This can be used to
// create the classic Accordion effect, hence the name.
// see setOptions for arguments
function Accordion(options) {
this.setOptions(options);
var selected = this.options.initialSection, current;
if (this.options.rememberance) {
current = document.location.hash.substring(1);
}
this.rememberanceTexts = [];
this.ans = [];
var _this = this;
for (var i=0; i<this.options.sections.length; i++) {
var el = this.options.sections[i];
var an = new Animator(this.options.animatorOptions);
var from = this.options.from + (this.options.shift * i);
var to = this.options.to + (this.options.shift * i);
an.addSubject(new NumericalStyleSubject(el, this.options.property, from, to, this.options.units));
an.jumpTo(0);
var activator = this.options.getActivator(el);
activator.index = i;
activator.onclick = function(){_this.show(this.index)};
this.ans[this.ans.length] = an;
this.rememberanceTexts[i] = activator.innerHTML.replace(/\s/g, "");
if (this.rememberanceTexts[i] === current) {
selected = i;
}
}
this.show(selected);
}
Accordion.prototype = {
// apply defaults
setOptions: function(options) {
this.options = Object.extend({
// REQUIRED: an array of elements to use as the accordion sections
sections: null,
// a function that locates an activator button element given a section element.
// by default it takes a button id from the section's "activator" attibute
getActivator: function(el) {return document.getElementById(el.getAttribute("activator"))},
// shifts each animator's range, for example with options {from:0,to:100,shift:20}
// the animators' ranges will be 0-100, 20-120, 40-140 etc.
shift: 0,
// the first page to show
initialSection: 0,
// if set to true, document.location.hash will be used to preserve the open section across page reloads
rememberance: true,
// constructor arguments to the Animator objects
animatorOptions: {}
}, options || {});
},
show: function(section) {
for (var i=0; i<this.ans.length; i++) {
this.ans[i].seekTo(i > section ? 1 : 0);
}
if (this.options.rememberance) {
document.location.hash = this.rememberanceTexts[section];
}
}
}

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 887 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 570 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,74 @@
body {
font-size:75%;
}
h1, h2, h3 {
font:normal 3em "Helvetica Neue",helvetica,georgia,"times new roman","Arial Rounded MT Bold",verdana,tahoma,arial,"sans serif";
font-weight:normal;
margin-bottom:0px;
}
h1, h2 {
letter-spacing:-1px; /* zomg web x.0! ;) */
}
h1, h2, h3 {
padding-bottom:1px;
margin-bottom:0.25em;
}
h1 {
margin-top:0px;
margin-bottom:0px;
background-color:#666;
color:#ccc;
margin-left:-5px;
padding-left:5px;
padding-right:5px;
padding-bottom:5px;
}
h1,
h1 a {
color:#fff;
text-decoration:none;
}
h1 a:hover {
text-decoration:underline;
}
h2 {
font-size:2em;
margin-top:1em;
background-color:#aaa;
color:#fff;
padding:5px;
margin-left:-5px;
min-width:23em;
}
h3 {
font-size:1.65em;
margin-top:0.5em;
margin-bottom:0.25em;
color:#333;
min-width:28em;
}
h3 a {
font-size:small;
}
h4 {
color:#444;
}
p {
font:normal 1em/2em verdana,tahoma,arial,"sans serif";
}
.balls img {
position:absolute;
width:12px;
height:12px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 549 B

View file

@ -0,0 +1,46 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<link rel="stylesheet" href="../template/template.css" media="screen" />
<link rel="stylesheet" href="css/animation.css" media="screen" />
<script type="text/javascript" src="../../script/soundmanager2-nodebug-jsmin.js"></script>
<script type="text/javascript" src="script/animation.js"></script>
</head>
<body>
<div style="margin-right:43em">
<h1>Interval-based animation (with sound)</h1>
<p>
Click + drag for fun.
</p>
<h2>Speeding Up ExternalInterface: Keep .swf in view</h2>
<p>SoundManager 2 now incorporates a "high performance" mode, which has been shown to noticeably improve timing and frequency of flash callbacks. This is important for timing, reducing delay between a JS call and the sound being played, etc.</p>
<p>To reduce audio delay and timing issues from slow JS/Flash communication, SM2 will try to ensure that the flash movie is visible on screen at all times. If hidden or otherwise off-screen, Flash will be given lower priority and thus JS/flash "lag" (ie., delay) will be introduced when trying to play audio "in sync."</p>
<p>Generally, positioning the flash movie using position:fixed and bottom/left or bottom/right 0px is the less-intrusive option.</p>
<p style="margin:0px;padding:0px">
<input id="useMouse" name="usemouse" value="usemouse" type="checkbox"> Throw from mouse
</p>
<p style="margin:0px;padding:0px">
<button id="b-start" onclick="startAnimation()" disabled="disabled">Start</button>
<button id="b-stop" onclick="stopAnimation()" disabled="disabled">Stop</button>
</p>
<p>Sound source: <a href="http://freesound.iua.upf.edu/samplesViewSingle.php?id=19987">"Acclivity"</a>, Free Sound Project</p>
</div>
<div id="ball-container" class="balls">
<img src="image/ball.gif" alt="" />
</div>
</body>
</html>

View file

@ -0,0 +1,189 @@
var balls = [];
var canvasX = 0;
var canvasY = 0;
var timer = null;
var m_lastX = 0;
var m_lastY = 0;
var M_SPACE = 24;
var B_VMIN = 5;
var B_VMAX = 5;
var B_WIDTH = 13;
var B_HEIGHT = 13;
var useMouse = null;
var ballSound = null;
var ballPopSound = null;
function rnd(n) {
return Math.random()*n;
}
function rndI(n) {
return parseInt(rnd(n));
}
function createBall(oParent) {
oParent.appendChild(balls[0].cloneNode(true));
initBall(balls[balls.length-1],balls.length);
}
function createBallAtMouse(e) {
e = e?e:event;
createBall(document.getElementById('ball-container'));
with (balls[balls.length-1]) {
_x = e.clientX;
_y = e.clientY;
if (useMouse.checked != false) {
_vX = (m_lastX-e.clientX)*-0.7;
_vY = (m_lastY-e.clientY)*-0.7;
} else {
_vX = 0;
_vY = 0;
}
}
moveBall(balls[balls.length-1]);
}
function initBall(oBall,i) {
oBall._id = 'ball'+i;
oBall._active = true;
oBall._x = rnd(canvasX);
oBall._y = rnd(canvasY);
oBall._vX = B_VMIN+rnd(B_VMAX)*(Math.random()>0.5?1:-1);
oBall._vY = B_VMIN+rnd(B_VMAX);
oBall.style.display = 'block';
}
function moveBall(oBall) {
oBall._x += oBall._vX;
oBall._y += (oBall._vY++); // gravity!
var bounce = false;
if ((oBall._vX>0 && oBall._x+oBall._vX+B_WIDTH>canvasX) || (oBall._vX<0 && oBall._x+oBall._vX<0)) {
oBall._vX *= -1;
bounce = true;
}
if ((oBall._vY>0 && oBall._y+oBall._vY+B_HEIGHT>canvasY) || (oBall._vY<0 && oBall._y+oBall._vY<0)) {
// bounce on Y axis - with resistance on both axes
if (oBall._vY>0) oBall._y = canvasY-B_HEIGHT; // bounce exactly from bottom
oBall._vY *= -(oBall._vY>1?0.6:1);
bounce = true;
if (Math.abs(oBall._vX)>0.5) {
oBall._vX *= 0.85;
} else {
oBall._vX = 0;
}
if (Math.abs(oBall._vY)<=3 && Math.abs(oBall._vX==0)) {
oBall._active = false;
bounce = false;
ballPopSound.play();
oBall.style.display = 'none';
}
}
oBall.style.left = oBall._x+'px';
oBall.style.top = oBall._y+'px';
if (bounce) ballSound.play({pan:getPan(oBall._x,canvasX)});
}
function getPan(x,canvasX) {
var pos = x/canvasX;
var pan = null;
if (pos<=0.4) {
pan = Math.floor(-100+(pos/0.4*100));
} else if (pos>0.4 && pos<=0.5) {
pan = 0;
} else {
pan = Math.floor(pos*100);
}
return pan;
}
function animateStuff() {
for (var i=balls.length; i--;) {
if (balls[i]._active) moveBall(balls[i]);
}
}
function startAnimation() {
if (!timer) timer = setInterval(animateStuff,20);
document.getElementById('b-start').disabled = true;
document.getElementById('b-stop').disabled = false;
}
function stopAnimation() {
if (!timer) return false;
clearInterval(timer);
timer = null;
document.getElementById('b-start').disabled = false;
document.getElementById('b-stop').disabled = true;
}
function mouseDown(e) {
e = e?e:event;
m_lastX = e.clientX;
m_lastY = e.clientY;
document.onmousemove = mouseMove;
document.onmouseup = mouseUp;
return false;
}
function mouseMove(e) {
e = e?e:event;
if (Math.abs(e.clientX-m_lastX)>M_SPACE || Math.abs(e.clientY-m_lastY)>M_SPACE) {
createBallAtMouse(e);
m_lastX = e.clientX;
m_lastY = e.clientY;
}
return false;
}
function mouseUp() {
document.onmousemove = null;
document.onmouseup = null;
}
function init() {
ballSound = soundManager.createSound({
id: 'ballSound',
url: '../animation/audio/fingerplop.mp3',
volume: 50,
multiShot: true,
autoLoad: true
});
ballPopSound = soundManager.createSound({
id: 'ballPopSound',
url: '../animation/audio/fingerplop2.mp3',
volume: 50,
multiShot: true,
autoLoad: true
});
balls = document.getElementById('ball-container').getElementsByTagName('img');
for (var i=balls.length; i--;) {
initBall(balls[i],i);
}
useMouse = document.getElementById('useMouse');
useMouse.checked = true;
getWindowCoords();
startAnimation();
document.onmousedown = mouseDown;
}
// I know this is kinda broken in Opera.
getWindowCoords = (navigator.userAgent.toLowerCase().indexOf('opera')>0||navigator.appVersion.toLowerCase().indexOf('safari')!=-1)?function() {
canvasX = window.innerWidth;
canvasY = window.innerHeight;
}:function() {
canvasX = document.documentElement.clientWidth||document.body.clientWidth||document.body.scrollWidth;
canvasY = document.documentElement.clientHeight||document.body.clientHeight||document.body.scrollHeight;
}
window.onresize = getWindowCoords;
soundManager.flashVersion = 9;
soundManager.url = '../../swf/';
soundManager.useHighPerformance = true;
soundManager.debugMode = false; // disable debug mode
soundManager.defaultOptions.multiShot = true;
soundManager.onload = function() {
// soundManager is ready to use (create sounds and so on)
init();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Some files were not shown because too many files have changed in this diff Show more