Made a music player with vue+flask (front-end part)

During this period of time, I suddenly wanted to make a music player to play, so this thing was born.

Originally I just wanted to make a small demo to play, so I didn't plan to make the interface look good, so I modeled the optimization on the interface of Yueting. Later, I found that the demand had increased, which made the unsightly interface worse, but it was acceptable. Let me briefly introduce it. After all, who can refuse a gadget that belongs to him alone?

front end

This music player is built by separating the front and back ends of vue and python flask. The front end mainly sends the name of the singer or song to be searched to the back end, and receives the lyrics, music, and comments from the back end.

1. Search

Here I demonstrate the search for Jay Chou

2. Play

Play music, receive comments and the appearance of the song list, the captured comments are the most popular comments in qq music, and you can also delete or favorite the song list

3. Lyrics display

Lyrics are also displayed

4. Collection

When you click on the heart, the song will be put into the favorite list and saved permanently locally, this is my favorite song list

5.audio customization and source change

And the following players have also been customized to realize the replacement of the upper and lower songs, as well as random, single, and sequential playback. The default is sequential playback. And provides download function. If you encounter some songs that cannot be played, you can also change the source, and you can understand the effect, such as "the light wrapped in the heart, mojito".

Just click on the logo to change the source. But after changing the source, whether the lyrics or comments or the song list are different from the other source.

When the source change is successful, the source below will become 1, and the list will be cleared, and the favorite lists of the two sources are also different.

At this time, search for the light wrapped in the heart, and there will be surprises. Here I will use my collection list to demonstrate it for a better display.

Ok, start playing.

6. Download

By the way, let's demonstrate the download function

Because it has been downloaded before, so there is (1), the format is saved in MP3
The front-end is probably introduced here, there is also an interface optimization and so on, the small details have not been done, so it has not been launched yet.

part of the code

logo and search bar
<div class="search_bar">
        <img src="../assets/musicPic/player_title5_1.png" alt="" @click="open1">

        <el-button type="info" class="sc_music" @click="get_Collection">Favorite playlist</el-button>
        <el-button type="info" class="ss_music" @click="get_Search">search list</el-button>
        <!-- search for songs -->
        <div class="search_input">
          <input type="text" autocomplete="off" v-model="query" @keyup.enter="searchMusic" placeholder="Please enter song title or artist"
                 class="Music_input">
          <button class="iconfont icon-sousuo" @click="searchMusic"></button>
        </div>
</div>
search list
<div class="song_wrapper"
             v-loading="loading"
             element-loading-text="desperately loading"
             element-loading-spinner="el-icon-loading"
             element-loading-background="rgba(255, 255, 255, 0.0)">
          <ul class="song_list">
            <li v-for="(item, index) in musicList" :key="index" @mouseover="onMouseover(index)" @mouseout="onMouseleave(index)" :class="{ MusicActivate:isPlaying===true&&musicid === item.id}" @dblclick="playMusic(item.id,item.mid,item.pid,item.name,item.sname)">
              <b :title=item.name>{{ item.name }}</b>
              <span style="width: 70px;margin-right: 0;overflow: hidden">{{ item.sname }}</span>
              <span style="width: auto;margin-bottom: 2px"><i class="iconfont icon-02" style="color: #fa048d" @click="setColl(item)"></i></span>
              <span  class="del-btn" style="width: auto;margin-bottom: 2px" ><i v-show="showDel&&n===index" class="iconfont icon-shanchu" @click="delMusic(index)"></i></span>
            </li>
          </ul>
          <img src="../assets/musicPic/line.png" class="switch_btn" alt="">
</div>
Middle cover and lyrics
<!-- song info container -->
        <div class="player_con" :class="{playing:isPlaying}" v-show="showdisc">
          <img src="../assets/musicPic/player_bar.png" class="play_bar"/>
          <!-- vinyl disc -->
          <div @click="LyricorPic">
            <img src="../assets/musicPic/disc.png" class="disc autoRotate"/>
            <img :src="musicCover" class="cover autoRotate"/>
          </div>
        </div>
        <!-- Lyrics display container -->
        <transition
          name="custom-classes-transition"
          enter-active-class="animate__animated animate__tada"
          leave-active-class="animate__animated animate__bounceOutRight"
        >
          <div class="play_lyric" @click="showBar" v-show="showLyric">
            <el-col type="flex" justify="center" class="lyric-contain">
              <ul class="lyric_list" ref="lyric_list">
                {{ getAllKey }}
                <li
                  :class="{ 'active':key < currentTime }"
                  v-for="(item,key,index) in musicLyric" :key="index"
                  class="lyric-row">
                  {{ item }}{{ srcollLrc(key, index) }}
                </li>
              </ul>
            </el-col>
          </div>
        </transition>
