ホームページ  >  記事  >  ウェブフロントエンド  >  JSは音楽プレーヤーインターフェースを実装します

JSは音楽プレーヤーインターフェースを実装します

php中世界最好的语言
php中世界最好的语言オリジナル
2018-03-23 16:36:183934ブラウズ

今回は、音楽プレーヤーのインターフェースを実装するための JS について説明します。以下は、音楽プレーヤーのインターフェースを実装するための注意点です。

この記事では、vue ページに音楽プレーヤーを実装する例を紹介し、皆さんと共有します。詳細は次のとおりです:

効果は次のとおりです:

プロジェクトアドレス: https:/ /github.com/ermu592275254/MiniMusicPlayer

デモアドレス: https://ermu592275254.github.io/MiniMusicPlayer/(曲のリンクは切れています)

開発前の構想

インターフェース

音楽プレーヤーを作るには、インターフェイスはクールでなければなりません。低音すぎて音楽を聴いていても何も感じません。仕事で使うことを想定しているので、NetEase Cloud Musicに似たインターフェースを適当なサイズで作りました。携帯電話に対応している必要はありません。

CSSを使用してアイコンを作成します

これは、シンプルで実用的なニーズに基づいています。アイコンにはSVG、URL、またはCSSを使用できます。 URLと比較すると、SVGやCSSの方が優れています。練習のために、最終的に css を選択しました。 after と before をうまく活用すると、DOM のネストを大幅に減らすことができます。

.next {
  position: relative;
  display: inline-block;
  height: 36px;
  width: 36px;
  border: 2px solid #fff;
  border-radius: 20px;
  -webkit-border-radius: 20px;
  -moz-border-radius: 20px;
}
    
.next:before {
  content: '';
  height: 0;
  width: 0;
  display: block;
  border: 10px transparent solid;
  border-right-width: 0;
  border-left-color: #fff;
  position: absolute;
  top: 8px;
  left: 10px;
}
.next:after {
  content: '';
  height: 20px;
  width: 4px;
  display: block;
  background: #fff;
  position: absolute;
  top: 8px;
  left: 22px;
}

レコードを描画します

NetEase Cloud のレコードはとても美しいので、私もレコードを作成したいです! box-shadow をうまく活用すると、1 つの要素で美しいレコード効果を作成できます。

