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

这两天完成了一个仿樊登 H5 的音乐播放悬浮球效果,这个效果跟微信音乐播放悬浮球的效果也很相似,今天总结一下实现的思路过程(基于 Vue 实现)。

先来看看樊登 H5 的效果。

fandeng.gif

再来看看我的实现,挺完美的,哈哈。

floatcircle.gif

实现起来也不复杂,主要是一步步想清楚下面的实现步骤:

第一步:小球被限制在固定范围内滑动
第二步:停止滑动时,小球吸边效果
第三步:点击吸边状态下的小球,变换为音频播放控制面板,点击毛玻璃,恢复成小球
第四步:背景毛玻璃效果

一步步来说。

第一步:小球被限制在固定范围内滑动

touchmove可以获得小球的滑动事件,所以可以使用touchmove​来限制小球的滑动范围。

先给小球的 touchmove 传入 handleTouchMove 函数,在 handleTouchMove 中获取到滑动事件 e,使用 e.targetTouches[0]可以获得手指滑动的坐标 clientX 和 clientY,来计算小球 left、top 值,从而来控制小球随手指滑动。

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

当手指或鼠标滑动到超过屏幕的左边界时,就将小球的 left 重置为 0,不让小球超出左边界。当滑动超过右边界时,就将小球的 left 重置为视口的宽度减去小球的宽度,不让小球超出右边界。

顶部和底部边界也一样,当手指或鼠标滑动到超过顶部边界时,将小球的 top 重置为 0,超过底部边界时,将 top 重置为视口的高度减去小球的高度。

当然滑动范围可以自己来控制,详细控制小球滑动的代码如下:

    //限制悬浮球一个范围内滑动
    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";
    },


第二步:停止滑动,悬浮球吸边效果

滑动小球,当手指松开时,小球需要吸附到屏幕边缘。根据小球中心的 x 坐标判断,如果 x 坐标小于屏幕宽度的一半,就吸附到屏幕左边,如果大于等于屏幕宽的一半则吸附到屏幕右边,实现代码走一波:

    //touchend的时候,悬浮球吸边显示
    handleTouchEnd(e) {
      this.isAnimated = true; //手指拖动小球滑动的时候不需要动画,滑动停止的时候添加动画
      let circleCenterX =
        parseInt(this.$refs.circle.style.left.replace("px", "")) +
        this.circleWidth / 2; //悬浮球中心的x坐标
      let circleCenterY =
        parseInt(this.$refs.circle.style.top.replace("px", "")) +
        this.circleHeight / 2; //悬浮球中心的y坐标

      if (circleCenterX < this.clientWidth / 2) {
        //吸附左侧
        this.$refs.circle.style.left = 0;
        this.$refs.circle.style.borderRadius = "0 50% 50% 0";
      } else {
        //吸附在右侧
        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";
      }
    },


第三步:点击吸边小球,变换为音频播放控制面板

当小球吸附到屏幕边缘时,点击小球,小球展开成音频控制面板,点击毛玻璃背景,小球收缩恢复原状。

floatcircle1.gif

在实现时我将小球 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">
    <!-- 小球悬浮状态 -->
  </div>
</div>

使用 circle-box 包裹悬浮小球 circle 和音频控制面板 content,使用变量 showCircleContent 来判断当前应该显示悬浮球还是音频播放控制面板。

当点击悬浮球时 showCircleContent 为 true,小球伸长变换为音频播放控制面板。

点击毛玻璃背景,设置 showCircleContent 为 false,音频播放控制面板收缩恢复成悬浮小球。

伸缩动画

floatcircle1.gif

小球从悬浮球变为音频控制面板,或者从控制面板变为悬浮球时是有动画的,这个动画应该在 touchend 的时候才添加,在 touchmove 的时候去掉。因为小球滑动时如果有动画的话,会有卡顿的现象。

使用 isAnimated 来控制动画的添加和删除,在 touchend 的时候为 true,在 touchmove 改为 false。


第四步:背景毛玻璃效果

backdrop-filter 属性实现毛玻璃了解一下,filter 只能让当前元素有模糊效果,当前元素之下的元素还是清晰的。而 backdrop-filter 可以让当前元素及以下的元素都模糊,从而实现毛玻璃的效果。

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

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

backdrop-filter.png

OK,以上就是实现音乐播放悬浮球的思路总结,其实在实现过程中还有很多细节上的处理,如果想了解更多细节,可以关注我的公众号「程序员张晴天」,并在后台回复「悬浮球」即可获得demo完整源码。

如果对你有帮助的话,点赞、评论、赞赏都是对我的鼓励,也是支持我写下去的动力,谢谢!

本文原创发布于微信公众号「程序员张晴天」,欢迎关注第一时间获取最新分享,一起进步。

扫码_搜索联合传播样式-标准色版 copy.jpg
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 198,154评论 5 464
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,252评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 145,107评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,985评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,905评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,256评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,978评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,611评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,891评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,910评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,736评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,516评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,995评论 3 301
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,132评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,447评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,034评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,242评论 2 339