• 作者:老汪软件技巧
  • 发表时间:2024-09-08 15:02
  • 浏览量:

包含 16 个元素,这些元素充当层,我将其包裹在标签中。我们将把这五个环放在一个父容器中,以便将所有内容放在一起。我们将为父容器指定一个.rings类,并为每个环指定一个类,这很有创意.ring。html

这是 HTML 的缩写版本,展示了其如何组合在一起:

<div class="rings">
  <div class="ring">
    <i style="--i: 1;">i>
    <i style="--i: 2;">i>
    <i style="--i: 3;">i>
    <i style="--i: 4;">i>
    <i style="--i: 5;">i>
    <i style="--i: 6;">i>
    <i style="--i: 7;">i>
    <i style="--i: 8;">i>
    <i style="--i: 9;">i>
    <i style="--i: 10;">i>
    <i style="--i: 11;">i>
    <i style="--i: 12;">i>
    <i style="--i: 13;">i>
    <i style="--i: 14;">i>
    <i style="--i: 15;">i>
    <i style="--i: 16;">i>
  div>
    
div>

请注意我在每个元素的属性--i上放置的自定义属性:style

我们将使用 来--i计算每个图层的位置、大小和颜色。这就是为什么我将它们的值设置为按升序排列的整数——这些将是用于单独排列和设置每个图层样式的乘数。

css

让我们从父.rings容器开始,现在它只会获得一个相对位置。如果没有相对定位,当设置绝对定位时,环将从文档流中移除,并最终离开页面的某个地方。

.rings { position: relative; } 
.ring { position: absolute; }

让我们对元素进行同样的操作,但使用CSS 嵌套来保持代码紧凑。我们会在border-radius操作过程中修剪方形边缘以形成完美的圆形。

.rings {
  position: relative;
}
.ring {
  position: absolute;
  
  i {
    position: absolute;
    border-radius: 50%;
  }
}

在继续之前,我们将应用的最后一项基本样式是 的自定义属性--ringColor。这将使环的着色变得相当简单,因为我们可以编写一次,然后逐层覆盖它。我们--ringColor在border属性上声明,因为我们只希望在每层的外边缘着色,而不是用 完全填充它们background-color:

.rings {
  position: relative;
}
.ring {
  position: absolute;
  --ringColor: #0085c7;
  
  i {
    position: absolute;
    inset: -100px;
    border: 16px var(--ringColor) solid;
    border-radius: 50%;
  }
}

你有没有注意到我偷偷地把其他东西放进去了?没错,属性inset也在那里,并设置为负值100px。这可能看起来有点奇怪,所以我们先讨论一下这个问题,然后再继续设计我们的作品。

将属性设置为负值inset意味着图层的位置超出了元素的范围.ring。因此,我们可能更愿意将其视为“起始”。在我们的例子中,.ring没有大小,因为没有内容或 CSS 属性来为其赋予尺寸。这意味着图层inset(或者更确切地说是“起始”)100px在每个方向上,从而导致 为.ring200×200 像素。

设置3D深度

我们利用图层来营造深度感。我们通过将 16 个图层沿 z 轴放置来实现这一点,z 轴将元素从前到后堆叠。我们将每个图层之间留出一点2px距离 — 这就是我们在每层之间创建轻微视觉分离所需的所有空间,从而实现我们想要的深度。

还记得--i我们在 HTML 中使用的自定义属性吗?

<i style="--i: 1;">i>
<i style="--i: 2;">i>
<i style="--i: 3;">i>

再次强调,这些是乘数,用于帮助我们translate沿 z 轴计算每一层。让我们创建一个新的自定义属性来定义方程,以便我们可以将其应用于每一层:

i { --translateZ: calc(var(--i) * 2px); }

我们将其应用于什么?我们可以使用 CSStransform属性。这样,我们可以垂直旋转图层(即rotateY()),同时沿 z 轴平移它们:

i {
  --translateZ: calc(var(--i) * 2px);
  transform: rotateY(-45deg) translateZ(var(--translateZ));
}

阴影颜色

