震惊!惊呆了!如何实现方形 border-radius ?

前言

直奔主题,下面就是我们要实现的效果:

image.png

抱歉各位,border-radius确实不能方形。但是我们是可以模仿这种效果的。

(标题为什么要加“震惊!惊呆了!”这些字?因为看到掘金上出现了一股现象:很多热点文章,标题总要加点乱七八糟的字眼。点进来一看,标题上突出的内容根本没讲明白。但是很引流啊。小的斗胆做一次标题党,请各位大佬见谅。-_-)

话说CSS中确实有很多奇形怪状需要画,看着还不太好实现。今天咱们就挑这一个来实现。

进入正题吧,本文就是想实现一个方形的border-radius效果。

咱们今天要用的就是clip-path属性。path就是路径。我们需要做的就是画出一条路径,来勾勒出我们需要实现的形状。

我们按照思考过程,写完整个实现过程。

1、实心三角形

先看效果:

image.png

图形总宽度 400px, 总高度 200px。

我们先给一个很常见的方案: 咦?这个很多同学都很熟悉:

  • content区的width/height 设置为0;
  • 一方 border width 设置为0;
  • 其相邻 border 设置 transparent;
  • 来看代码吧:

    .div {
        height: 0;
        width: 0;
        border-top: 200px solid lightgreen;
        border-bottom-width: 0;
        border-left: 200px solid transparent;
        border-right: 200px solid transparent;
    }
    

    然后我们看看用clip-path的方案: 我们只需要给出三个点的位置即可。

    我们都知道,前端常用的坐标系,是一个Y轴朝下的坐标系。

    左上角的点是(0,0),右下角的是(100%, 100%),当然,你也可以用px等任意长度单位。

    第一个点是左上角,也就是 (0,0)

    第二个点是底部这个点。x轴偏移50%, y轴偏移100%,就是(50%, 100%)

    第三个点是右边这个点。x轴偏移100%, y轴偏移0,就是(100%, 0)

    看代码:

    .div {
        height: 200px;
        width: 400px;
        background: lightgreen;
        clip-path: polygon(0 0, 50% 100%, 100% 0);
    }
    

    其中有一个单词:polygon ,是多边形的意思。这里我们给出了多边形的三个顶点,浏览器渲染引擎帮我们渲染出了这三个点围成的一个形状,也就是三角形。

    同理,我们如果给出n个点,我们可以实现实心的n边形。

    2、实心圆

    题外话,除了polygon以外,我们还可以实现圆形/椭圆形等,一下是一个圆形:

    它的直径200px。

    image.png

    .div {
        height: 400px;
        width: 400px;
        clip-path: circle(200px at 50% 50%);
        background: green;
    }
    

    at前面这个数字,表示半径。 at后面的2个数字,表示圆心位置。

    4、实心八边形

    我们想实现方形的border-radius,实际上是要实现一个空心的八边形。

    步子别跨的那么快,我们先把实心八边形搞定一下。

    我们要实现下图的样子,首先分析一下每个点的坐标:

    image.png

    于是麻利的把8个点标注上去,代码如下:

    .div {
        height: 400px;
        width: 400px;
        clip-path: polygon(
            20px 0, calc(100% - 20px) 0,
            100% 20px, 100% calc(100% - 20px),
            calc(100% - 20px) 100%, 20px 100%,
            0 calc(100% - 20px), 0 20px
        );
        background: green;
    }
    

    4、实心八边形

    我们想实现方形的border-radius,实际上是要实现一个空心的八边形。

    步子别跨的那么快,我们先把实心八边形搞定一下。

    我们要实现下图的样子,首先分析一下每个点的坐标:

    image.png

    于是麻利的把8个点标注上去,代码如下:

    .div {
        height: 400px;
        width: 400px;
        clip-path: polygon(
            20px 0, calc(100% - 20px) 0,
            100% 20px, 100% calc(100% - 20px),
            calc(100% - 20px) 100%, 20px 100%,
            0 calc(100% - 20px), 0 20px
        );
        background: green;
    }
    

    特别注意⚠️:我们只需要画八个点,最后一个点,不需要回到起点,会自动闭合。

    5、空心的八边形

    速度放慢一点,这个时候我们还不想立刻实现最终效果,我们先实现一个镂空的图形,之前踩了一个坑,下面是2份代码,做个比较:

    image.png

    正确代码:

    .div {
        height: 400px;
        width: 400px;
        clip-path: polygon(
            20px 0, calc(100% - 20px) 0, 100% 20px, 100% calc(100% - 20px),
            calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 20px), 0 20px,
            20px 0, 50px 100px, 100px 50px);
        background: green;
    }
    

    起点和终点自动闭合,效果如下:

    image.png

    错误代码:

    这是错误示例: 内圈和外圈的方向一致,无法勾勒出空心图形。 image.png

    .div {
        height: 400px;
        width: 400px;
        clip-path: polygon(
            20px 0, calc(100% - 20px) 0, 100% 20px, 100% calc(100% - 20px),
            calc(100% - 20px) 100%, 20px 100%, 0 calc(100% - 20px), 0 20px,
            20px 0, 50px 100px, 100px 50px);
        background: green;
    }
    

    效果如下:

    image.png

    6、最终效果?不

    这一步,我们将很接近想要实现的效果了。但还不是最终的。

    我们这一步可以实现以下效果:

    image.png

    按照我们上一步的思路,内外方向如果相同,那么就会是实心的效果。所以,我们暂定:外圈是顺时针方向,内圈是逆时针方向:

    image.png

    内圈8个点,外圈8个点。 注意观察,我们中间的20px 0 使用2次了。

    但是起点和终点,我们不能使用同一个点。

    我们一共使用了17个点。

    所以我们的代码是这样的:

    .div {
        height: 400px;
        width: 400px;
        clip-path: polygon(
            20px 0,
            calc(100% - 20px) 0,
            100% 20px,
            100% calc(100% - 20px),
            calc(100% - 20px) 100%,
            20px 100%,
            0 calc(100% - 20px),
            0 20px,
            20px 0,
            20px 4px,
            4px 20px,
            4px calc(100% - 20px),
            20px calc(100% - 4px),
            calc(100% - 20px) calc(100% - 4px),
            calc(100% - 4px) calc(100% - 20px),
            calc(100% - 4px) 20px,
            calc(100% - 20px) 4px,20px 4px)
        background: green;
    }
    

    细心的同学可能会发现,转折处的边框,是不是宽度变小了?

    image.png

    这到底是什么原因呢?

    会不会是勾股定理?

    哦,确实,实际转折处的宽度,是 4/1.414 = 2.8左右。

    7、最终效果!

    作为一个严谨的程序员,我们把这个小小的误差修复一下:

    我们需要将外圈的20px,统统改为 20 - 4/1.414 = 18.8px左右。

    .div {
        height: 400px;
        width: 400px;
        clip-path: polygon(
            18.8px 0,
            calc(100% - 18.8px) 0,
            100% 18.8px,
            100% calc(100% - 18.8px),
            calc(100% - 18.8px) 100%,
            18.8px 100%,
            0 calc(100% - 18.8px),
            0 18.8px,
            18.8px 0,
            20px 4px,
            4px 20px,
            4px calc(100% - 20px),
            20px calc(100% - 4px),
            calc(100% - 20px) calc(100% - 4px),
            calc(100% - 4px) calc(100% - 20px),
            calc(100% - 4px) 20px,
            calc(100% - 20px) 4px,
            20px 4px
        )
        background: green;
    }
    

    最终效果:

    image.png

    转角处放大细节:

    image.png

    这次真的是等宽的边框了!!

    后续

    本来想写一个文章介绍所有CSS的奇形怪状,但是时间有限,挑了一个有意思的来实现。

    这里实现的图形,是空心的,而且中间是透明的,不会遮挡底层内容。

    我们可以写一个上述的div,position:absolute 定位作为背景使用,就相当于一个 方形的border-radius了。

    最后:我这应该不算标题党吧。标题说的效果,我是百分百实现了啊。求各位大佬轻声批评!

    猜你喜欢

    转载自juejin.im/post/7126107207036305445