如何实现抛物线跳跃交互底部导航栏?

点击小卡片

db61e0721e7a2e2510b7c1e17d4b2c0f.png记录程序员专属笔记325a12b27ce54044d735e7c7d2304b56.png

如何实现抛物线跳跃交互底部导航栏?_第1张图片

专注于目标,全世界都会给你让路

写在最前

做这个效果的初衷是当年在第一家公司的时候,我们的UI小姐姐拿着B站的视频效果

问:「“这个效果可以实现吗?”」

答:「“你想我死可以直说,不用拐弯抹角 ”」

年少不知道男人不能说不行,现在想要弥补一下遗憾,于是花了点时间实现了「抛物线跳跃交互底部导航栏」

原理其实非常简单:「两点之间的抛物线运动 + CSS3镂空效果」

抛物线运动

在上一篇文章里我们似乎出现过这个词,但是实现方式却是通过现成的API实现。今天我们通过 「数学公式」 来完成。

先把热乎的饭菜端上:

/**
* @param target 目标点的x,y坐标
* @param x      当前x坐标
* @param a      常量,决定曲率
*/
const curve = (target : { x : number, y : number }, x : number, a : number = 0.001) => {
 let b = (target.y - a * (target.x * target.x)) / target.x;
 let y = a * (x * x) + b * x;

 return y;
}

这是通过下面公式转换而来的

「y = a * x * x + b * x + c」

公式中有 3 个变量 「a、b、c」。我们假设抛物线经过(0,0),将x = 0,y = 0代入公式,可以得知「c = 0」; 已知变量 a 是 常量,抛物线起终两点也已知,那 b 点也自然能够算出。

「b = (y2 - a * (x2 * x2)) / x2」

三个变量都已知后,就可以算出抛物线的轨迹了

CSS3镂空效果

CSS3 镂空效果实现方式有很多种,就不展开讲了。我这边使用的CSS3中的 「遮罩 + 径向渐变」

径向渐变MDN

background-image: radial-gradient(「shape size」 at 「position, start-color, ..., last-color」);

background-image: radial-gradient(circle at 50% 0upx, transparent 200upx, white 200upx);
如何实现抛物线跳跃交互底部导航栏?_第2张图片 image.png

当相邻颜色偏移量相等时,不出现渐变情况,语法简单,不多展开。

mask 遮罩

语法与 background 相似,不展开。

-webkit-mask: radial-gradient(circle at 50rpx 0rpx, transparent 45rpx, #999999 45rpx)
如何实现抛物线跳跃交互底部导航栏?_第3张图片 image.png

「tips: 不透明色显示底色(白色),所以后面的颜色可随便填写」

到这里用到的知识点都介绍完了,接下来我们只需要设置一个位移变量控制镂空与小球位置就行了。

想要实现CSS 「transition」 丝滑的运动效果,需使用之前「requestAnimationFrame」控制每一帧位移量。

/*
*  @param target 目标位置
*  @param time   运动时长
**/

const move = (target, time) => {

 let distance = target - circleLeft.value;
 let speed = distance / (time / 60);
 let isMoveLeft = circleLeft.value > target;
 let sourceLeft = JSON.parse(JSON.stringify(circleLeft.value));
        
  const resetStatus = () => {
      cancelAnimationFrame(timer);
      circleTop.value = 0;
      circleLeft.value = target;
  }
        
 let animate = () => {
   circleLeft.value += speed;
   circleTop.value = curve({ x: distance, y: 0 }, circleLeft.value - sourceLeft);

   if (isMoveLeft) {
         if (circleLeft.value <= target) {
    resetStatus();
        }
    } else {
        if (circleLeft.value >= target) {
            resetStatus();
         }
    }
    
    timer = requestAnimationFrame(animate);
 }
        
 animate();
}

每次位移时,保存初始位置 「sourceLeft」 , 和计算出位移长度 「distance」 与 每帧位移的长度 「speed」

这样就完成了丝滑的运动。

最终效果

如何实现抛物线跳跃交互底部导航栏?_第4张图片 tabbar.gif

效果还不错吧

总结

相信大家看完后能够学习或者复习到 「抛物线公式、径向渐变等」 一些常用的知识点,看完后大家也动手实现一个有意思的底部导航栏吧~

码字不易,看到这的话就动手点点赞吧,您每次的随手点赞都能给到我很大的动力!

如果文章对你有帮助的话欢迎

「关注+点赞+收藏」

你可能感兴趣的:(如何实现抛物线跳跃交互底部导航栏?)