shape()

实验性: 这是一个 实验性技术
在生产环境中使用此功能之前,请仔细查看 浏览器兼容性表格

shape() CSS 函数 用于为 clip-pathoffset-path 属性定义形状。它将初始起点与一系列定义形状路径的形状命令结合起来。shape() 函数是 <basic-shape> 数据类型的成员。

语法

css
/* <fill-rule> */
clip-path: shape(nonzero from 0 0, line to 10px 10px);

/* <move-command>, <line-command>, and close */
offset-path: shape(from 10px 10px, move by 10px 5px, line by 20px 40%, close);

/* <hvline-command> */
offset-path: shape(from 10px 10px, hline by 50px, vline to 5rem);

/* <curve-command> */
offset-path: shape(from 10px 10px, curve to 80px 80px via 160px 1px 20% 16px);

/* <smooth-command> */
offset-path: shape(from 10px 10px, smooth to 100px 50pt);

/* <arc-command> */
offset-path: shape(
  from 5% 0.5rem,
  arc to 80px 1pt of 10% ccw large rotate 25deg
);

/* Using a CSS math function */
offset-path: shape(
  from 5px -5%,
  hline to 50px,
  vline by calc(0% + 160px),
  hline by 70.5px,
  close,
  vline by 60px
);

clip-path: shape(
  evenodd from 10px 10px,
  curve to 60px 20% via 40px 0,
  smooth to 90px 0,
  curve by -20px 60% via 10% 40px 20% 20px,
  smooth by -40% -10px via -10px 70px
);

参数

<fill-rule> 可选

指定如何填充形状的重叠区域。可能的值包括

  • nonzero:如果从点绘制的射线与左侧到右侧的路径段的交点数多于右侧到左侧的路径段的交点数,则该点被视为在形状内部,从而产生非零计数。当省略 <fill-rule> 时,这是默认值。
  • evenodd:如果从点绘制的射线与路径段的交点数为奇数,则该点被视为在形状内部。这意味着每次射线进入形状时,它都没有退出相同次数,表明输入次数为奇数,而没有相应的退出次数。

警告:<fill-rule>offset-path 中不受支持,使用它会使该属性无效。

from <coordinate-pair>

将第一个 <shape-command> 的起点定义为一对坐标,这些坐标是从 参考框 的左上角测量的。坐标被指定为以空格分隔的 <x> <y> <length-percentage> 值,分别表示左侧偏移量和顶部偏移量。百分比值分别相对于元素参考框的宽度和高度。在此参数后添加逗号。

<shape-command>

指定一个或多个用逗号分隔的命令列表,这些命令使用类似于 SVG 路径命令 的语法来定义形状。命令包括 <move-command><line-command><hv-line-command><curve-command><smooth-command><arc-command>close。每个命令的起点是前一个命令的终点,形状的第一个点由 from <coordinate-pair> 参数定义。

大多数形状命令的语法是一个提供指令的关键字,例如 moveline,后跟 byto 关键字,以及一组坐标。

by:表示 <coordinate-pair> 相对于命令的起点(“相对”值)。

to:表示 <coordinate-pair> 相对于参考框的左上角(“绝对”值)。

注意:如果 <coordinate-pair> 中的坐标被指定为百分比,则该值相对于参考框的相应宽度或高度计算。

可以指定以下 <shape-command><move-command><line-command><hv-line-command><curve-command><smooth-command><arc-command>close

<move-command>:指定为 move [by | to] <coordinate-pair>。此命令将 移动到命令 添加到形状命令列表中。它不绘制任何内容。相反,它指定下一个命令的起始位置。byto 关键字分别指定 <coordinate-pair> 点是相对的还是绝对的。如果 <move-command> 位于 close 命令之后,它标识下一个形状或子路径的起始点。

<line-command>:指定为 line [by | to] <coordinate-pair>。此命令将一个LineTo 命令添加到形状命令列表中。它从命令的起始点绘制一条直线到其结束点。byto 关键字分别指定由 <coordinate-pair> 指定的结束点是相对的还是绝对的。

<hv-line-command>:指定为 [hline | vline] [by | to] <length-percentage>。此命令将一个水平 (hline) 或垂直 (vline) LineTo 命令添加到形状命令列表中。使用 hline,将从命令的起始点绘制一条水平线到或偏移由 <length-percentage> 定义的 x 位置。使用 vline,将从命令的起始点绘制一条垂直线到或偏移由 <length-percentage> 定义的 y 位置。byto 关键字分别确定相对或绝对的结束点。此命令等效于 <line-command>,其中一个坐标值由单个 <length-percentage> 设置,另一个坐标值保持与其起始命令相同。