.disc {
  position: relative;
  margin-top: 10%;
  margin-left: 10%;
  width: 300px;
  height: 300px;
  border-radius: 300px;
  transform: rotate(45deg);
  background-image: radial-gradient(5em 30em ellipse, #fff, #000);
  border: 2px solid #131313;
  box-shadow: 0 0 0 10px #343935;
  opacity: 0.7;
}

範囲を進行状況バーとして使用します

オーディオ自体のスタイルは醜く、ブラウザごとに表示される効果も異なります。もちろん、オーディオのスタイルを変更することもできます。従来の方法では、controls 属性を使用してオーディオを非表示にし、代わりに p を使用します。もちろん、今は HTML5 の時代です。よりシーンに適した新しい要素を使用する必要があります。

input[type=range] {
  -webkit-appearance: none;
  width: 80%;
  height: 8px;
  border-radius: 10px;
  background-color: #fff;
}
input[type=range]::-webkit-slider-thumb{
  -webkit-appearance: none;
} 
input[type=range]::-webkit-slider-runnable-track {
  height: 8px;
  border-radius: 20px;
}
input[type=range]:focus {
  outline: none;
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none;
  margin-top: -3px;
  height: 14px;
  width: 14px;
  background: #eb7470;
  border-radius: 50%;
  border: solid 3px #fff;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.5);
}

背景フィルターぼかし

写真を背景に設定すると、プレーヤー全体の見た目の半分を占めると言っても過言ではありません。設定もcss3フィルターを使用するので非常に簡単です。

.bg-blur {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100%;
  height: 100%;
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
  filter: blur(20px);
  z-index: -1;
}

背景画像はjsを通じて制御されます。

<p class="bg-blur" :style="`background-image:url(${currentSong.album_logo})`"></p>

曲リソース

インターフェースを降りてください

Xiami公式Webサイトに直接アクセスしてネットワークを開き、URLをpostmanにコピーしてリクエストを行ってください。ヘッダーを変更すると、Referer が検証されることがわかります。つまり、Xiami によって許可されたドメイン名のみがこのインターフェイスにアクセスできます。 http://api.xiami.com/web?v=2.0&app_key=1&key=aliez&page=1&limit=5&callback=jsonp154&r=search/songs

インターフェイスが jsonp をサポートしているため、クロスドメインの問題を解決します

。最初に、Chrome ブラウザをクロスドメインに設定してから、$.ajax を介して jsonp リクエストを作成しようとしました。通常通りアクセス可能です。

その後、突然機能しなくなりました。Xiami が制限を課したのでしょうか?

そこで、ノードを使用してサービスを開始し、リファラーを偽ってリクエストを開始し、そのリクエストをページに転送しました。誤ってエージェントを書いてしまいました。

...
case '/song':
  let songOptions = {
    url: 'http://api.xiami.com/web?'+ urlArr[1],
    headers: {
      'Referer': 'http://m.xiami.com/'
    }
  };
  function callback1(error, response, body) {
    if (!error && response.statusCode == 200) {
      res.end(body);
    }
  }
  request(songOptions, callback1);
  break;
...

歌詞スクロール

高品質プレーヤーとして、歌詞スクロールは必須です。

原則

各歌詞を対応する時間を含むオブジェクトとして保存します。曲の現在の継続時間が歌詞の時間以上、歌詞の次の行の時間未満の場合、歌詞を表示領域までスクロールします。そして文字の色を変更します。

歌詞のフォーマット

インターフェースから返される歌詞は、注意深く調べた結果、パターンがあることがわかりました。

[ti:aLIEz]
[ar:SawanoHiroyuki[nZk]:mizuki]
[al:o1]
[ly:澤野弘之]
[mu:澤野弘之]
[ma:]
[pu:]
[by:ttpod]
[total:268512]
[offset:0]
[00:00.000]<195>aLIEz <199>- <451>SawanoHiroyuki[nZk]:mizuki
[x-trans]彻头彻尾的谎言 - SawanoHiroyuki[nZk]:mizuki
[00:01.095]<201>作<250>詞<200>:<201>澤<200>野<199>弘<300>之
[x-trans]
[00:02.846]<200>作<150>曲<150>:<200>澤<200>野<351>弘<349>之
[x-trans]
[00:20.828]<200>決<250>め<200>つ<201>け<149>ば<201>か<349>り
[x-trans]一直独断专权
[00:23.279]<200>自<200>惚<200>れ<200>を<200>着<400>た
[x-trans]总是自负逞强
[00:24.979]<200>チ<200>ー<200>プ<450>な<550>hokori<350>で
[x-trans]明明只是一文不值的骄傲
......
  refactoringLyrics(lyric){
  let text = lyric.split('[offset:0]')[1];
  let textArr = text.split('\n');
  let lyricsArr = [], translate = [];
  textArr.forEach((item, index) => {
    let time = 0, text = '';
    if (item.indexOf('[x-trans]') > -1) {
      translate.push(item.split('[x-trans]')[1])
    } else if (item.trim() != '') {
      time = item.slice(1, 6).split(':');
      time = parseInt(time[0]) * 60 + parseInt(time[1]);
      text = item.slice(11);
      let arr = text.split('>');
      let str = arr.reduce((a, b) => {
        return a.split('<&#39;)[0] + b.split(&#39;<&#39;)[0]
      });
      let obj = {
        time: time,
        text: str
      };
      lyricsArr.push(obj);
    }
  });
  for (let i in translate) {
    lyricsArr[i].text = lyricsArr[i].text + &#39;\n&#39; + translate[i];
  }
  this.currentLyrics = lyricsArr;
},

検索バーの実装

同じファイルの下にサブコンポーネントを実装

モジュール開発に従うために、検索バーをサブコンポーネントとして記述することにしました。同じページにサブコンポーネントを記述する場合は、サブコンポーネントを対応するテンプレートにマウントすることが重要です。このテンプレートは、親コンポーネントのマウント要素に含めることはできません。そうしないと、親コンポーネントがレンダリングされるときに、子コンポーネントのデータをレンダリングできないため、未定義が報告されます。

<p id="app" class="main">
...
</p>
<template id="search-box">
...
</template>
var searchBox = {
    template: '#search-box',
    props: {
      isShow: Boolean,
      openFun: Function
    },
    data(){
      return {
        resultList: [],
        searchValue: '',
      }
    },
    methods: {
    }
  };
 new Vue({
  el: '#app',
  components: {
    'com-tip': tip,
    'search-box': searchBox
  },
  ...
})

eventBus がデータ伝送を解決します

通过jsonp去请求数据,需要设置一个callback函数,此callback写成一个全局函数,如果不这样写,而是通过 searchBox.methods.callback的形式,this指向将为methods。而无法直接给searchBox的data赋值。 于是通过eventBus来处理,这样更易维护。

var EventBus = new Vue();
var callBack = function(result) {
  console.log(result);
  EventBus.$emit('callBack', result);
};
...
mounted(){
  let self = this;
  EventBus.$on('callBack', function(res) {
    if (res && res.data) {
      self.resultList = res.data.songs;
    }
  })
}
...

localStrong储存歌曲信息

下次再打开,应该播放列表应该保留上一次的数据,这个可直接用localstrong实现

踩了坑

prop传递数据

使用cdn,vue的prop只支持中线格式,驼峰格式不生效

ps: 在用webpack打包的项目中用驼峰是可以,在打包过程中,会做处理。

// 正确写法
<search-box :is-show="showSearch" :open-fun="openSearch" @push-song="pushNewSong"
        @play-song="playSong"></search-box>
// 错误写法
<search-box :isShow="showSearch" :openFun="openSearch" @pushSong="pushNewSong"
        @playSong="playSong"></search-box>

待优化

手动修改进度,偶尔会不生效。

搜索暂不支持分页

不支持建歌单

背景颜色与进度条颜色相近需修改进度条颜色

不支持播放模式选择-单曲循环-随机播放

相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!

推荐阅读:

Express与Koa2的使用详解

地图网格的实现

以上がJSは音楽プレーヤーインターフェースを実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。