导读:本期聚焦于徐致远创作的《微信小程序自定义tabbar中间凸起按钮与旋转动画怎么实现?》,敬请观看详情。微信小程序原生的tabbar功能有限,想做中间凸起的发布按钮、点击旋转或者弹出子菜单这类效果,就必须走自定义tabbar方案。本文围绕这一需求展开,先讲解custom-tab-bar目录的创建和app.json配置方法,说明如何用cover-view或自定义组件替代原生栏,再详细实现中间按钮的圆形凸出样式与超出tabbar区域的布局技巧,最后拆解旋转动画的两种实现路径:CSS transition纯样式方案与JS控制角度的动态方案,并附上完整的wxml、wxss和js代码示例,同时提示自定义tabbar后页面切换监听、selected状态同步、真机层级等常见坑,帮助开发者快速做出一个带凸起按钮和旋转动画的底部导航。

微信小程序原生tabbar只能支持简单的图标加文字切换,一旦产品需求里出现"中间凸起的圆形发布按钮"、"点击时图标旋转"或者"凸起按钮周围弹出子菜单"这类设计稿,原生tabbar就无能为力了。好在小程序官方提供了自定义tabbar机制,允许开发者在custom-tab-bar目录下完全接管底部导航的渲染和交互。本文就带大家完整实现一个带中间凸起按钮和点击旋转动画的自定义tabbar,并附上可直接运行的代码。

一、开启自定义tabbar的配置基础

首先要明确,自定义tabbar不是简单地在每个页面上写一个组件,而是使用小程序官方预留的特殊目录。在小程序项目根目录下新建一个名为custom-tab-bar的文件夹,注意目录名必须完全一致,否则小程序无法识别。在这个目录下创建index.js、index.json、index.wxml、index.wxss四个文件,结构上和一个普通自定义组件完全相同。

接着修改app.json,在tabBar配置项中增加"custom": true,同时保留list数组的声明。这一点非常关键:即使你完全接管了渲染,list中的页面路径仍然是小程序识别tab页的依据,pagePath、text等字段不能删除,否则switchTab接口会失效。示例配置如下:

{
  "tabBar": {
    "custom": true,
    "color": "#999999",
    "selectedColor": "#1989fa",
    "backgroundColor": "#ffffff",
    "list": [
      { "pagePath": "pages/index/index", "text": "首页" },
      { "pagePath": "pages/publish/publish", "text": "发布" },
      { "pagePath": "pages/mine/mine", "text": "我的" }
    ]
  }
}

还需要注意,index.json中必须声明"component": true,表示这是一个组件。另外,如果项目使用了分包,custom-tab-bar目录必须放在主包根目录下,放到分包里是找不到的。配置完成后编译,原生tabbar就会消失,取而代之的是你自己的组件,只是此时还是空白,需要继续往下写界面。

二、中间凸起按钮的布局实现

凸起按钮的核心是让一个圆形按钮在视觉上"超出"tabbar顶部边界。小程序中overflow默认不会裁剪子元素,所以只要让按钮使用绝对定位,负的top值把它顶出去即可。tabbar整体高度一般设为100rpx左右,再加上底部安全区高度(适配iPhone X以后的机型),凸起按钮直径约110rpx,通过bottom: 30rpx; margin: auto; left: 0; right: 0;实现水平居中悬浮。

wxml结构可以这样组织,三个tab项横向排列,中间的发布按钮单独用绝对定位:

<view class="tab-bar">
  <view class="tab-item {{selected === 0 ? 'active' : ''}}" bindtap="switchTab" data-index="0" data-path="/pages/index/index">
    <image src="/images/home{{selected === 0 ? '-active' : ''}}.png"/>
    <text>首页</text>
  </view>

  <view class="center-btn {{rotating ? 'rotate' : ''}}" bindtap="onCenterTap">
    <image class="center-icon" src="/images/publish.png"/>
  </view>

  <view class="tab-item {{selected === 2 ? 'active' : ''}}" bindtap="switchTab" data-index="2" data-path="/pages/mine/mine">
    <image src="/images/mine{{selected === 2 ? '-active' : ''}}.png"/>
    <text>我的</text>
  </view>
</view>

对应的wxss关键样式如下,重点看center-btn的绝对定位和圆角阴影:

.tab-bar {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  height: 100rpx;
  padding-bottom: env(safe-area-inset-bottom);
  background: #ffffff;
  display: flex;
  align-items: center;
  justify-content: space-around;
  border-top: 1rpx solid #eeeeee;
}

