【问题标题】:clip-path:circle() radius doesn't seem to be calculated correctlyclip-path:circle() 半径似乎没有正确计算
【发布时间】:2020-05-03 20:28:51
【问题描述】:

每当我尝试使用 CSS circle() 函数进行一些剪辑时,我一直困扰着我:

.red {
  	width: 200px;
        height: 300px;
        background: red;
        border: 2px solid black;
        clip-path: circle(69%);  /*barely cuts off the corners of the .red div */
}

/*  the full circle will enclose the entire box at around 71% or (sqrt(2)/2 * 100%)
 per Mozilla documentation and not at 100% as one might expect */
<div class='red'></div>

似乎从来没有像我期望的那样计算半径。在查看 Mozilla MDN 参考 (https://developer.mozilla.org/en-US/docs/Web/CSS/basic-shape) 后,他们似乎按如下方式计算:





这对我来说似乎不正确。我想他们会计算包围元素矩形(div、img 等)的圆周半径,如下所示:





但情况似乎并非如此。任何人都可以对此有所了解。这是某种错误还是我只是不理解这里的东西?

【问题讨论】:

  • @G-Cyr,看,即使在您的示例中,将 red:hover 圆半径更改为 71% 也会显示整个红色矩形。我不确定这是如何“预期”的

标签: css geometry clip-path


【解决方案1】:

它的定义是这样的,他们从来没有打算计算你所显示的半径。也是in the specification

为了更好地理解,让我们考虑一个正方形。如果您将50% 视为价值,您可以拥有一个完美的圆圈

.red {
  width: 200px;
  height: 200px;
  background: red;
  clip-path: circle(50%);
  border:2px solid;
  box-sizing:border-box;
}
<div class='red'></div>

背后的思路是考虑下图:

R 是您正在计算的“c”(绿线),r 是使用的参考(紫色线)。你可以很容易地看到r = R/sqrt(2)R = sqrt(w² + h²)。将两者结合起来会得到:

r = sqrt(w² + h²)/sqrt(2)

您在 MDN 页面中看到的公式是什么。

在正方形内使用此值的50% 将为我们提供逻辑圆:

 r/2 = sqrt(w² + h²)/(2*sqrt(2)) = sqrt(2*w²)/(2*sqrt(2)) = w/2 (or h/2)

要覆盖整个正方形,我们需要一个等于R/2 的值,即r/sqrt(2) = r/1.41,因为r100%,您将拥有您发现的71%

.red {
  width: 200px;
  height: 200px;
  background: red;
  clip-path: circle(calc(100% / 1.44)); /* a little bogger  than 1.4 to better see*/
  border:2px solid;
  box-sizing:border-box;
}
<div class='red'></div>

同样的逻辑适用于宽度和高度不同但参考保持不变的非正方形形状:

r = sqrt(w² + h²)/sqrt(2)

从上面我们可以得出结论,71% 是一个神奇的值,无论形状如何,它都会产生相同的输出,因为它依赖于包围元素矩形的圆周半径,而 50%(或任何其他值) ) 会给出不同的结果:

.red {
  width: 200px;
  height: 200px;
  background: red;
  box-shadow:0 0 0 100px yellow;
  display:inline-block;
  clip-path: circle(71%); 
  margin: 70px;
}
<div class='red'></div>
<div class='red' style="width:300px;"></div>
<div class='red' style="width:100px;"></div>
<div class='red' style="width:50px;"></div>

使用50%

.red {
  width: 200px;
  height: 200px;
  background: red;
  clip-path: circle(50%); 
  border:2px solid;
  box-sizing:border-box;
}
<div class='red'></div>
<div class='red' style="width:300px;"></div>
<div class='red' style="width:100px;"></div>
<div class='red' style="width:50px;"></div>

我们也可能认为任何大于71% 的值都是无用的,因为我们总是会给出一个比我们的元素更大的圆。这是真的,但我们不应该忘记我们也有这个职位。

使用100%200%甚至300%的输出示例!

.red {
  width: 200px;
  height: 200px;
  background: red;
  border:2px solid;
  box-sizing:border-box;
}
<div class='red' style="clip-path: circle(100% at  0    50%)"></div>

