web高仿樊登H5/微信音樂播放懸浮球效果

這兩天完成了一個仿樊登 H5 的音樂播放懸浮球效果,這個效果跟微信音樂播放懸浮球的效果也很相似,今天總結(jié)一下實現(xiàn)的思路過程(基于 Vue 實現(xiàn))。

先來看看樊登 H5 的效果。

fandeng.gif

再來看看我的實現(xiàn),挺完美的,哈哈。

floatcircle.gif

實現(xiàn)起來也不復(fù)雜,主要是一步步想清楚下面的實現(xiàn)步驟:

第一步:小球被限制在固定范圍內(nèi)滑動
第二步:停止滑動時,小球吸邊效果
第三步:點擊吸邊狀態(tài)下的小球,變換為音頻播放控制面板,點擊毛玻璃,恢復(fù)成小球
第四步:背景毛玻璃效果

一步步來說。

第一步:小球被限制在固定范圍內(nèi)滑動

touchmove可以獲得小球的滑動事件,所以可以使用touchmove?來限制小球的滑動范圍。

先給小球的 touchmove 傳入 handleTouchMove 函數(shù),在 handleTouchMove 中獲取到滑動事件 e,使用 e.targetTouches[0]可以獲得手指滑動的坐標(biāo) clientX 和 clientY,來計算小球 left、top 值,從而來控制小球隨手指滑動。

      <div
        class="circle"
        v-if="!showCircleContent"
        @click="handleClickCircle"
        @touchend="handleTouchEnd"
        @touchmove.prevent="handleTouchMove"
      ></div>

當(dāng)手指或鼠標(biāo)滑動到超過屏幕的左邊界時,就將小球的 left 重置為 0,不讓小球超出左邊界。當(dāng)滑動超過右邊界時,就將小球的 left 重置為視口的寬度減去小球的寬度,不讓小球超出右邊界。

頂部和底部邊界也一樣,當(dāng)手指或鼠標(biāo)滑動到超過頂部邊界時,將小球的 top 重置為 0,超過底部邊界時,將 top 重置為視口的高度減去小球的高度。

當(dāng)然滑動范圍可以自己來控制,詳細(xì)控制小球滑動的代碼如下:

    //限制懸浮球一個范圍內(nèi)滑動
    handleTouchMove(e) {
      this.isAnimated = false;  //手指拖動小球滑動的時候不需要動畫,滑動停止的時候添加動畫
      this.$refs.circle.style.borderRadius = "50%";
      let offsetX = e.targetTouches[0].clientX - this.circleWidth / 2; //減去this.circleWidth / 2目的是讓手指按在懸浮球正中
      let offsetY = e.targetTouches[0].clientY - this.circleHeight / 2; //減去this.circleHeight / 2目的是讓手指按在懸浮球正中
      if (offsetX <= 0 + this.placeholderWidth) {
        offsetX = 0 + this.placeholderWidth; //不讓懸浮球完全貼邊
      } else if (
        offsetX >=
        document.documentElement.clientWidth -
          this.circleWidth -
          this.placeholderWidth //微信懸浮球不是完全貼邊,離屏幕邊緣有一段距離
      ) {
        offsetX =
          document.documentElement.clientWidth -
          this.circleWidth -
          this.placeholderWidth;
      }

      if (offsetY <= 0 + this.placeholderWidth) {
        offsetY = 0 + this.placeholderWidth;
      } else if (
        offsetY >=
        document.documentElement.clientHeight -
          this.circleHeight -
          this.placeholderWidth
      ) {
        offsetY =
          document.documentElement.clientHeight -
          this.circleHeight -
          this.placeholderWidth;
      }
      this.$refs.circle.style.left = offsetX + "px";
      this.$refs.circle.style.top = offsetY + "px";
    },


第二步:停止滑動,懸浮球吸邊效果

