first commit of free version
BIN
admin/custom/soundmanager/demo/360-player/360 button - large.psd
Normal file
BIN
admin/custom/soundmanager/demo/360-player/360 button.psd
Normal file
After Width: | Height: | Size: 627 B |
After Width: | Height: | Size: 752 B |
After Width: | Height: | Size: 329 B |
After Width: | Height: | Size: 408 B |
BIN
admin/custom/soundmanager/demo/360-player/360-button-pause.gif
Normal file
After Width: | Height: | Size: 329 B |
BIN
admin/custom/soundmanager/demo/360-player/360-button-pause.png
Normal file
After Width: | Height: | Size: 329 B |
BIN
admin/custom/soundmanager/demo/360-player/360-button-play-2x.png
Normal file
After Width: | Height: | Size: 693 B |
After Width: | Height: | Size: 898 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 477 B |
BIN
admin/custom/soundmanager/demo/360-player/360-button-play.gif
Normal file
After Width: | Height: | Size: 441 B |
BIN
admin/custom/soundmanager/demo/360-player/360-button-play.png
Normal file
After Width: | Height: | Size: 357 B |
After Width: | Height: | Size: 889 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 881 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1009 B |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1001 B |
After Width: | Height: | Size: 1.3 KiB |
@ -0,0 +1,150 @@
|
||||
/* larger canvas, spectrum + EQ visualization and other items */
|
||||
|
||||
.ui360-vis,
|
||||
.ui360-vis .sm2-360ui,
|
||||
.sm2-inline-list .ui360-vis {
|
||||
/* size of the container for the circle, etc. */
|
||||
width:256px;
|
||||
height:256px;
|
||||
}
|
||||
|
||||
.ui360-vis {
|
||||
position:relative;
|
||||
/* a little extra spacing */
|
||||
padding-top:1px;
|
||||
padding-bottom:1px;
|
||||
padding-left:248px;
|
||||
margin-left:0px;
|
||||
background-position:22.6% 50%; /* (~109px) initial play button position */
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360-vis {
|
||||
cursor:pointer
|
||||
}
|
||||
|
||||
.ui360-vis a {
|
||||
font:14px "helvetica neue",helvetica,monaco,lucida,terminal,monospace;
|
||||
white-space:nowrap;
|
||||
text-indent:0px; /* undo inline style */
|
||||
top:46%; /* ehh. */
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360-vis a {
|
||||
line-height:256px;
|
||||
top:auto;
|
||||
}
|
||||
|
||||
.ui360-vis .sm2-360ui {
|
||||
margin-left:-256px;
|
||||
}
|
||||
|
||||
.ui360-vis .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-vis,
|
||||
.sm2-inline-list .ui360-vis .sm2-360ui {
|
||||
margin-left:0px;
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360-vis {
|
||||
margin:8px 13px 7px 0px;
|
||||
padding-left:0px;
|
||||
background-position:50% 50%; /* initial play button position */
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360-vis .sm2-360ui {
|
||||
border:1px solid #eee;
|
||||
/* offset the border */
|
||||
margin-left:-1px;
|
||||
margin-top:-1px;
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360-vis a {
|
||||
position:absolute;
|
||||
display:inline;
|
||||
left:0px;
|
||||
bottom:0px;
|
||||
top:1px;
|
||||
width:100%; /* 2px padding in box */
|
||||
height:99%; /* dumb vertical hack */
|
||||
*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;
|
||||
border-radius:0px;
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360 a:hover {
|
||||
background-color:transparent; /* reset */
|
||||
}
|
||||
|
||||
.sm2-inline-list .ui360-vis:hover .sm2-360ui,
|
||||
.sm2-inline-list .ui360-vis a.sm2_link:hover,
|
||||
.sm2-inline-list .ui360-vis a.sm2_link:active,
|
||||
.sm2-inline-list .ui360-vis a.sm2_link:focus {
|
||||
background-color:transparent;
|
||||
}
|
||||
|
||||
/* Use a bigger loading image for this layout */
|
||||
|
||||
.ui360-vis .sm2-360btn,
|
||||
.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,
|
||||
.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn {
|
||||
width:48px;
|
||||
height:48px;
|
||||
margin-left:-24px;
|
||||
margin-top:-24px;
|
||||
border-radius: none;
|
||||
}
|
||||
|
||||
.ui360-vis,
|
||||
.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn,
|
||||
.ui360-vis .sm2-360btn-default {
|
||||
background:transparent url(360-button-vis-play.png) no-repeat 50% 50%;
|
||||
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAABuVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7++lpaXr6+uAgIDk5OQzMzPt7e1tbW3n5+dgYGDW1tZNTU10dHQ5OTnw8PCvr6/e3t6JiYlAQEDb29vo6OgrKyuqqqrq6uq4uLjf399AQEDGxsbq6uqAgIDY2Nje3t61tbXp6enU1NTu7u7r6+vl5eXt7e2fn5/n5+fDw8Ph4eHv7+/t7e3CwsLW1tbu7u7b29vw8PDm5uYgICDp6enY2Nji4uLo6Ojm5uakpKTS0tLPz8/h4eHw8PDs7Ozj4+Pa2trg4ODx8fHT09Pk5OTPz8/S0tLBwcGmpqawsLCOjo7h4eHn5+fo6OgAAADY2NjNzc3n5+cAAADd3d3Gxsbu7u7t7e0AAADX19fl5eXi4uLf39/Hx8fn5+fs7Ozg4ODR0dHX19e4uLjv7+/z8/P09PTy8vL19fXv7+/n5+fx8fH29vbs7Ozq6urm5ubo6Ojw8PDu7u7p6enr6+sAAAB/f3/Z2dn39/fh4eGOjo4ODg7t7e3l5eWWlpba2tqjo6NVVVXk5OTe3t65ubnMzMzExMTf39/GxsampqZiYmJNcTiZAAAAbXRSTlMAAQIEAwcFCAb5EdAImAXpB6oIUAoLCfsgZQ0EVrsGEr4ZYQgbsgpUYxikNd/aatQQli+R7rlUUdas6+8I+VaFruoOOV/S8Nq5sWL8UqmKUFsuHyTcrtsJm0z7C49V3NMKkdKXuk7S7oVeVSv7tAAEVwAAAu5JREFUeF6llmVz3DwURmNLsr1pmJmZmZmxzMwsybS8gXJfhl9cKXbHEK+TmZ4P/nDnOXN1NbalHD8CQ7QRGDmhnIQhBDYQnkhheRECSVIQQrLMHookAciUkHhBw1zVwuLShcJIpPDC0uJC1VxDQTaFx1srSvM3DUxU1TRVlWBjM7+0opUrQaupLSnrLK7ELIepwaCYmbiyuLOspJY38eeLykdGxzDhYQfKCmOjI+VFPkMQYF7NZD0l2DgFJrR+siYPegxBzBvqeoQxpgGw8qOuoTz3HGw9udUPCaFZIORhdS5blZOHjXWDBIdABusanb0S4MpqEw4XcNPqCrQFQQTN+XwPQ8CY5jcDUbB3KLdlg6hnQDZacqEgWA3a2rF6Jri9zWohwI6dXXK2QHZ3OqBw0qC7B6vnAPd0sxZMkHr7VNPD34YZgNrXK3EBSgPU9HJ4eIQDDDogQS4ow4QJxy4+MmKs4oYJZFhhggjQuMoKHoHzn3bsQx1HQOTClOkXLP6lviZTtjCjmn7B5g/izqszliBHTB+HDhl3PSJbwnxSS3n45HDkVLXkvCWg5Uws7eHgJ98/uKqxzLI9w3o6oXuwhd+OPNVEet0WtnU9/sWNJfz1u6cY1/VtLghQuRgk/PmBmT7hogJPXo3L8YQed3Nw8PWfuB89Eb8scUGUrl33DfH/N93BGeH6NUnkArh1O5FOuNETp2GR27cAE/iaJu6mz8HdCQnan+i96XQmdgaZ9PQ9+xMVoPJgNhrNhBKNzj5Q+E/AavH4SSz6OZRo7Mlj3oDDp7jyPJoKJfr8CpvAOUrQi6eppJaVZOrpCwTdP1cgr93UjKxoN9dka2KX8ealZtBADO3lG2+e7xRAd7Y0igOg2tYdBKD/CBIBenf/lYGJD2y8uv8OgaBDDkry3v57SlQXhL7f35OlwJOXGUBBl571JykmzCIE02T/s0tIASyf/R6Arr59fcM62G+8fnsVhdwFwq4Ov345Of/15wd0RYY81HHUTQAAAABJRU5ErkJggg==);
|
||||
*background-image:url(360-button-vis-play.png);
|
||||
_background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.ui360-vis:hover .sm2-360btn,
|
||||
.ui360-vis .sm2-360btn-default:hover,
|
||||
.ui360-vis .sm2-360ui.sm2_paused .sm2-360btn:hover {
|
||||
background:transparent url(360-button-vis-play-light.png) no-repeat 50% 50%;
|
||||
_background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
|
||||
.ui360-vis .sm2-360ui.sm2_playing .sm2-360btn:hover,
|
||||
.ui360-vis .sm2-360btn-playing:hover {
|
||||
background:transparent url(360-button-vis-pause-light.png) no-repeat 50% 50%;
|
||||
_background:transparent url(360-button-vis-pause-light.gif) no-repeat 50% 50%;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.ui360-vis {
|
||||
/* non-JS / before-loaded state */
|
||||
background-position: 21% 50%;
|
||||
_background:transparent url(360-button-vis-play.gif) no-repeat 21% 50%; /* IE 6-only: special crap GIF */
|
||||
}
|
||||
|
||||
.ui360-vis .sm2-360btn-default {
|
||||
/* real button, post-loaded state */
|
||||
_background:transparent url(360-button-vis-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */
|
||||
}
|
||||
|
||||
.ui360-vis .sm2-360ui.sm2_dragging .sm2-360btn {
|
||||
visibility: hidden;
|
||||
}
|
316
admin/custom/soundmanager/demo/360-player/360player.css
Normal file
@ -0,0 +1,316 @@
|
||||
/* General warning: Beta-ish. Code could be a bit cleaner. */
|
||||
|
||||
.ui360, /* entire UI */
|
||||
.sm2-360ui { /* canvas container */
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.ui360 {
|
||||
margin-bottom: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.ui360,
|
||||
.sm2-360ui {
|
||||
min-width:50px; /* should always be at least this. */
|
||||
min-height:50px;
|
||||
}
|
||||
|
||||
.sm2-360ui {
|
||||
width:50px;
|
||||
height:50px;
|
||||
}
|
||||
|
||||
.sm2-360ui {
|
||||
/* slight inner shadow + BG color + border */
|
||||
background-color: #f9f9f9;
|
||||
background-color: rgba(0,0,0,0.025);
|
||||
box-shadow: inset 0px 0px 8px rgba(0,0,0,0.15);
|
||||
/* a little radii, modern browsers only */
|
||||
border-radius: 100%;
|
||||
-webkit-transition: all 0.1s ease-in-out;
|
||||
-moz-transition: all 0.1s ease-in-out;
|
||||
transition: all 0.1s ease-in-out;
|
||||
/* specifics */
|
||||
-moz-transition-property: background, border, box-shadow;
|
||||
-webkit-transition-property: background, border, box-shadow;
|
||||
transition-property: background, border, box-shadow;
|
||||
}
|
||||
|
||||
.sm2-360ui:hover {
|
||||
background-color: rgba(0,0,0,0.1);
|
||||
border-color: rgba(0,0,0,0.15);
|
||||
box-shadow: inset 0px 0px 5px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.ui360,
|
||||
.ui360 * {
|
||||
vertical-align:middle;
|
||||
}
|
||||
|
||||
.sm2-360ui {
|
||||
position:relative;
|
||||
display:inline-block; /* firefox 3 et al */
|
||||
float:left; /* IE 6+7, firefox 2 needs this, inline-block would work with fx3 and others */
|
||||
*display:inline;
|
||||
clear:left;
|
||||
}
|
||||
|
||||
.sm2-360ui.sm2_playing,
|
||||
.sm2-360ui.sm2_paused {
|
||||
/* bump on top when active */
|
||||
z-index:10;
|
||||
}
|
||||
|
||||
.ui360 a { /* .sm2_link class added to playable links by SM2 */
|
||||
float:left;
|
||||
display:inline;
|
||||
position:relative;
|
||||
color:#000;
|
||||
text-decoration:none;
|
||||
left:3px; /* slight spacing on left UI */
|
||||
top:18px; /* vertical align */
|
||||
text-indent:50px; /* make room for UI at left */
|
||||
}
|
||||
|
||||
.ui360 a.sm2_link { /* SM2 has now started */
|
||||
text-indent:0px; /* UI now in place. */
|
||||
}
|
||||
|
||||
.ui360 a,
|
||||
.ui360 a:hover,
|
||||
.ui360 a:focus {
|
||||
padding:2px;
|
||||
margin-left:-2px;
|
||||
margin-top:-2px;
|
||||
}
|
||||
|
||||
.ui360 a:hover,
|
||||
.ui360 a:focus {
|
||||
background:#eee;
|
||||
border-radius:3px;
|
||||
outline:none;
|
||||
}
|
||||
|
||||
.ui360 .sm2-canvas {
|
||||
position:absolute;
|
||||
left:0px;
|
||||
top:0px;
|
||||
}
|
||||
|
||||
.ui360 .sm2-canvas.hi-dpi {
|
||||
/* hi-dpi / "retina" screens */
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
-moz-transform: scale(0.5);
|
||||
-ms-transform: scale(0.5);
|
||||
-webkit-transform: scale(0.5);
|
||||
transform: scale(0.5);
|
||||
}
|
||||
|
||||
.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 {
|
||||
/* devious center-alignment tweak for Safari (might break things for others.) */
|
||||
/* no longer applies. */
|
||||
/*
|
||||
text-indent:1px;
|
||||
*/
|
||||
}
|
||||
|
||||
.ui360 .sm2-cover {
|
||||
position:absolute;
|
||||
left:0px;
|
||||
top:0px;
|
||||
width:100%;
|
||||
height:100%;
|
||||
z-index:2;
|
||||
display:none;
|
||||
background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==); /* old-skool bug: IE 9 won't catch mouse events otherwise. /smash */
|
||||
}
|
||||
|
||||
.ui360 .sm2-360btn {
|
||||
position:absolute;
|
||||
display:block;
|
||||
top:50%;
|
||||
left:50%;
|
||||
/*
|
||||
width:22px;
|
||||
height:22px;
|
||||
margin-left:-11px;
|
||||
margin-top:-11px;
|
||||
*/
|
||||
/* by default, cover whole space. make smaller when playing. */
|
||||
width:50px;
|
||||
height:50px;
|
||||
margin-left:-25px;
|
||||
margin-top:-25px;
|
||||
border-radius: 25px;
|
||||
cursor:pointer;
|
||||
z-index:3;
|
||||
}
|
||||
|
||||
.ui360 .sm2-360data {
|
||||
display:inline-block;
|
||||
font-family:helvetica;
|
||||
}
|
||||
|
||||
.sm2-inline-block .ui360 .sm2-360btn,
|
||||
.ui360 .sm2-360ui.sm2_playing .sm2-360btn,
|
||||
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||
/* smaller clickable button, in center */
|
||||
width:22px;
|
||||
height:22px;
|
||||
margin-left:-11px;
|
||||
margin-top:-11px;
|
||||
}
|
||||
|
||||
.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,
|
||||
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||
background:transparent url(360-button-play.png) no-repeat;
|
||||
/* if you change the source image, update these data: URIs as well. */
|
||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABYAAAAWCAYAAADEtGw7AAABoUlEQVR42sWVu2oCQRhGU/s8gpVYJeQJNkZSbiH4QNuLlQZS21sJayGYaOEFVFDxNiremj9zig2uzk5YQpKFg8PMd75ZZle9E5Ff4e+Ll8tlQuNoPI2vUcCYOdbIxCmm9F5T0YgNMmS/LebSwWdNa7VayXq9ls1mI9vtVna7nQBj5lgjQxYHN7KY3QkiUbDf7+V4PMrpdArBHGtkyOJc3/n1mVaUUl+F5/PZSrABDi4dpmKH3QkixQEHlw5TsccZmsRCoSD1et1ajkuHqdg/HA5GKZPJCOTzeanVasYMLh2mYsXDIGAoDuG6rlSr1WCdBxrcsTIWazgrQiHS6bSRYJ3XDzeq2O/3+9Ltdm9IpVIhstmslEqlUAY36ii8ZrMpjUbjhmQyKeA4jhSLRWMGN+rhOZ1Oh8ANuVxOyuUy40hwo163RK/XeyPQbrdjgYNr/ILAYDB41Gf1wZnFAQfX+iM0HA5fxuPx+2g0Ej22QoYsDq61mGsymTxMp9NX/Sk2yJDFsRZfXpzXbDZ7WiwW3nw+9zUKGDPHGpkL5V//mn7OJyJZApyzeUS5AAAAAElFTkSuQmCC);
|
||||
/* hi-dpi, we presume */
|
||||
background-image: none, url(360-button-play-2x.png);
|
||||
background-size: 22px 22px;
|
||||
*background-image: url(360-button-play.png);
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.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: 14px 50%;
|
||||
_background:transparent url(360-button-play.gif) no-repeat 14px 50%; /* IE 6-only: special crap GIF */
|
||||
}
|
||||
|
||||
.ui360 .sm2-360btn-default,
|
||||
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||
background-position:50% 50%;
|
||||
_background:transparent url(360-button-play.gif) no-repeat 50% 50%; /* IE 6-only: special crap GIF */
|
||||
}
|
||||
|
||||
.ui360 .sm2-360btn-default,
|
||||
.ui360 .sm2-360ui.sm2_paused .sm2-360btn {
|
||||
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%;
|
||||
/* hi-dpi, we presume */
|
||||
background-image: none, url(360-button-play-light-2x.png);
|
||||
background-size: 22px 22px;
|
||||
_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-image: none, url(360-button-pause-light-2x.png);
|
||||
background-size: 22px 22px;
|
||||
_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,
|
||||
.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-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;
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
<!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° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization, basic example</title>
|
||||
<meta name="robots" content="noindex" />
|
||||
<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.setup({
|
||||
// path to directory containing SM2 SWF
|
||||
url: '../../swf/'
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (threeSixtyPlayer.config.useWaveformData || threeSixtyPlayer.flash9Options.useEQData || threeSixtyPlayer.flash9Options.usePeakData) {
|
||||
// even if HTML5 supports MP3, prefer flash so the visualization features can be used.
|
||||
soundManager.preferFlash = 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° 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 < 9 (too slow.) Data not implemented 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 ui360-vis"><a href="../../demo/mpc/audio/CRASH_1.mp3">Crash 1</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_5.mp3">Crash 5</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="../../demo/mpc/audio/CRASH_6.mp3">Crash 6</a></div>
|
||||
<div class="ui360 ui360-vis"><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 ui360-vis"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: LOUD)</a></div>
|
||||
<div class="ui360 ui360-vis"><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>
|
@ -0,0 +1,360 @@
|
||||
<!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° MP3 player UI demo (SoundManager 2): Javascript + Canvas Visualization</title>
|
||||
<meta name="robots" content="noindex" />
|
||||
<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.setup({
|
||||
// path to directory containing SM2 SWF
|
||||
url: '../../swf/'
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (threeSixtyPlayer.config.useWaveformData || threeSixtyPlayer.flash9Options.useEQData || threeSixtyPlayer.flash9Options.usePeakData) {
|
||||
// even if HTML5 supports MP3, prefer flash so the visualization features can be used.
|
||||
soundManager.preferFlash = 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">
|
||||
|
||||
body {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#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%;
|
||||
}
|
||||
|
||||
.ui360 span {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
</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° Player Demo</a>: JS + Canvas Visualization</h1>
|
||||
|
||||
<p class="note" style="color:#666;margin-top:0.5em;margin-bottom:0.5em">Canvas-based UI with visualization options. <b>Note: Spectrum/EQ visualizations disabled for IE < 9 (too slow.) Data is not implemented 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° player UI">default 360° 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="Amount to downsample waveform data by"></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="Amount to downsample EQ data by"></div>
|
||||
</dd>
|
||||
|
||||
<dt>Ring Thickness</dt>
|
||||
<dd class="title">(Scale)</dd>
|
||||
<dd>1-200</dd>
|
||||
<dd class="control">
|
||||
<div class="bar" title="Click to move here"></div>
|
||||
<div class="slider" title="Scale factor for the ring width"></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 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/The%20Fugitives%20-%20Graffiti%20Sex.mp3">The Fugitives - Graffiti Sex</a></div>
|
||||
<div class="ui360 ui360-vis"><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 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20I%20Tried.mp3">SonReal - I Tried</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/SonReal%20-%20People%20Asking.mp3">SonReal - People Asking</a></div>
|
||||
<div class="ui360 ui360-vis"><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>: "Graffiti Sex" courtesy of <a href="http://www.fugitives.ca/" title="A group of musicians, poets, and multi-instrumentalists from Vancouver, Canada">The Fugitives</a>. "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 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/gong-192kbps.mp3">32" Chau Gong Sounds</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/mpc/20090207%20-%20Loverman.mp3">20090207 - Loverman</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="http://freshly-ground.com/data/audio/sm2/dialup.mp3">56K Modem dial-up sound (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="../../demo/_mp3/1hz-10khz-sweep.mp3">1-10 Khz Sweep (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
|
||||
<div class="ui360 ui360-vis"><a href="../../demo/_mp3/sine,%20square,%20sawtooth,%20rando.mp3">Sine, Square, Sawtooth, Wave (Warning: <span style="color:#ff3333">LOUD</span>)</a></div>
|
||||
</div>
|
||||
|
||||
<p class="note medium-note" style="clear:left">56K Modem sound (Creative Commons license) via <a href="http://www.freesound.org/samplesViewSingle.php?id=16475">dialup.mp3</a>, from freesound.org user <a href="http://www.freesound.org/usersViewSingle.php?id=54447">Jlew</a>.</p>
|
||||
|
||||
|
||||
<h2 style="clear:left;padding-top:1em">Variant: Annotations/meta-data</h2>
|
||||
|
||||
|
||||
<ul class="ui360playlist">
|
||||
|
||||
<li>
|
||||
|
||||
<div class="ui360 ui360-vis">
|
||||
<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 ui360-vis">
|
||||
<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>
|
@ -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;
|
||||
}
|
@ -0,0 +1,750 @@
|
||||
/*
|
||||
Ancient fireworks slider control code (2005)
|
||||
Kinda/sorta refactored for SM2 360 demo
|
||||
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.scaleArcWidth = (self.controls[5].value/100);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
if (threeSixtyPlayer.lastSound) {
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.circleDiameter = self.controls[0].value;
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.circleRadius = self.controls[0].value/2;
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.waveformDataLineRatio = (self.controls[1].value/100)*2;
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.waveformDataDownsample = (self.controls[2].value);
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.eqDataLineRatio = parseInt((self.controls[3].value/100)*3*1000)/1000;
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.eqDataDownsample = (self.controls[4].value);
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.useEQData = (document.getElementById('disabled-1').checked?true:false);
|
||||
|
||||
// radio buttons
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.useWaveformData=(document.getElementById('use-waveform').checked?true:false);
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.waveformDataOutside = document.getElementById('waveform-inside').checked?false:true;
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.eqDataOutside = document.getElementById('eq-inside').checked?false:true;
|
||||
|
||||
threeSixtyPlayer.lastSound._360data.useAmplifier = (document.getElementById('use-amplifier').checked?true:false);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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\
|
||||
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(){
|
||||
// default values for controls
|
||||
var values = [
|
||||
256,
|
||||
65,
|
||||
40,
|
||||
72,
|
||||
48,
|
||||
100
|
||||
];
|
||||
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 window.addEventListener !== 'undefined' ? o.addEventListener(evtName,evtHandler,false) : o.attachEvent('on'+evtName,evtHandler);
|
||||
}
|
||||
|
||||
function removeEvent(o,evtName,evtHandler) {
|
||||
typeof window.removeEventListener !== '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,
|
||||
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,
|
||||
scaleArcWidth: 1, // thickness factor of playback progress ring
|
||||
useAmplifier: true
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
64
admin/custom/soundmanager/demo/360-player/demo.css
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 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: -0.005em; /* 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;
|
||||
}
|
||||
|
||||
#left {
|
||||
max-width:56em;
|
||||
margin-left:1em;
|
||||
}
|
BIN
admin/custom/soundmanager/demo/360-player/icon_loading_dots.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 493 B |
After Width: | Height: | Size: 2.4 KiB |
171
admin/custom/soundmanager/demo/360-player/index.html
Normal file
@ -0,0 +1,171 @@
|
||||
<!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° 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.setup({
|
||||
// path to directory containing SM2 SWF
|
||||
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 */
|
||||
|
||||
body {
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
#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° Player</a>: JavaScript + Canvas UI</h1>
|
||||
|
||||
<p class="note" style="color:#666;margin-top:0.5em;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° 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;min-width:200px"> <!-- 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:150px">
|
||||
|
||||
<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><div class="<span>ui360</span>">
|
||||
<a href="/path/to/an.mp3">play "an.mp3"</a>
|
||||
</div></code></pre>
|
||||
|
||||
</div>
|
||||
|
||||
<p>When the 360 player script loads, it adds a <code>UI</code> template to the block, prepending it in front of the MP3 link:</p>
|
||||
|
||||
<pre class="block"><code><div class="<span>ui360</span>">
|
||||
<span><span><-- dynamically-inserted block --></span></span>
|
||||
<div class="<span>ui</span>">
|
||||
<canvas class="<span>sm2-canvas</span>"></canvas>
|
||||
<span class="<span>sm2-360btn</span>"></span>
|
||||
<div class="<span>sm2-timing</span>"></div>
|
||||
<div class="<span>sm2-cover</span>"></div>
|
||||
</div>
|
||||
<span><span><-- /UI --></span></span>
|
||||
<a href="<span>/path/to/an.mp3</span>">
|
||||
</div></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° 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>
|
||||
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>;
|
||||
height:<span>50px</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>
|
1416
admin/custom/soundmanager/demo/360-player/script/360player.js
Normal file
@ -0,0 +1,674 @@
|
||||
/** @license
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|