Message section
<!-- comment container -->
        <div class="comment_wrapper"
             v-loading="loadings"
             element-loading-text="desperately loading"
             element-loading-spinner="el-icon-loading"
             element-loading-background="rgba(255, 255, 255, 0.0)">
          <h5 class='title'>Popular comments</h5>
          <div class='comment_list'>
            <dl v-for="item in hotComments">
              <dt><img :src="item.Avatar" alt=""></dt>
              <dd class="name">{{ item.Nick }}</dd>
              <dd class="detail">
                {{ item.Content }}
              </dd>
              <dl v-for="sub in item.SubComments">
                <dt><img :src="sub.Avatar"></dt>
                <dd class="name">{{ sub.Nick }}</dd>
                <dd class="detail">
                  {{ sub.Content }}
                </dd>
              </dl>
            </dl>
          </div>
          <img src="../assets/musicPic/line.png" class="right_line">
        </div>
      </div>
custom audio section
<!-- customize audio -->
      <div class="audio_con">
        <audio ref='audio' @ended="end" @play="playFunc" @pause="pauseFunc" :src="musicUrl" class="myaudio"
               @timeupdate="timeupdateFunc"
               @canplay="canplayFunc"
               @error="errorFunc"></audio>
        <div class="audio_control">
          <div class="play_control">
             <span
               class="audioSpan"
               @click="clickFunc('backward')"
               style="width: 10px; height: 20px; "
             ><i class="el-icon-d-arrow-left" aria-hidden="true"></i
             ></span>
            <span
              class="audioSpan"
              @click="clickFunc('play')"
              v-show="!isPlaying"
              style="width: 10px;margin-left: 30px"
            ><i class="el-icon-video-play" aria-hidden="true"></i
            ></span>
            <span
              class="audioSpan"
              @click="clickFunc('pause')"
              v-show="isPlaying"
              style="width: 10px;margin-left: 30px"
            ><i class="el-icon-video-pause" aria-hidden="true"></i
            ></span>
            <span
              class="audioSpan"
              @click="clickFunc('forward')"
              style="width: 10px;margin-left: 30px"
            ><i class="el-icon-d-arrow-right" aria-hidden="true"></i
            ></span>
            <div
              style="display: block; align-items: center;margin-left: 60px; margin-top: 0px;position: relative"
              @mousedown="isDraging = true"
              @mouseup="isDraging = false"
              class="audio_slider">
              <div style="width: auto; top:0; position: absolute; font-size: 10px;margin-left: 20px">
                {{ title }}--{{ artist }}
              </div>
              <div style="font-size: 10px;position: absolute;top:0;left: 430px;">
                {{ formatCurrentTime }}/{{ formatDuration }}
              </div>
              <el-slider
                v-model="playProcess"
                class="sliderClass"
                style="width: 500px;margin-top: 10px"
                @change="setProcessFunc"
                :format-tooltip="formatTooltip"
              ></el-slider>
            </div>
            <span
              class="audioSpan"
              @click="changeMode"
              style="width: 10px;margin-left: 30px;font-size: 20px;margin-top: 10px;cursor: pointer"
            ><i :class=iconMode() aria-hidden="true" style="font-weight: bolder"></i
            ></span>
            <span class="audioVolSpan" style="width: 10px;margin-left: 30px;font-size: 20px;margin-top: 10px"
            ><i class="el-icon-microphone" aria-hidden="true"></i
            ></span>
            <el-slider
              v-model="playVolume"
              style="margin-left: 15px;margin-top: 5px;width: 80px;"
              class="sliderVolumClass"
              :format-tooltip="formatTooltipVol"
              @change="setVolumeFunc"
            ></el-slider>
            <a class="iconfont icon-xiazai" style="font-size: 25px;margin-top: 5px;margin-left: 30px" @click="downloadMusic(musicUrl,title)"></a>
          </div>
        </div>
      </div>

Summarize

The rest of the code will not be shown one by one, and the optimization has not been fully completed. It has not been open sourced on GitHub. If you are interested in this project or want to play with it, you can privately message me. Because the back end involves the crawler part, I don't know if it will be limited, so I will introduce it in two parts.

Tags: Javascript Front-end Vue Vue.js

Posted by KyleVA on Tue, 03 May 2022 15:43:37 +0300