likes
comments
collection
share

实现抛物线跳跃交互底部导航栏🎈🎈🎈

作者站长头像
站长
· 阅读数 19

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

写在最前

狠久没更新了,写了几篇草稿,感觉一般就没想着发布,厦门的夏天是真热啊,上个月本以为是巅峰,想着能否挑战一年不开空调,没想到仅仅只是开始,听说下个礼拜会下雨,期待。

做这个效果的初衷是当年在第一家公司的时候,我们的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);

实现抛物线跳跃交互底部导航栏🎈🎈🎈

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

mask 遮罩

语法与 background 相似,不展开。

-webkit-mask: radial-gradient(circle at 50rpx 0rpx, transparent 45rpx, #999999 45rpx)

实现抛物线跳跃交互底部导航栏🎈🎈🎈

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

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

最终效果

实现抛物线跳跃交互底部导航栏🎈🎈🎈

效果还不错吧 😍

总结

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

码字不易,看到这的话就动手点点赞吧,您每次的随手点赞都能给到我很大的动力!
转载自:https://juejin.cn/post/7254488391025639483
评论
请登录