声明:本人前端技术小白,借着图鸟UI Tabbar大赛学习一下前端知识,以下是思维过程。
前言
图鸟UI整了一个Tabbar大赛,正好最近有空,试着来参加一下,学习一下前端知识,以下是思维过程。
一、图鸟UI
官网:https://docs.ahuaaa.cn/
图鸟UI-是图鸟科技打造的开发者全成长周期开源平台,围绕酷炫、效率、合作、成就、变现,五大用户价值布局平台能力,全力服务开发者,旨在成为开发者的好朋友。图鸟历经多轮打磨雕刻,集海量高品质图鸟模板、实时在线预览、多元化场景模板、轻便好学、易上手等多重优势于一身的开发神器,更自带免费开源可商用属性,为企业集团、公司团队、前端后端开发者、运营大佬、社交达人、学生小白提供了一个零成本的在线开发平台和资源库。
二、前期思考
1.Tabbar选择
由于本人毫无审美,所以就在图鸟UI的Tabbar模板库看看选择一下大方向。地址:图鸟UI官网
看了一圈,对一个tabbar的样式很感兴趣。
因为之前在其他群里有人问过类似的突起效果怎么做,当时我的想法就是一个圆+两个马尾辫。借着这个机会,我想来复现一下我的想法。于是就准备复现以下这个圆弧。
2.突起平滑圆弧实现
1.双马尾 ❎
当时有人在群里问这种平滑圆弧如何实现,我当时的想法就是一个圆+两个双马尾:
.circle {
position: relative;
width: 300rpx;
height: 150rpx;
border-radius: 300rpx 300rpx 0 0;
background-color: red;
overflow: visible;
&::before {
content: '';
position: absolute;
top: 150rpx;
left: 300rpx;
width: 300rpx;
height: 150rpx;
border-radius: 0 0 300rpx 300rpx;
background-color: salmon;
border: 20rpx solid #000;
box-sizing: border-box;
}
}
效果:
看着就奇奇怪怪的不够平滑,这时候就很好奇图鸟是怎么实现这个效果的:翻阅图鸟代码发现是使用的SVG,好像SVG就是css中连续平滑曲线的最佳实现:
-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 61.5'%3E%3Cpath d='M100 0H0c32.9 0 49.3 61.5 100 61.5S167.1 0 200 0H100z'/%3E%3C/svg%3E"), linear-gradient(#000, #000);
但是我就想用css去实现该效果,于是继续仔细观察这个图像
这个图像很像三角函数中的sin图像移动而来,于是我准备在css中复现三角函数
2.三角函数 ❎
因为我们使用的是scss 于是百度scss sin函数图像实现:地址:sin图像实现
代码实现:scss sin函数实现
图像:
这个方法有个问题,那就是其函数图像是用连续的阴影来实现的而非border,这样会与border看起来失真。
3.剪裁圆形状 ❎
我们发现方法二双马尾中,曲线不平滑的原因就是快到交点的时候斜率骤降,导致图像不平滑,那我们就可以在不平滑之前,截断曲线,于是我将圆进行了剪裁,然后将两个圆进行拼接。
代码:
.mask {
position: relative;
--w: 200rpx;
--h: 100rpx;
width: calc(2*var(--w));
height: 50rpx;
background-color: aqua;
overflow: hidden;
.circle1 {
position: absolute;
width: var(--w);
height: var(--h);
border-top-right-radius: 100%;
background-color: red;
}
.circle2 {
position: absolute;
width: var(--w);
left: var(--w);
height: var(--h);
border-top-left-radius: 100%;
background-color: blue;
}
}
效果:
写到这里,大家想必都知道接下来咋办了吧,弦长公式计算出弦长然后将两个半圆分成两块,再剪裁x轴方向,将两个图像的顶点对齐即可。
但是这样也太复杂了,相较于svg好像没有半点优势,再观察svg图像,你会发现,其实图像连续的本质好像是斜率相同,即:两个圆相外切,平滑的本质就是在上图裁剪的部分作切点即可!
4.两图像在裁剪点相外切 ✅
综上所述,我们绘制以下草图:
代码:
//sqrt的scss实现
@function sqrt($r) {
$x0: 1;
$x1: $x0;
@for $i from 1 through 10 {
$x1: (
$x0 + $r / $x0) / 2;
$x0: $x1;
}
@return $x1;
}
$static-a: 10px;
$static-b: 20px;
$a-val: $static-a / 1px;
$b-val: $static-b / 1px;
$R-val: sqrt($a-val * $a-val + $b-val * $b-val) / 2;
$static-R: #{$R-val}px;
.box {
position: relative;
--a: #{$static-a};
--b: #{$static-b};
--R: #{$static-R};
.c1 {
position: absolute;
width: calc(2 * #{$static-R});
height: calc(2 * #{$static-R});
border-radius: 50%;
background-color: #fff;
z-index: 999;
}
.c2 {
position: absolute;
left: #{$static-b};
top: calc(-1 * #{$static-a});
width: calc(2 * #{$static-R});
height: calc(2 * #{$static-R});
border-radius: 50%;
background-color: #000;
}
}
效果:
接下来就是剪裁大法啦,将右边的图像y轴剪裁:r+a/2个长度即可啦。
代码:
.box {
position: relative;
--a: #{$static-a};
--b: #{$static-b};
--R: #{$static-R};
.c1 {
position: absolute;
width: calc(2 * #{$static-R});
height: calc(2 * #{$static-R});
border-radius: 50%;
background-color: #fff;
z-index: 999;
}
.c2 {
position: absolute;
left: #{$static-b};
top: calc(-1 * #{$static-a});
width: calc(2 * #{$static-R});
height: calc(2 * #{$static-R});
border-radius: 50%;
clip-path: polygon(0 #{$clip-height-px}, 50% #{$clip-height-px}, 50% 100%, 0 100%);
box-shadow: 0 0 0 10px #000;
}
但是我们发现因为使用了裁剪大法,当b和a的比值大时,图像是这样的:
因为使用了clip-path 导致shadow没有办法完整的显示出来,如果使用overflow: hidden;的话又太麻烦了。于是我就问GPT,css还有哪些方法画圆:
✅ 方法 1:使用 border-radius
✅ 方法 2:使用 clip-path
✅ 方法 3:使用 mask(遮罩)实现圆形
✅ 方法 4:使用 canvas
其他都知道,这个mask遮罩是什么东西?
background-image: radial-gradient(shape size at position, start-color, ..., last-color);
看了一下,好像是在指定地方position,创建画布,画出shape并且指定颜色。
at后面是相较于div进行定位,然后后面还可以控制背景图层的定位,这样子更容易画出我们想要的图像。
好像这个更方便一点
代码:`
.box {
--a: #{$static-a};
--b: #{$static-b};
--R: #{$static-R};
height: 200px;
width: 200px;
margin: 5px;
background:
radial-gradient(var(--R) at 50% var(--R), #000 100%, #0000 100%) center center / calc(4 * var(--b)) 100%,
radial-gradient(var(--R) at calc(50% + var(--b)) calc((var(--R) - var(--a))), #000 100%, #0000 100%) center center / calc(4 * var(--b)) 100% no-repeat;
}
效果:
然后就是无聊的乐高时间~
.box {
--a: #{$static-a};
--b: #{$static-b};
--R: #{$static-R};
height: calc(2*var(--b));
width: 200px;
margin: 5px;
background-color: aqua;
background:
radial-gradient(calc(2*var(--R)) at 50% calc(var(--b) + var(--a)), #000 99%, #0000 101%) calc(50% - 2*var(--b)) 0/calc(4*var(--b)) 100% no-repeat,
radial-gradient(calc(2*var(--R)) at 50% calc(-1*var(--a)), #0000 99%, #fff 101%) 50% var(--b)/calc(4*var(--b)) 100% no-repeat;
}
- 出门回来再拼乐高吧,先用div写一个,时间来不及了呜呜呜,下午要出门。理论上一个div就可以实现这个的渲染。
3. 添加动画
加一点贝尔曲线,再加一个到点翻转(实在是没时间了,要出门了qwq)
总结
以上方法可以用一个div radial-gradient 实现任意曲线。
曲线平滑过渡:外切。
我是一个个人开发者,我从事于校园市场。
开源课表(准备用图鸟UI重写):https://gitee.com/czczcz666/kezhidao
VX:lczwuairu 欢迎交流。