<div class='red' style="clip-path: circle(200% at -100% 50%)"></div>

<div class='red' style="clip-path: circle(300% at -200% 50%)"></div>

我会考虑一个不同的属性来更好地消除混淆,即radial-gradient

.box {
  width:200px;
  height:200px;
  border:1px solid;
  background:radial-gradient(circle 50%, red ,blue);
}
<div class="box">

</div>

下面的代码是用来定义一个半径等于50%的圆,但它是无效的,因为我们不知道参考:

注意:此处不允许使用百分比;它们只能用于指定椭圆渐变的大小,而不是圆形渐变。 之所以存在此限制,是因为对于百分比应与哪个维度相关,有多种合理的答案。此模块的未来级别可能会提供使用百分比调整圆圈大小的功能,也许可以更明确地控制使用哪个维度。ref

我们正在处理矩形形状,因此我们可以使用您正在计算的高度、宽度、半径等。有很多选项,所以他们只是决定使其无效,但对于clip-path,他们采取了决定并定义了使用百分比的参考。

顺便说一句,考虑到closest-side/farthest-side 之类的值,您可以更好地控制您的圈子。

下面将始终为我们提供接触最近边的圆圈(与带有背景的contain 相同)

.red {
  width: 200px;
  height: 200px;
  background: red;
  clip-path:circle(closest-side); 
  border:2px solid;
  box-sizing:border-box;
}
<div class='red'></div>
<div class='red' style="width:300px;"></div>
<div class='red' style="width:100px;"></div>
<div class='red' style="width:50px;"></div>

下面将始终为我们提供最远边的圆圈(与 cover 的背景相同)

.red {
  width: 200px;
  height: 200px;
  background: red;
  clip-path:circle(farthest-side); 
  border:2px solid;
  box-sizing:border-box;
}
<div class='red'></div>
<div class='red' style="width:300px;"></div>
<div class='red' style="width:100px;"></div>
<div class='red' style="width:50px;"></div>

结合位置,它们可以给出一些有趣的结果:

.red {
  width: 200px;
  height: 200px;
  background: red;
  border:2px solid;
  box-sizing:border-box;
  transition:1s all;
}
<div class='red' style="clip-path:circle(farthest-side at left); "></div>
<div class='red' style="clip-path:circle(closest-side at 10% 10%); "></div>
<div class='red' style="clip-path:circle(farthest-side at top left); "></div>
<div class='red' style="clip-path:circle(closest-side at 40% 50%); "></div>

【讨论】:

  • 感谢您的快速回复,尽管根据他们的文档 参数表示 r,圆的半径。在您的情况下, r 代表一些不相关的周围正方形边,如果盒子碰巧是正方形而不是矩形,它也等于圆直径(不是半径)。这个任意的圆与 DIV 或 IMG 形状有什么关系?
  • @techexpert 你混淆了两件事。 r 是定义剪辑路径圆周的半径,它可以是像素或百分比值。在像素的情况下它是微不足道的,但在百分比值的情况下,规范已将该值的引用定义为sqrt(w² + h²)/sqrt(2)。它可能是其他东西,但它是这样定义的,如果您使用百分比值,这是您的参考。它不一定定义形状。查看我的最新更新
  • 是的,看起来是这样,尽管我确实认为他们将整个百分比部分搞砸了,这永远不会提供一致的有意义的结果。而 80% 或 90% 之类的值似乎与日常使用完全无关,因为它们甚至不剪裁矩形的任何部分。如果百分比意义不大,为什么他们还要为百分比而烦恼,而我们必须手动计算像素才能获得一致的结果?我认为他们应该将此规范更改为真正有意义的东西。感谢您的帮助!
  • @techexpert 添加了更多细节,以更好地理解为何如此复杂 ;) 以及其他可供考虑的替代方案
  • @techexpert 您还忘记了另一个重要部分,即位置,因此 100% 的值在某些情况下可能很有用。再次检查我的上次更新
猜你喜欢
  • 1970-01-01
  • 2014-01-14
  • 2021-05-28
  • 1970-01-01
  • 2010-09-08
  • 2016-12-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多