发布于 2026-01-06 0 阅读
0

使用 CSS 和 JavaScript 创建的交互式齿轮状对象。HTML CSS JavaScript CodePen 结论

这是一个用 CSS 和 JavaScript 制作的交互式齿轮状物体。

HTML

CSS

JavaScript

CodePen

结论

请我喝杯咖啡

齿轮齿轮轮是一种旋转机械零件它有切出的齿,或者,在齿轮轮的情况下,有插入的齿(称为齿),这些齿与另一个带齿的零件啮合以传递扭矩。

在本文中,我将展示如何构建一个交互式齿轮状物体。

为了更好地理解这个概念,我们可以把齿轮想象成一组呈圆形排列的齿。

每颗牙齿都有其自身特征,例如形状和高度。

考虑到以上数据,让我们来构建这样一个对象。

HTML

布局的静态部分很简单。我们只需要定义一个容器,然后设置并填充对象。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Gear</title>
  </head>
  <body>
    <div id="container"></div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

动态部分将包含齿轮:

<div
  class="tooth"
  style="height: 5vmin; width: 14.5vmin; transform: rotateZ(315deg) translateX(15vmin);"
></div>
Enter fullscreen mode Exit fullscreen mode

以及对中心部分的覆盖:

<div class="cover"></div>
Enter fullscreen mode Exit fullscreen mode

部分牙齿参数由 JavaScript 计算,其余设置由 CSS 定义。

CSS

首先,我们将定义基本设置,以便能够在一个地方通过更改数据来调整我们的对象。

:root {
  --smokey: #f5f5f5;
  --darky: #262625;
  --thickness: 0.1vmin;
  --half: 50%;
  --border: var(--thickness) solid var(--smokey);
  --border-radius: var(--half);
}
Enter fullscreen mode Exit fullscreen mode

容器

该容器不仅包含齿轮,而且还起到齿轮主体的外围作用。

#container {
  position: relative;
  display: flex;
  border: var(--border);
  justify-content: center;
  align-items: center;
  border-radius: var(--border-radius);
}
Enter fullscreen mode Exit fullscreen mode

为了使容器呈圆形,我们将边框半径设置为 50%。此外,我们还将应用边框规则。

覆盖

封面帮助我们勾勒出一个齿轮的轮廓。为了更好地理解,让我们逐层查看布局。

第一层是一个带有边框的容器。

替代文字

下一层包含一组牙齿。每颗牙齿的内半部分都放置在容器内,从而形成一个单一的轮廓。

替代文字

最后一层包含覆盖元素,用于隐藏牙齿的内部部分。

替代文字

因此,通过将对象放置在相应的图层中,并设置正确的背景颜色,我们通过隐藏不必要的部分来创建一个单一的轮廓。

替代文字

由于齿轮在任何参数更改后都会重新构建,因此值得一提的是,盖板元件需要设置正确的 z 索引值。

让我们总结一下:

#container .cover {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: var(--darky);
  border-radius: var(--border-radius);
  z-index: 1;
}
Enter fullscreen mode Exit fullscreen mode

齿轮必须安装在轴上。

接下来,我们将添加着陆孔。

为了保持布局简洁,我们在封面元素之前使用一个伪元素:

#container .cover::before {
  width: var(--half);
  height: var(--half);
  border-radius: var(--border-radius);
  content: "";
  border: var(--border);
}
Enter fullscreen mode Exit fullscreen mode

为了使着陆孔居中,我们使用覆盖元素的弹性属性。

齿

我们身体的最后一个组成部分是牙齿。

虽然大部分设置都在 JavaScript 部分完成,但仍然有一些 CSS 规则。

首先,牙齿元素使用了绝对定位。其次,我们利用了 CSS 的 box-sizing 规则来避免破坏布局。

#container .tooth {
  position: absolute;
  box-sizing: border-box;
}
Enter fullscreen mode Exit fullscreen mode

为了好玩,我添加了三种牙齿形状:方形、圆形和三角形。

每种形状都是通过before伪元素构建的。

正方形

这是默认类型,因此没有单独的类名。

这是一个带边框的正方形,具有绝对定位功能:

#container .tooth::before {
  position: absolute;
  width: 100%;
  height: 100%;
  border: var(--border);
  content: "";
  background: var(--darky);
}
Enter fullscreen mode Exit fullscreen mode

圆圈

对于圆形,我们将应用一个边框半径技巧:

#container .tooth.circle::before {
  border-radius: var(--border-radius);
}
Enter fullscreen mode Exit fullscreen mode

三角形

要把正方形变成三角形,我们只需将其旋转 45 度:

#container .tooth.triangle::before {
  transform: rotateZ(45deg);
}
Enter fullscreen mode Exit fullscreen mode

JavaScript

核心变量存储在全局范围内。它们定义了对象的所有参数:容器的 DOM 引用、齿轮半径、齿数、齿高和齿形、轮廓粗细以及齿轮旋转角度。