滑動小球,當(dāng)手指松開時,小球需要吸附到屏幕邊緣。根據(jù)小球中心的 x 坐標(biāo)判斷,如果 x 坐標(biāo)小于屏幕寬度的一半,就吸附到屏幕左邊,如果大于等于屏幕寬的一半則吸附到屏幕右邊,實現(xiàn)代碼走一波:

    //touchend的時候,懸浮球吸邊顯示
    handleTouchEnd(e) {
      this.isAnimated = true; //手指拖動小球滑動的時候不需要動畫,滑動停止的時候添加動畫
      let circleCenterX =
        parseInt(this.$refs.circle.style.left.replace("px", "")) +
        this.circleWidth / 2; //懸浮球中心的x坐標(biāo)
      let circleCenterY =
        parseInt(this.$refs.circle.style.top.replace("px", "")) +
        this.circleHeight / 2; //懸浮球中心的y坐標(biāo)

      if (circleCenterX < this.clientWidth / 2) {
        //吸附左側(cè)
        this.$refs.circle.style.left = 0;
        this.$refs.circle.style.borderRadius = "0 50% 50% 0";
      } else {
        //吸附在右側(cè)
        this.$refs.circle.style.left =
          this.clientWidth - this.circleWidth + "px";
        this.$refs.circle.style.borderRadius = "50% 0 0 50%";
      }

      if (circleCenterY >= this.clientHeight - this.placeholderBottom) {
        this.$refs.circle.style.top =
          this.clientHeight - this.placeholderBottom + "px";
      }
    },


第三步:點擊吸邊小球,變換為音頻播放控制面板

當(dāng)小球吸附到屏幕邊緣時,點擊小球,小球展開成音頻控制面板,點擊毛玻璃背景,小球收縮恢復(fù)原狀。

floatcircle1.gif

在實現(xiàn)時我將小球 circle 跟音頻控制面板 content 分開布局,大概是這個樣子。

<div
  class="circle-box"
  :class="{
        opened: showCircleContent,
        animation: isAnimated
      }"
  ref="circle"
>
  <div class="content" v-if="showCircleContent">
    <!-- 音頻控制面板,?顯示歌曲名字、播放時長,同時還能控制播放暫停音頻 -->
  </div>
  <div class="circle" v-if="!showCircleContent">
    <!-- 小球懸浮狀態(tài) -->
  </div>
</div>

使用 circle-box 包裹懸浮小球 circle 和音頻控制面板 content,使用變量 showCircleContent 來判斷當(dāng)前應(yīng)該顯示懸浮球還是音頻播放控制面板。

當(dāng)點擊懸浮球時 showCircleContent 為 true,小球伸長變換為音頻播放控制面板。

點擊毛玻璃背景,設(shè)置 showCircleContent 為 false,音頻播放控制面板收縮恢復(fù)成懸浮小球。

伸縮動畫

floatcircle1.gif

小球從懸浮球變?yōu)橐纛l控制面板,或者從控制面板變?yōu)閼腋∏驎r是有動畫的,這個動畫應(yīng)該在 touchend 的時候才添加,在 touchmove 的時候去掉。因為小球滑動時如果有動畫的話,會有卡頓的現(xiàn)象。

使用 isAnimated 來控制動畫的添加和刪除,在 touchend 的時候為 true,在 touchmove 改為 false。


第四步:背景毛玻璃效果

backdrop-filter 屬性實現(xiàn)毛玻璃了解一下,filter 只能讓當(dāng)前元素有模糊效果,當(dāng)前元素之下的元素還是清晰的。而 backdrop-filter 可以讓當(dāng)前元素及以下的元素都模糊,從而實現(xiàn)毛玻璃的效果。

backdrop-filter: blur(10px); //毛玻璃效果,ios有效
-webkit-backdrop-filter: blur(10px);

但是目前 backdrop-filter 的兼容性不是太好,在 IOS 平臺能看到毛玻璃效果,Android 平臺看不到。

backdrop-filter.png

OK,以上就是實現(xiàn)音樂播放懸浮球的思路總結(jié),其實在實現(xiàn)過程中還有很多細(xì)節(jié)上的處理,如果想了解更多細(xì)節(jié),可以關(guān)注我的公眾號「程序員張晴天」,并在后臺回復(fù)「懸浮球」即可獲得demo完整源碼。

如果對你有幫助的話,點贊、評論、贊賞都是對我的鼓勵,也是支持我寫下去的動力,謝謝!

本文原創(chuàng)發(fā)布于微信公眾號「程序員張晴天」,歡迎關(guān)注第一時間獲取最新分享,一起進(jìn)步。

掃碼_搜索聯(lián)合傳播樣式-標(biāo)準(zhǔn)色版 copy.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容