对于颜色阴影,我们将根据图层的位置使其变暗,这样当我们从 z 轴的前面移动到后面时,图层会变暗。有几种方法可以做到这一点。一种方法是放入另一个黑色图层,并降低不透明度。另一种方法是修改hsl()颜色函数中的“亮度”通道,其中值在前面“较亮”,向后逐渐变暗。第三个选项是调整图层的不透明度,但这会变得很混乱。

_草莓裹层巧克力的大福_元素充能的作用

尽管我们有这三种方法,但我认为现代 CSS 相对颜色语法是最好的方法。我们已经定义了一个默认的--ringColor自定义属性。我们可以将它放入相对颜色语法中,将其操纵为每个环层的其他颜色。

首先,我们需要一个新的自定义属性来计算“light”值:

.ring {
  --ringColor: #0085c7;
  
  i {
    --light: calc(var(--i) / 16);
    border: 16px var(--ringColor) solid;
  }
}

我们将calc()在另一个自定义属性中使用 -ulated 结果,该属性将我们的默认值--ringColor置于相对颜色语法中,其中--light自定义属性有助于修改结果颜色的亮度。

.ring {
  --ringColor: #0085c7;
  
  i {
    --light: calc(var(--i) / 16);
    --layerColor: rgb(from var(--ringColor) calc(r * var(--light)) calc(g * var(--light)) calc(b * var(--light)));
    border: 16px var(--ringColor) solid;
  }
}

这真是一个相当复杂的方程!但它看起来很复杂,因为相对颜色语法需要颜色(RGB)中每个通道的参数,而我们正在计算每个参数。

    rgb(from origin-color channelR channelG channelB)

至于计算,我们将每个 RGB 通道乘以自定义属性,该属性是介于和--light之间的数字,乘以层数。

创建形状

为了获得圆环形状,我们将使用属性设置图层的大小(即厚度)border。这是我们可以在工作中开始使用三角函数的地方!

我们希望每个环的厚度介于 到 之间 0deg—180deg因为实际上我们只制作了半个圆 — 因此我们将除以180deg层数,16,结果为11.25deg。使用sin()三角函数(相当于直角的对边和斜边),我们得到层的的表达式--size:

--size: calc(sin(var(--i) * 11.25deg) * 16px);

因此,无论--iHTML 中的内容是什么,它都充当计算图层border厚度的乘数。我们一直像这样声明图层的边框:

i {
  border: 16px var(--ringColor) solid;
}

16px现在我们可以用计算来替换硬编码值--size:

i {
  --size: calc(sin(var(--i) * 11.25deg) * 16px);
  border: var(--size) var(--layerColor) solid;
}

但是!您可能已经注意到,当我们改变图层的border宽度时,我们并没有改变图层的大小。因此,圆形轮廓仅出现在图层的内侧。这里的关键是理解使用属性设置,--size这inset意味着它不会影响元素的box-sizing。结果肯定是一个 3D 环,但大部分阴影都被埋没了。.

我们可以通过为每一层计算一个新的来呈现阴影inset。这有点像我在 2020 版本中所做的,但我认为我找到了一种更简单的方法:添加具有outline相同border值的 来完成环外侧的圆弧。现在我们已经建立了一个看起来更自然的环outline:

i {
  --size: calc(sin(var(--i) * 11.25deg) * 16px);
  border: var(--size) var(--layerColor) solid;
  outline: var(--size) var(--layerColor) solid;
}

动画戒指

在最后一个演示中,我必须为戒指添加动画,以比较戒指前后的阴影。我们将在最后一个演示中使用相同的动画,因此在将其他四个戒指添加到 HTML 之前,让我们分解一下我是如何做到这一点的

我并没有想做什么花哨的事情;我只是将 y 轴的旋转设置为从-45deg到45deg(translateZ值保持不变)。

@keyframes ring {
  from { transform: rotateY(-45deg) translateZ(var(--translateZ, 0)); }
  to { transform: rotateY(45deg) translateZ(var(--translateZ, 0)); }
}

至于animation属性,我将其命名为ring,并硬编码(至少目前)一个无限循环的持续时间。分别使用和3s来设置动画的计时函数,可实现平滑的来回运动。ease-in-out``alternate

i {
  animation: ring 3s infinite ease-in-out alternate;
}