该 API 由一系列函数组成。其中一些函数非常基础,旨在处理用户输入:setTeethsetHeightsetShapesetAngle。以下是此类函数的一个示例:

/**
 * set modifier for tooth height
 * @param {number} value tooth height modifier
 */
function setHeight(value) {
  height = value;
  update();
}
Enter fullscreen mode Exit fullscreen mode

值得一提的是setThickness函数,因为它会改变 CSS 变量--thickness的值

/**
 * set thickness
 * @param {number} value thickness value
 */
function setThickness(value) {
  document.documentElement.style.setProperty(
    "--thickness",
    `${value / 10}vmin`
  );
}
Enter fullscreen mode Exit fullscreen mode

构建装备的重型功能名称已更新

我们将分步骤进行分析,以便了解发生了什么。

在执行操作之前,我们将计算基本设置。

首先,我们需要知道容器的尺寸。接下来,我们将找出牙齿的基本参数值。

// calculate the container dimensions
const size = `${radius * 3}vmin`;
// calculate the angle between teeth
const step = 360 / teeth;
// calculate the base dimension of the tooth
const side = (2 * Math.PI * radius) / (teeth * (Math.PI / 2));
// calculate the tooth displacement
const displacement = radius * 1.5;
// calculate the height multiplier
const multiplier = (height - 1) / 10;
Enter fullscreen mode Exit fullscreen mode

接下来,我们来设置容器:

// setup container
container.style.width = size;
container.style.height = size;
container.style.margin = `${radius * 2}vmin`;
container.style.transform = `rotate(${angle}deg)`;
container.innerHTML = null;
Enter fullscreen mode Exit fullscreen mode

现在我们来画牙齿:

  • 创建元素。
  • 使用正确的类名。
  • 根据当前形状设置宽度和高度。
  • 旋转牙齿并将其放在牙圈上。
  • 将牙齿放入容器中。
// create tooth
const tooth = document.createElement("div");
tooth.className = `tooth ${shape}`;
// set size for the triangle-shaped tooth
if (shape === "triangle") {
  const length = `${(side / 2) * multiplier}vmin`;
  tooth.style.height = length;
  tooth.style.width = length;
} else {
  // set size for the square and circle-shaped teeth
  tooth.style.height = `${side}vmin`;
  tooth.style.width = `${side * multiplier}vmin`;
}
// place the tooth
tooth.style.transform = `rotateZ(${i *
  step}deg) translateX(${displacement}vmin)`;
// append tooth to the container
container.appendChild(tooth);
Enter fullscreen mode Exit fullscreen mode

在设定牙齿的宽度和高度时,我们依赖于侧面常数。关键在于严格按照牙齿数量的比例绘制,以避免重叠。因此,牙齿越多,每颗牙齿就越小。此外,这种计算也会导致牙齿高度按比例缩小,从而保持牙齿外观的平衡。

最后,添加封面元素:

// restore cover
const cover = document.createElement("div");
cover.className = "cover";
container.appendChild(cover);
Enter fullscreen mode Exit fullscreen mode

让我们总结一下:

/**
 * update the gear
 */
function update() {
  if (container) {
    // calculate the container dimensions
    const size = `${radius * 3}vmin`;
    // calculate the angle between teeth
    const step = 360 / teeth;
    // calculate the base dimension of the tooth
    const side = (2 * Math.PI * radius) / (teeth * (Math.PI / 2));
    // calculate the tooth displacement
    const displacement = radius * 1.5;
    // calculate the height multiplier
    const multiplier = (height - 1) / 10;
    // setup container
    container.style.width = size;
    container.style.height = size;
    container.style.margin = `${radius * 2}vmin`;
    container.style.transform = `rotate(${angle}deg)`;
    container.innerHTML = null;
    // draw teeth
    for (var i = 0; i < teeth; i++) {
      // create tooth
      const tooth = document.createElement("div");
      tooth.className = `tooth ${shape}`;
      // set size for the triangle-shaped tooth
      if (shape === "triangle") {
        const length = `${(side / 2) * multiplier}vmin`;
        tooth.style.height = length;
        tooth.style.width = length;
      } else {
        // set size for the square and circle-shaped teeth
        tooth.style.height = `${side}vmin`;
        tooth.style.width = `${side * multiplier}vmin`;
      }
      // place the tooth
      tooth.style.transform = `rotateZ(${i *
        step}deg) translateX(${displacement}vmin)`;
      // append tooth to the container
      container.appendChild(tooth);
    }
    // restore cover
    const cover = document.createElement("div");
    cover.className = "cover";
    container.appendChild(cover);
  }
}
Enter fullscreen mode Exit fullscreen mode

CodePen

结论

现在你知道如何制作齿轮状物体了。

虽然本文没有介绍控件,但您可以使用 API 动态修改牙齿数量、对象的旋转角度、设置牙齿高度、从三种牙齿形状中进行选择以及设置轮廓粗细。

文章来源:https://dev.to/peacefullatom/the-interactive-gear-shape-object-made-with-css-and-javascript-2n8f