.center-btn {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  top: -55rpx;
  width: 110rpx;
  height: 110rpx;
  border-radius: 50%;
  background: linear-gradient(135deg, #ff9a56, #ff5a3c);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 6rpx 20rpx rgba(255, 90, 60, 0.4);
  z-index: 10;
}

.center-icon {
  width: 56rpx;
  height: 56rpx;
}

这里有个细节:transform的translateX(-50%)会和后面的旋转动画共用transform属性,后面写旋转时要记得把它拼进去,否则旋转开始时按钮会突然偏移。解决方式有两种:一是外层view负责居中定位,内层view专门做旋转动画;二是旋转时写成transform: translateX(-50%) rotate(45deg)。推荐第一种,结构更清晰,互不干扰。

三、旋转动画的两种实现方式

1. CSS transition方案

最简单的旋转做法是给图标加一个class切换,配合transition实现平滑过渡。点击时图标旋转135度变成一个"加号变叉"的效果,再次点击旋转回来。这种方案纯CSS驱动,性能好,代码量少,适合状态简单切换的场景:

.center-icon {
  transition: transform 0.4s ease;
}

.rotate {
  transform: rotate(135deg);
}
// custom-tab-bar/index.js
Component({
  data: {
    selected: 0,
    rotating: false
  },
  methods: {
    onCenterTap() {
      const next = !this.data.rotating;
      this.setData({ rotating: next });
      if (next) {
        // 打开子菜单或跳转发布页
        wx.navigateTo({ url: '/pages/publish/publish' });
      }
    }
  }
});

2. JS控制角度的连续旋转方案

如果需求是每点击一次累计旋转90度,而不是来回切换,纯CSS class切换就不方便了,因为每次移除class角度会归零。这时用data维护一个角度值,每次点击加90,动画依然交给transition完成:

Component({
  data: {
    selected: 0,
    angle: 0
  },
  methods: {
    onCenterTap() {
      const angle = this.data.angle + 90;
      this.setData({ angle });
      setTimeout(() => {
        wx.switchTab({ url: '/pages/publish/publish' });
      }, 400); // 等动画播完再跳转
    }
  }
});

wxml里用内联样式绑定角度:style="transform: rotate({{angle}}deg); transition: transform 0.4s;"。这种写法角度只增不减,动画始终朝一个方向旋转,视觉上更流畅。还可以进一步扩展成弹出子菜单:点击凸起按钮后,周围按弧形分布弹出三个小按钮,每个小按钮的位置用三角函数计算,配合scale和opacity的transition就能做出不错的扩散效果。

四、selected状态同步与常见坑

自定义tabbar最大的坑是每个tab页都会创建独立的tabbar组件实例,切换页面后组件会重新初始化,selected状态丢失。解决办法是在每个tab页的onShow里调用组件的setData方法同步索引:

// pages/index/index.js
onShow() {
  if (typeof this.getTabBar === 'function' && this.getTabBar()) {
    this.getTabBar().setData({ selected: 0 });
  }
}

每个tab页都要写一遍这段代码,只是selected的值不同。如果觉得繁琐,可以把这段逻辑抽成behaviors或者公共函数复用。

另外几个容易踩的点:第一,跳转tab页必须用wx.switchTab,不能用navigateTo,否则会出现页面叠加;第二,凸起按钮超出了tabbar区域,如果tabbar背景色和页面背景色不一致,注意按钮下缘的阴影在低端安卓机上可能被截断,可以适当加高tabbar容器;第三,封面组件的问题在自定义tabbar中已不存在,自定义tabbar本身就是原生组件层级,直接用view和image即可,不需要cover-view,但在video、map等原生组件上方仍需真机验证显示层级是否正常。

最后,如果产品要求"凸起按钮点击后原地旋转并弹出扇形菜单",可以把第二节的布局和第三节的连续旋转结合起来,用wx:if控制子菜单的渲染,配合CSS的transform-origin属性把旋转中心设置到凸起按钮圆心,就能实现菜单围绕按钮弧线展开的动效。整体方案在小程序基础库2.5.0以上版本均可运行,建议开发时用真机调试动画流畅度,模拟器上的动画表现和真机存在差异。

微信小程序自定义tabbar凸起按钮动画修改时间:2026-08-31 06:59:02

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。