CSS中的基本图形和路径

发布于 大漠

在CSS中有些属性是允许CSS绘制图形形状,比如常见的是使用border或者box-shadow来绘制图形或者形状。除此之外,在CSS中还有类似circle()函数也可以绘制圆形。

除此之外,在CSS中有一些形状是为CSS其它属性服务,比如clip-pathmask服务和在shape-outside让文本围绕形状排版。

还有一些CSS属性使用像SVG中的图形做一些事情,比如offset-path中使用path()函数实现路径动画。而其中path()是一个非常棒的功能,可以绘制任何图形。

在接下来的内容中,来介绍一下CSS中的基本图形和路径。希望对大家有所帮助。

CSS中的基本图形

在CSS中polygon()circle()ellipse()inset()函数可以绘制基本形状。在CSS中的offset-pathshape-outside中都可以使用这四个图形函数,实现对应的路径动画以及文本围绕排版效果。他们虽然绘制基本形状,但也常将其称之为路径图形。那么什么是路径呢?

什么是路径

使用过SVG的同学对路径这个词并不会感到陌生,在SVG中有一个<path>元素,允许我们绘制任何东西。在HTML中,我们可以这样来使用<path>绘制图形:

<path d="M 25,100 C 25,150 75,150 75,100 S 100,25 150,75" />

在CSS中可以通过path()来实现类似上面绘制图形的效果:

path("M 25,100 C 25,150 75,150 75,100 S 100,25 150,75");

属性中的图形

如果你前面有接触过clip-path或者shape-outside话知道。虽然这里面用到类似像circle()polygon()的图形,但令人奇怪的是,使用的并不是像SVG中的<path>或者说path()函数。而offset-path却可以使用path()而不是基本图形里面的图形函数。

看上去有些混乱,但我们可以慢慢将这些理一理,能帮助你更好的理解CSS中的形状和路径。

clip-path可以使用基本形状但不能使用path()

在CSS的clip-path属性中可以使用CSS的基本图形(polygon()circle()ellipse()inset())但不能使用path()。比如,我们在项目中需要使用不规则的用户头像,那么我们可以通过clip-path来完成。比如:

.avatar {
  clip-path: polygon(0% 5%, 100% 0%, 100% 85%, 65% 80%, 75% 100%, 40% 80%, 0% 75%);
}

你能看到类似下图的效果:

但是,如果你想要用户的头像实现像下图这样形状的效果:

对于上图这样的形状,使用基本的图形形状函数是没办法实现的,但在clip-path中又没有办法使用path()函数。不过值得庆幸的是,在clip-path中可以通过url()传一个带有ID属性名的<clipPath>元素。

<clipPath>是SVG中的一个元素,在这里面可以通过<path>元素绘制所需要的图形。比如上面所需的图形,可以通过下面的SVG来绘制:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 201 196.1" class="hide">
    <title>bubble-path</title>
    <clipPath id="clip">
        <path d="M100.5,39.47C100.5,58.3,83.36,74,60.58,77.64l16.85,19.9L33.94,76.25C14.47,70.92.5,56.47.5,39.47c0-21.52,22.39-39,50-39S100.5,17.95,100.5,39.47Z" fill="#fff" stroke="#000" stroke-miterlimit="10"></path>
    </clipPath>
</svg>

特别注意:在clipPath中需要指定一个明确的ID属性值,比如这里指定了id="clip",另外为了让SVG元素不显示,不占空间,给<svg>元素指定个hide类名,然后设置样式,让<svg>元素隐藏起来:

.hide {
  	position: absolute;
  	top: -9999px;
  	left: -9999px;
}

这个时候再通过clip-pathurl()将SVG绘制的路径图形,运用到用户头像中:

.avatar {
    width: 100px;
  	height: 100px;
  	margin-right: 2rem;
  	clip-path: url(#clip);
}

此时你将看到的效果如下图所示:

offset-path可以使用path()但不能使用基本形状

offset-path早期称为motion-path。只是后来规范将其改变offset-path,而它主要用来制作路径动画效果,用来指定动画的行动路径。比如下面这个效果:

动画中的小圆球行动的路径,就是通过path()来完成的:

path("M100.5,39.47C100.5,58.3,83.36,74,60.58,77.64l16.85,19.9L33.94,76.25C14.47,70.92.5,56.47.5,39.47c0-21.52,22.39-39,50-39S100.5,17.95,100.5,39.47Z");

具体的代码如下:

.move-me {
  	offset-path: path("M100.5,39.47C100.5,58.3,83.36,74,60.58,77.64l16.85,19.9L33.94,76.25C14.47,70.92.5,56.47.5,39.47c0-21.52,22.39-39,50-39S100.5,17.95,100.5,39.47Z");
  	animation: move 3s linear infinite;
}
@keyframes move {
  	100% {
  		motion-offset: 100%;
  	}
}

同样的有一个问题,如果你想让小球按一个圆形来运动,你可能会想到像circle(50% at 50% 50%)来绘制的图形路径,但不幸的是,没有效果。那是因为offset-path并不支持circle()函数绘制的路径。不过值得庆幸的是,同样可以使用path()来会制一个圆形:

offset-path: path("M100,50a50,50,0,1,1-50-50A50,50,0,0,1,100,50Z");

除此之外,还可以使用复合动画来模拟一个圆形动画效果。在@Lea Verou的《CSS Secrets》一书中就有一节专门介绍使用其它方法来实现圆形的路径动效

其中原理很简单,简单用下图就能阐述:

shape-outside可以使用基本图形,但不支持path()

shape-outsideclip-path类似,在其属性值中只能使用CSS的基本图形函数,但不能使用path()函数绘制的图形。

shape-outside是能让文本围绕不同形状排版,如果从未接,可以点击早前整理的相关文章

来看一个简单的示例:

.egg {
  	float: left;
  	shape-outside: ellipse(120px 160px at 50% 50%);
  	width: 280px;
  	height: 320px;
}

将看到的效果如下:

而其中效果图中的椭圆是通过clip-path绘制的:

clip-path: ellipse(120px 160px at 50% 50%);

但有时候你想让文本围绕一个弯曲的形状进行排版,像下图所示:

CSS中的基本图形函数是没法绘制上图那相的曲线图形形状,但path()可以,只不过shape-outside不能支持path()绘制的形状。不过还好,在shape-outside中也可以通过url()来传SVG中绘制好的形状。也可以像传递一个图片的形式使用:

shape-outside: url('curved-shape.svg');

使用shape-outside实现文本围绕不同形状的排版效果,需要对图形元素使用浮动。但在CSS中提供了CSS Exclusions模块,它可以解决这个问题。如果你感兴趣的话,可以阅读《CSS Exclusions:让布局变得更有意思》一文。

在CSS中使用path()改变的基本图形

在SVG中可以通过<path>来绘制图形。比如:

<svg viewBox="0 0 10 10" class="svg-1">
  <path d="M2,2 L8,8" />
</svg>

很有意思的是,在CSS中可以使用path()来改变SVG中的<path>图形:

.svg-1:hover path {
  	d: path("M8,2 L2,8");
}

从上面的效果和代码中,可以看出。在CSS中给显式的设置了path元素的样式,修改path元素的属性的属性值。比如path元素中的d属性的值,<circle>元素中的cxcyr的值:

svg:hover circle {
  	cx: 40;
  	cy: 40;
  	r: 40;
}

看上去是不是很有意思。

总结

这篇文章简单的介绍了CSS中属性中怎么使用基本图形函数和路径图形函数:

  • clip-pathshape-outside属性值中可以使用polygon()circle()ellipse()inset()函数绘制的图形,但不能使用path()函数,不过可能通过url()给其传<svg><path>元素绘制的图形
  • offset-pathclip-path以及shape-outside相反,只能使用path()函数绘制的图形,但不能使用CSS中绘制图形的图形函数
  • 在CSS中可以显式的重置svg元素中图形元素的属性值,从而改变SVG绘制的图形

扩展阅读

文章中部分图片和效果来自于@CHRIS COYIER的博文《Basic Shapes & Path… Never the Twain Shall Meet?》。

另外文章中涉及到的一些相关属性知识,可以阅读下列相关文章:

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.fedev.cn/css/basic-shapes-path.htmlAir Jordan XI 11 Wool