hw-gs-player

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 378c865761b9b7bacfaed7d0837e9211d69b63da
parent 79c53357f3cc5b9b649920a6226e3d67287fc297
Author: Sunny <122193933+Sunny-JP@users.noreply.github.com>
Date:   Tue, 18 Mar 2025 02:29:55 +0900

Dev 5 (#13)

* add small player

* monospaced time font

* removed not using songname
Diffstat:
Msrc/App.vue | 2+-
Msrc/assets/AlbumsList.json | 25++++++++++++++++++++-----
Msrc/components/About.vue | 6+++---
Msrc/components/AlbumList.vue | 10+++++++++-
Msrc/components/Enquiries.vue | 6+++---
Msrc/components/Info.vue | 4+++-
Msrc/components/Player.vue | 269++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/components/Policy.vue | 4+++-
Msrc/components/Terms.vue | 6+++---
Msrc/style.css | 198++++++++++---------------------------------------------------------------------
10 files changed, 323 insertions(+), 207 deletions(-)

diff --git a/src/App.vue b/src/App.vue @@ -23,7 +23,7 @@ onBeforeUnmount(() => { <header> <nav> <div class="title_bar"> - <p>GS Player</p> + <p><router-link to="/">GS Player</router-link></p> </div> <div class="hamburger_btn" @click.stop="MenuButton = !MenuButton"> <span class="line line_01" :class="{ 'btn_line01': MenuButton }"></span> diff --git a/src/assets/AlbumsList.json b/src/assets/AlbumsList.json @@ -1,22 +1,37 @@ [ { - "albumTitle": {"ja":"アルバム1", "en": "Album1"}, + "albumTitle": { + "ja": "アルバム1", + "en": "Album1" + }, "songs": [ { - "title": { "ja": "曲1", "en": "Song 1" }, + "title": { + "ja": "曲1", + "en": "Song 1" + }, "videoId": "QcrxntJERRs" }, { - "title": { "ja": "曲2", "en": "Song 2" }, + "title": { + "ja": "曲2", + "en": "Song 2" + }, "videoId": "BrpIRBW4g0A" } ] }, { - "albumTitle": {"ja":"アルバム2", "en": "Album2"}, + "albumTitle": { + "ja": "アルバム2", + "en": "Album2" + }, "songs": [ { - "title": { "ja": "曲A", "en": "Song A" }, + "title": { + "ja": "曲A", + "en": "Song A" + }, "videoId": "L_jWHffIx5E" } ] diff --git a/src/components/About.vue b/src/components/About.vue @@ -1,5 +1,5 @@ <template> - <div class="container"> - <h1>About</h1> - </div> + <div class="page"> + <h1>About</h1> + </div> </template> \ No newline at end of file diff --git a/src/components/AlbumList.vue b/src/components/AlbumList.vue @@ -13,9 +13,10 @@ function add_play_album(albumIndex: number) { <template> <div class="page"> <h1>Album List</h1> + 曲タイトルをクリックするとPlayer表示を切り替えられるよ <div v-for="(AlbumList, index) in AlbumList"> <button - v-on:click="add_play_album(index)"> + v-on:click="add_play_album(index)" class="button_album"> AlbumTitle: {{ AlbumList.albumTitle.ja }} </button> </div> @@ -23,4 +24,11 @@ function add_play_album(albumIndex: number) { </template> <style scoped> +.button_album { + background: #4c4c4c; + color: #ffffff; + border: none; + padding: 5px; + cursor: pointer; +} </style> \ No newline at end of file diff --git a/src/components/Enquiries.vue b/src/components/Enquiries.vue @@ -1,5 +1,5 @@ <template> - <div class="container"> - <h1>お問い合わせ</h1> - </div> + <div class="page"> + <h1>お問い合わせ</h1> + </div> </template> \ No newline at end of file diff --git a/src/components/Info.vue b/src/components/Info.vue @@ -1,3 +1,5 @@ <template> - <h1>運営者情報</h1> + <div class="page"> + <h1>運営者情報</h1> + </div> </template> \ No newline at end of file diff --git a/src/components/Player.vue b/src/components/Player.vue @@ -3,7 +3,7 @@ import { YoutubeIframe } from '@vue-youtube/component'; import { ref, computed, onUnmounted, nextTick } from 'vue'; import queue from '../queue'; -//let videoId = ref('zxt-_P_WXtM'); // example of long titleName +// let videoId = ref('zxt-_P_WXtM'); // example of long titleName // let videoId = ref('XAwXaGQwoZ0'); // example of short titleName const player = ref<any>(null); const nowTime = ref(0); @@ -22,15 +22,12 @@ const isAnimating = ref(false); const SCROLL_SPEED = 40; // px/s const WAIT_TIME = 2000; // ms - const isFullscreen = ref(false); const toggleFullscreen = () => { isFullscreen.value = !isFullscreen.value; }; - - const togglePlay = async () => { player.value?.togglePlay(); // Change play-pause }; @@ -122,7 +119,7 @@ const renderKey = queue.get_playerRenderKey(); @ready="onReady" @state-change="onStateChange" /> <div class="info_box"> - <div class="title"> + <div class="title" @click="toggleFullscreen"> <div ref="titleElement" class="scroll-container" :class="{ scrolling: isAnimating }" @@ -137,6 +134,16 @@ const renderKey = queue.get_playerRenderKey(); </div> <div class="album">{{albumTitle}}</div> <div class="time_container"> + <div v-for="(, index) in queue.get_queueTitleList()"> + #{{ index }}  + </div> + <div class="nowtime">{{ formattedNowTime }}</div> + <div class="endtime">{{ formattedEndTime }}</div> + </div> + <div class="queue" v-for="(SongName, index) in queue.get_queueTitleList()"> + #{{ index }} : {{ SongName }} + </div> + <div class="fs_time_container"> <div class="nowtime">{{ formattedNowTime }}</div> <div class="endtime">{{ formattedEndTime }}</div> </div> @@ -147,23 +154,253 @@ const renderKey = queue.get_playerRenderKey(); <div class="bar bar-right"></div> </div> </button> - <button @click="queue.onLoopButton()"> - LoopButton - </button> - Queue - <div v-for="(SongName, index) in queue.get_queueTitleList()"> - {{ index }} : {{ SongName }} - </div> </div> - <button @click="toggleFullscreen" class="toggle-btn"> - {{ isFullscreen ? '通常表示' : 'フルスクリーン' }} - </button> + <button @click="queue.onLoopButton()" class="toggle-btn-loop"> + Loop + </button> </template> <style scoped> -.toggle-btn { +/* overall frame */ +.container { + position: fixed; + bottom: 0; + width: 100%; + height: 10vw; + max-height: 60px; + background: #000000; + border-top: #404040 solid 2px; + display: flex; + align-items: center; + justify-content: center; + padding-top: clamp(1px, 2vw, 10px); + padding-bottom: clamp(1px, 2vw, 10px); + flex-direction: row; + animation: slideDown 0.25s ease forwards; +} + +.fscontainer { + display: flex; + flex-direction: column; + align-items: center; + padding: 30px; + background: #000000; + animation: slideUp 0.25s ease forwards; +} + +@keyframes slideDown { + 0% { + transform: translateY(-100px); + opacity: 0; + } + 100% { + transform: translateY(0); + } + 40%,100% { + opacity: 1; + } +} + +@keyframes slideUp { + 0% { + transform: translateY(100px); + opacity: 0; + } + 100% { + transform: translateY(0); + } + 40%,100% { + opacity: 1; + } +} + +/* title, album, time */ +.container .info_box { + margin-left: 10px; + padding: 0px 10px 0px 0px; + width: 70vw; + max-width: 300px; + color: white; +} + +.fscontainer .info_box { + position: relative; + top: 55px; + margin: 5px; + width: 100%; + max-width: 500px; +} + +.title { + overflow: hidden; + white-space: nowrap; + position: relative; + width: 100%; +} + +.container .scroll-container { + display: flex; + align-items: center; + white-space: nowrap; + font-size: clamp(2px, calc(4vw - 1.3px), 20px); +} + +.fscontainer .scroll-container { + display: flex; + align-items: center; + white-space: nowrap; + font-size: clamp(3px, calc(6vw - 2px), 30px); +} + +.scrolling .scroll-text { + display: inline-block; + animation: scrollText var(--animation-duration) linear infinite; +} + +@keyframes scrollText { + 0% { + transform: translateX(0); + } + + 20% { + transform: translateX(0); + } + + 97% { + opacity: 1; + } + + 98% { + opacity: 0; + transform: translateX(calc(-50%)); + } + + 99% { + opacity: 0; + transform: translateX(0); + } + + 100% { + opacity: 1; + } +} + +.single-text { + display: inline-block; + opacity: 1; +} + +.container .album { + font-size: 0; +} + +.fscontainer .album { + font-size: clamp(2px, calc(4vw - 1.3px), 20px); +} + +.container .queue { + font-size: 0; +} + +.fscontainer .queue { + font-size: clamp(1.5px, calc(3vw - 1px), 15px); +} + +.container .time_container { + font-family: "Lekton", monospace; + display: flex; + justify-content: flex-start; + align-items: center; + font-size: clamp(1.5px, calc(3vw - 1px), 15px); +} + +.container .fs_time_container { + font-size: 0; +} + +.fscontainer .time_container { + font-size: 0; +} + +.fscontainer .fs_time_container { + font-family: "Lekton", monospace; + display: flex; + justify-content: flex-start; + align-items: center; + margin-top: 0.5em; + margin-bottom: 2em; + font-size: clamp(1.75px, calc(3.5vw - 1.15px), 17.5px); +} + +.container .endtime { + margin-left: 5px; + text-align: right; +} + +.container .endtime::before { + content: "-"; + padding-right: 5px; +} + +.fscontainer .endtime { + margin-left: auto; + text-align: right; +} + +/* control button */ +.play-pause-button { + font-size: clamp(2px, 4vw, 20px); + background: none; + border: none; + padding: 0; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} + +.fscontainer .play-pause-button { + position: relative; + top: 55px; +} + +.play-pause-icon { + position: relative; + width: 8vw; + max-width: 2em; + height: 9vw; + max-height: 2.2em; +} + +.bar { + position: absolute; + background: white; + width: 0.9em; + height: 2.2em; + transition: all 0.3s ease-in-out; +} + +.bar-left { + left: 0.12em; + clip-path: polygon(0% 0%, 100% 26%, 100% 74%, 0% 100%); +} + +.bar-right { + right: 0.12em; + clip-path: polygon(0% 25%, 100% 50%, 0% 75%); +} + +.playing .bar-left, +.playing .bar-right { + clip-path: inset(0 0 0 0); + width: 0.5em; +} + + +.toggle-btn-loop { position: fixed; bottom: 90px; + left: 60px; background: #4c4c4c; color: #ffffff; border: none; diff --git a/src/components/Policy.vue b/src/components/Policy.vue @@ -1,3 +1,5 @@ <template> - <h1>プライバシーポリシー</h1> + <div class="page"> + <h1>プライバシーポリシー</h1> + </div> </template> \ No newline at end of file diff --git a/src/components/Terms.vue b/src/components/Terms.vue @@ -1,5 +1,5 @@ <template> - <div class="container"> - <h1>利用規約</h1> - </div> + <div class="page"> + <h1>利用規約</h1> + </div> </template> \ No newline at end of file diff --git a/src/style.css b/src/style.css @@ -1,6 +1,7 @@ @import './reset-style.css'; -@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Lekton:wght@700&family=Noto+Sans+JP:wght@100..900&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); +/* general */ body { margin: 0px; padding: 0px; @@ -12,32 +13,19 @@ body { -webkit-text-size-adjust: none; } -.page { - height: 70px; -} -.container { - position: fixed; - bottom: 0; - width: 100%; - height: 5em; - background: #333; - display: flex; - align-items: center; - justify-content: center; +/* pages */ +.page { + position: absolute; + top: 55px; padding: 10px; - flex-direction: row; + z-index: -100; } -.fscontainer { - display: flex; - flex-direction: column; - align-items: center; - padding: 30px; -} /* title bar */ .title_bar { + position: fixed; padding: 15px; width: calc(100vw - 30px); height: 25px; @@ -53,6 +41,12 @@ body { line-height: 1; } +.title_bar a { + text-decoration: none; + color: #ffffff; +} + + /* hamburger button */ .hamburger_btn { position: fixed; @@ -88,7 +82,7 @@ body { top: 36px; } -/* hamburger button transform -> x */ +/* hamburger button -transform */ .btn_line01 { transform: translateY(10px) rotate(-45deg) } @@ -101,6 +95,7 @@ body { transform: translateY(-10px) rotate(45deg); } + /* side menu */ .menu { background-color: #1f1f1f; @@ -149,165 +144,22 @@ body { margin-bottom: 6px; } -/* player */ + +/* iframe in player */ .container iframe { - width: 5em; - height: auto; + width: 10vw; + max-width: 60px; + height: 10vw; + max-height: 60px; aspect-ratio: 1/1; } .fscontainer iframe { + position: relative; + top: 55px; margin-bottom: 5px; width: 100%; - height: 100%; max-width: 500px; + height: 100%; aspect-ratio: 1/1; -} - -/* アンダーバー時のinfo_box配置 */ -.container .info_box { - margin-left: 10px; - padding: 5px; - width: 70%; - max-width: 300px; - color: white; -} - -/* フルスクリーン時のinfo_box */ -.fscontainer .info_box { - margin: 5px; - width: 100%; - max-width: 500px; -} - -.title { - overflow: hidden; - white-space: nowrap; - position: relative; - width: 100%; -} - -.container .scroll-container { - display: flex; - align-items: center; - white-space: nowrap; - font-size: clamp(2px, calc(4vw - 1.3px), 20px); -} - -.fscontainer .scroll-container { - display: flex; - align-items: center; - white-space: nowrap; - font-size: clamp(3px, calc(6vw - 2px), 30px); -} - -.scrolling .scroll-text { - display: inline-block; - animation: scrollText var(--animation-duration) linear infinite; -} - -@keyframes scrollText { - 0% { - transform: translateX(0); - } - - 20% { - transform: translateX(0); - } - - 97% { - opacity: 1; - } - - 98% { - opacity: 0; - transform: translateX(calc(-50%)); - } - - 99% { - opacity: 0; - transform: translateX(0); - } - - 100% { - opacity: 1; - } -} - -.single-text { - display: inline-block; - opacity: 1; -} - -.container .album { - font-size: 0; -} - -.fscontainer .album { - font-size: clamp(2px, calc(4vw - 1.3px), 20px); -} - -.container .time_container { - display: flex; - justify-content: flex-start; - align-items: center; - margin-top: 0.5em; - font-size: clamp(1.5px, calc(3vw - 1px), 15px); -} - -.fscontainer .time_container { - display: flex; - justify-content: flex-start; - align-items: center; - margin-top: 0.5em; - margin-bottom: 2em; - font-size: clamp(1.5px, calc(3vw - 1px), 15px); -} - -.endtime { - margin-left: auto; - text-align: right; -} - -/* control button */ -/* play-pause button */ -.play-pause-button { - font-size: clamp(2px, 4vw, 20px); - background: none; - border: none; - padding: 0.5em 0.5em 0.5em 1em; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; -} - -.play-pause-icon { - position: relative; - width: 2em; - height: 2.2em; -} - -.bar { - position: absolute; - background: white; - width: 0.9em; - height: 2.2em; - transition: all 0.3s ease-in-out; -} - -.bar-left { - left: 0.12em; - clip-path: polygon(0% 0%, 100% 26%, 100% 74%, 0% 100%); -} - -.bar-right { - right: 0.12em; - clip-path: polygon(0% 25%, 100% 50%, 0% 75%); -} - -.playing .bar-left, -.playing .bar-right { - clip-path: inset(0 0 0 0); - width: 0.5em; } \ No newline at end of file