Music Player - SEF 2017
Software Edu Fest Conference Resources
by Jee Hoon
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/audiojs/1.0.1/audio.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.19.1/TweenMax.min.js"></script>
<!----------------------------------------------------------------------------
코드 참고 URL: https://goo.gl/Lf1A1M
--------------------------------------------------------------------------->
<!-- album-container -->
<div class="album-container is-center">
<!-- 1.1 Audio Control: 여기에 사운드를 재생할 <audio> HTML 코드를 작성합니다. -->
<audio class="album-player" preload="auto"></audio>
<!-- playlist-container -->
<nav class="playlist-container is-center-x is-open">
<div class="playlist" role="group">
<!-- 1.2 TITLE: 여기에 뮤직 플레이어 타이틀 컨텐츠를 추가해봅니다. -->
<h2 class="title"> Nine Track Mind - Chalie Puth </h2>
<ol class="list">
<li class="item">
<span class="is-number">01</span> <span class="is-divider">|</span>
<a role="button" href="01-OneCallAway.compressed.mp3">One Call Away</a>
<time class="runtime">03:14</time>
</li>
<li class="item">
<span class="is-number">02</span> <span class="is-divider">|</span>
<a role="button" href="02-Dangerously.compressed.mp3">Dangerously</a>
<time class="runtime">03:19</time>
</li>
<li class="item">
<span class="is-number">03</span> <span class="is-divider">|</span>
<a role="button" href="03-MarvinGaye.compressed.mp3">Marvin Gaye (feat. Meghan Trainor)</a>
<time class="runtime">03:10</time>
</li>
</ol>
</div>
</nav>
<!-- 1.3 ALBUM COVER: 앨범 커버 이미지를 CD 이미지로 교체 해봅니다. -->
<img
class="album-cover is-rwd"
src="https://raw.githubusercontent.com/yamoo9/yamoo9.github.io/master/sef/media/cover.jpg"
width="1000" height="1000" alt="">
<!-- album-control -->
<div class="album-control is-center is-flex-center" role="group">
<button type="button" class="button is-play"...
CSS
@charset "UTF-8";
html {
-webkit-font-smoothing: antialiased;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004);
font-size: 10px;
}
body {
box-sizing: border-box;
min-height: 100vh;
margin: 0;
font-family: "Spoqa Han Sans", "Sans-serif";
}
body *,
body *::before,
body *::after {
box-sizing: inherit;
}
nav ul,
nav ol {
list-style: none;
margin-top: 0;
margin-bottom: 0;
padding-left: 0;
}
.button {
/* 2.1 버튼 스타일링: UX(사용자 경험) 고려, 마우스 커서 손 모양 변경 */
cursor: pointer;
border: none;
padding: 0;
background: transparent;
}
/* -------------------------------------------------
* 접근성 감춤
*/
.a11y-hidden {
overflow: hidden;
position: absolute;
clip: rect(0 0 0 0);
/* IE 6,7 */
clip: rect(0, 0, 0, 0);
width: 1px;
height: 1px;
margin: -1px;
border: 0;
padding: 0;
}
.a11y-hidden.focusable:focus {
overflow: visible;
position: static;
clip: auto;
width: auto;
height: auto;
margin: 0;
}
caption.a11y-hidden {
position: static;
}
.is-center {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.is-center-x {
left: 50%;
transform: translateX(-50%);
}
.is-center-y {
top: 50%;
transform: translateY(-50%);
}
.is-flex-center {
display: -ms-flexbox;
display: flex;
-ms-flex-pack: center;
justify-content: center;
-ms-flex-align: center;
align-items: center;
}
.is-rwd {
width: 100%;
height: auto;
}
body {
font-family: "Spoqa Han Sans";
background: radial-gradient(circle, #504bd1 35%, #35318a);
}
body::before {
content: '';
opacity: 1;
position: fixed;
z-index: 5;
top: 0;
right: 0;
bottom: 0;
left: 0;
/* 2.2 배경 그레디언트 스타일링 */
background: radial-gradient(circle, #393939 35%, #121212);
transition: opacity 1.4s ease-out;
}
body.is-play::before {
opacity: 0;
}
/* =ALBUM */
.album-container {
position: fixed;
z-index: 100;
max-width: 600px;
max-height: 600px;
width: 60vw;
height: 60vw;
}
.album-cover {
position: absolute;
top: 0;
...
JavaScript
(function(global, $){
'use strict';
//////////////
// 모바일 감지
//////////////
var userAgent = global.navigator.userAgent.toLowerCase();
var mobile_devices = ['iphone', 'ipad', 'android'];
var document = global.document;
var html = document.documentElement;
for (var d of mobile_devices){
if ( userAgent.includes(d) ) {
html.classList.add('mobile');
break;
}
}
//////////////
// 타임라인 컨트롤
//////////////
// 3.1 타임라인 객체 애니메이션 설정 - 앨범 커버 회전 시키기
var tl = new TimelineMax({paused: true});
tl.from('.album-cover', 360, { rotate: -720, ease: Power0.easeIn });
function wiggle(selector, duration){
$(selector).each(function() {
wiggleProp(this, 'scale', 0.45, duration);
wiggleProp(this, 'rotation', -2, 2);
// wiggleProp(this, 'x', -3, 3);
wiggleProp(this, 'y', -3, 3);
});
}
function wiggleStop(selector) {
TweenMax.killTweensOf(selector);
TweenMax.staggerTo(selector,0.2,{scale:1},0.05);
}
function wiggleProp(element, prop, min, max, duration) {
var duration = duration || Math.random() * (0.1 - 0.2) + 0.1;
var tweenProps = {
ease: Power1.easeInOut,
onComplete: wiggleProp,
onCompleteParams: [element, prop, min, max]
};
tweenProps[prop] = Math.random() * (max - min) + min;
TweenMax.to(element, duration, tweenProps);
}
// --------------------------------------------------------------------------------
////////////
// 앨범 컨트롤
////////////
var $body = $('body'),
$container = $('.album-container'),
$playlist = $('.playlist-container', $container),
$playlist_items = $('.item', $playlist),
$cover = $('.album-cover', $container),
$buttons = $('.button', $container),
audio;
$.each($buttons, function(i) {
var $button = $buttons.eq(i);
$button.on('click', $.proxy(buttonControl, $button));
});
function buttonControl(e) {
...