<curve-command>:指定为 curve [by | to] <coordinate-pair> via <coordinate-pair> [<coordinate-pair>]。此命令将一个贝塞尔曲线命令添加到形状命令列表中。byto 关键字分别确定由第一个 <coordinate-pair> 指定的曲线的结束点是相对的还是绝对的。via 关键字指定贝塞尔曲线的控制点。

  • 如果只提供了一个 <coordinate-pair>,则该命令绘制一个二次贝塞尔曲线,它由三个点(起始点、控制点和结束点)定义。
  • 如果提供了两个 <coordinate-pair> 值,则该命令绘制一个三次贝塞尔曲线,它由四个点(起始点、两个控制点和结束点)定义。

<smooth-command>:指定为 smooth [by | to] <coordinate-pair> [via <coordinate-pair>]。此命令将一个平滑的贝塞尔曲线命令添加到形状命令列表中。byto 关键字分别确定由第一个 <coordinate-pair> 指定的曲线的结束点是相对的还是绝对的。

  • 如果省略了 via <coordinate-pair>,则该命令绘制一个平滑的二次贝塞尔曲线,它使用先前的控制点和当前端点来定义曲线。
  • 如果包含可选的 via 关键字,则它通过 <coordinate-pair> 指定曲线的控制点,绘制一个平滑的三次贝塞尔曲线,该曲线由先前的控制点、当前控制点和当前端点定义。

平滑曲线确保形状的过渡平滑,而二次曲线则没有。平滑的二次曲线使用单个控制点保持无缝过渡,而平滑的三次曲线则使用两个控制点提供更精细的过渡。

<arc-command>:指定为 arc [by | to] <coordinate-pair> of <length-percentage> [<length-percentage>] [<arc-sweep> | <arc-size> | rotate <angle>]。此命令将一个椭圆弧曲线命令添加到形状命令列表中。它在起始点和结束点之间绘制一个椭圆弧。byto 关键字分别确定由第一个 <coordinate-pair> 指定的曲线的结束点是相对的还是绝对的。

椭圆弧曲线命令定义了两个可能的椭圆,它们与起始点和结束点相交,并且每个都可以顺时针或逆时针跟踪,根据弧的大小、方向和角度,导致四种可能的弧。of 关键字指定弧线取自的椭圆的大小:第一个 <length-percentage> 提供椭圆的水平半径,第二个 <length-percentage> 提供椭圆的垂直半径。

指定以下参数以选择要使用的四种弧线中的哪一种

  • <arc-sweep>:指示所需的弧线是围绕椭圆顺时针 (cw) 还是逆时针 (ccw) 跟踪的弧线。如果省略,则默认为 ccw
  • <arc-size>:指示所需的弧线是两个弧线中较大的 (large) 还是较小的 (small) 弧线。如果省略,则默认为 small
  • <angle>:指定相对于 x 轴旋转椭圆的角度(以度为单位)。正角度顺时针旋转椭圆,负角度逆时针旋转椭圆。如果省略,则默认为 0deg

特殊情况处理如下

  • 如果只提供了一个 <length-percentage>,则相同的值用于水平和垂直半径,从而有效地创建一个圆。在这种情况下,<arc-size><angle> 没有影响。
  • 如果任一半径为零,则该命令等效于到结束点的 <line-command>
  • 如果任一半径为负,则使用其绝对值代替。
  • 如果水平和垂直半径不能描述一个足够大的椭圆以与起始点和结束点(在通过指定的 <angle> 旋转后)相交,则统一放大半径,直到椭圆恰好足够大以与这两个点相交。
  • 如果弧线的起始点和结束点正好位于椭圆的对侧,则只有一个可能的椭圆和两个可能的弧线。在这种情况下,<arc-sweep> 指定要选择的弧线,<arc-size> 没有影响。

close:将一个ClosePath 命令添加到形状命令列表中,从当前位置(最后一个命令的末尾)绘制一条直线到 from <coordinate-pair> 参数中定义的路径的第一个点。要关闭形状而不绘制线条,请在 close 命令之前包含一个带有起始坐标的 <move-command>。如果 close 命令紧跟在 <move-command> 之后,则它定义下一个形状或子路径的起始点。

描述

shape() 函数允许您定义复杂的形状。它在许多方面类似于path() 形状函数

  • shape() 函数中的 <fill-rule> 参数的工作方式与 path() 函数中的相同参数完全相同。
  • shape() 函数需要指定一个或多个 <shape-command>,其中每个命令都使用底层的路径命令,例如MoveToLineToClosePath

