CSS—形状就该随心所欲

6,480 阅读4分钟

说到div的形状,基本上想到的都是圆形或者方形,这两种形状其实也已经符合了前端95%的应用场景(95%的数据从哪得来的 - - !),但是作为一个不愿随波逐流的程序员,就是要搞事情。

兼容性

image

(图片来源于网络)果然限制我们创造的不是想象力,而是兼容性。支持浏览器的版本偏高,如果你是做正经项目还是不推荐使用,如果是自己的或者比较新潮的项目,那就开搞吧! ( 道路千万条,兼容第一条。尝鲜有风险,翻车两行泪。)。手机端记得加上-webkit-clip-path: polygon()

几个小案例先祭天

  1. 圆形 => 西瓜

clip-path: polygon(100% 100% , 0 100% , 50% 0 );

image

  1. 正方形 => 三角形

clip-path: polygon(0 0 , 0 100% , 100% 50% );

image

  1. 正方形 => 箭头

clip-path: polygon(100% 50% , 0 100% , 50% 50% , 0 0);

image

  1. 椭圆形 => 钻石

clip-path: polygon(50% 100% , 100% 10% , 0 10%);

image

分析 clip-path:polygon()

先根据上面的三角形画一张分析图

image

可以看到括号中由一对值组成。在当前的div内,分别对应 xy坐标 ,接收单位px 或者%(推荐百分比),用逗号分隔,逗号后写入的值代表一个新的点,新的点会与原来的点连成线,点的数量不限。

两个问题:
  1. 点一旦多起来,坐标一堆。眼睛看花了,修改也不方便。
  • 既然你都做了前端,想必你一定已经掌握了通灵之术:

image

火狐在这个属性的调试上有很好的支持

image

点击属性旁边的图标,线条就可以随意拖动了,会随着你是`%`还是`px`自动进行调整
  1. 点与点只能连成直线,那我想要画个带圆弧的形状岂不是要建无数个点。
  • 很遗憾,这个属性虽然也有对应的圆形clip-path:circle()跟椭圆clip-path: ellipse()但两者并不能同时使用。并且因为这个属性是裁剪的,只要超出线的范围都会被裁减掉,所以尝试用::after::befor填充上弧形,效果也不尽人意,参照这个西瓜。

    image

  • 另外一个缺点就是,超出部分都不会显示,而普通的box-shadow是基于这个盒子做的阴影,理所当然的阴影也被裁剪掉了。

    image

    所以需要给box-shadow加上内阴影box-shadow: inset 3px 2px 16px #bbb;(但是阴影是不会根据你的线条来形成的,还是一样根据盒子,所以使用起来要见仁见智了)

分析 clip-path:circle()clip-path: ellipse()

clip-path:circle是用来裁剪圆形,单位也是支持px%,它提供了三个参数(圆形半径 at x方向坐标 y方向坐标)

image

clip-path: ellipse跟上面区别就在于它把圆的半径拆分成x方向的半径/y方向的半径

image

动画

clip-path对动画的过渡有着很好的支持,下面来一个小demo

image

.demo_box{
    width: 100px;
    height: 100px;
    border-radius:50%;
    background:#ffa700;
    clip-path: polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%, 0% 25%, 50% 50%, 0% 80%);
    animation:a 1s infinite alternate;
}
@keyframes a {
    0%, 10% {
        clip-path: polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%, 0% 25%, 50% 50%, 0% 80%)
    }
    90%, 100% {
        clip-path: polygon(0% 100%, 100% 100%, 100% 0%, 0% 0%, 0% 50%, 60% 50%, 0% 60%)
    }
}

搭配shape-outside让图形嵌入文字中

shape-outsideclip-path一样都有对应的polygoncircleellipse它们对应的参数也是一样的,需要div浮动才能生效

image

赠送扫二维码CSS动画

路线的条纹是截图工具的问题实际上是没有的。

image

<div class="scan"></div>

.scan {
  width: 150px;
  height: 150px;
  margin: 30px auto;
  position: relative;
  background: linear-gradient(to left, #108EE9, #108EE9) left top no-repeat, linear-gradient(to bottom, #108EE9, #108EE9) left top no-repeat, linear-gradient(to left, #108EE9, #108EE9) right top no-repeat, linear-gradient(to bottom, #108EE9, #108EE9) right top no-repeat, linear-gradient(to left, #108EE9, #108EE9) left bottom no-repeat, linear-gradient(to bottom, #108EE9, #108EE9) left bottom no-repeat, linear-gradient(to left, #108EE9, #108EE9) right bottom no-repeat, linear-gradient(to left, #108EE9, #108EE9) right bottom no-repeat;
  background-size: 3px 20px, 20px 3px, 3px 20px, 20px 3px;
}

.scan::after {
  content: '';
  width: 140px;
  border: 1px solid #BBE2FF;
  position: absolute;
  left: 5px;
  top: 2px;
  animation: myfirst 4s infinite;
}
@keyframes myfirst {
  from {
    top: 2px;
  }
  to {
    top: 144px;
  }
}