但是,shape() 比使用 path() 提供了一些优势

  • shape() 使用标准 CSS 语法,使您能够更轻松地在样式表中直接创建和修改形状。相比之下,path() 使用SVG 路径 语法,对于不熟悉 SVG 的人来说,这种语法不太直观。
  • shape() 支持各种 CSS 单位,包括百分比、remem。另一方面,path() 将形状定义为单个字符串,并将单位限制为 px
  • shape() 还允许使用 CSS 数学函数,如calc()max()abs(),在定义形状时提供更多通用性。

正式语法

<shape()> = 
shape( <'fill-rule'>? from <coordinate-pair> , <shape-command># )

<fill-rule> =
nonzero |
evenodd

<coordinate-pair> =
<length-percentage>{2}

<shape-command> =
<move-command> |
<line-command> |
<hv-line-command> |
<curve-command> |
<smooth-command> |
<arc-command> |
close

<length-percentage> =
<length> |
<percentage>

<move-command> =
move <by-to> <coordinate-pair>

<line-command> =
line <by-to> <coordinate-pair>

<hv-line-command> =
[ hline | vline ] <by-to> <length-percentage>

<curve-command> =
curve [ <by-to> <coordinate-pair> using <coordinate-pair>{1,2} ]

<smooth-command> =
smooth [ [ <by-to> <coordinate-pair> ] || [ using <coordinate-pair> ]? ]

<arc-command> =
arc [ [ <by-to> <coordinate-pair> ] || [ of <length-percentage>{1,2} ] || <arc-sweep>? || <arc-size>? || [ rotate <angle> ]? ]

<by-to> =
by |
to

<arc-sweep> =
cw |
ccw

<arc-size> =
large |
small

示例

使用 shape() 定义路径

此示例演示了如何在offset-path 属性中使用 shape() 函数来定义元素可以遵循的路径的形状。

第一个形状 shape1 遵循由 curve to 命令定义的三次贝塞尔曲线路径。接下来,close 命令从曲线的结束点绘制一条直线回到 from 命令中定义的初始点。最后,shape1 移动到其在 0px 150px 的新位置,然后沿着水平线继续。

第二个形状 shape2 最初遵循一条水平线,然后移动回其在 50px 90px 的起始位置。接下来,它遵循一条垂直线,然后关闭路径回到初始点。

这两个形状都以其原始颜色开始,并在动画结束时逐渐过渡到 hotpink,并在动画重新开始时恢复到其初始颜色。这种循环的颜色变化为您提供了有关动画进度和重新开始的视觉线索。

css
.shape {
  width: 50px;
  height: 50px;
  background: #2bc4a2;
  position: absolute;
  text-align: center;
  line-height: 50px;
  animation: move 6s infinite linear;
}

.shape1 {
  offset-path: shape(
    from 30% 60px,
    curve to 180px 180px via 90px 190px,
    close,
    move by 0px 150px,
    hline by 40%
  );
}

.shape2 {
  offset-path: shape(
    from 50px 90px,
    hline to 8em,
    move to 50px 90px,
    vline by 20%,
    close
  );
}

@keyframes move {
  0% {
    offset-distance: 0%;
  }
  100% {
    offset-distance: 100%;
    background-color: hotpink;
  }
}

结果

使用 shape() 定义元素的可见部分

此示例演示了如何在clip-path 属性中使用 shape() 函数为剪裁区域创建不同的形状。第一个形状 (shape1) 使用由直线定义的三角形。第二个形状 (shape2) 包括曲线和平滑过渡;它还说明了在 close 命令之后使用 <move-command> 的方法,这将一个矩形形状添加到剪裁区域。

css
.shape {
  width: 100%;
  height: 100%;
  background: #2bc4a2;
  position: absolute;
  text-align: center;
  line-height: 50px;
}

/* Triangular clipping region */
.shape1 {
  clip-path: shape(from 0% 0%, line to 100% 0%, line to 50% 100%, close);
}

/* Clipping region with curves and smooth transitions and a box */
.shape2 {
  clip-path: shape(
    from 10px 10px,
    curve to 60px 20% via 40px 0,
    smooth to 90px 0,
    curve by -20px 60% via 10% 40px 20% 20px,
    smooth by -40% -10px via -10px 70px,
    close,
    move to 100px 100px,
    hline by 50px,
    vline by 50px,
    hline by -50px,
    close
  );
}

结果

规范

规范
CSS Shapes 模块级别 2
# shape-function

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