这是一个用 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>
动态部分将包含齿轮:
<div
class="tooth"
style="height: 5vmin; width: 14.5vmin; transform: rotateZ(315deg) translateX(15vmin);"
></div>
以及对中心部分的覆盖:
<div class="cover"></div>
部分牙齿参数由 JavaScript 计算,其余设置由 CSS 定义。
CSS
首先,我们将定义基本设置,以便能够在一个地方通过更改数据来调整我们的对象。
:root {
--smokey: #f5f5f5;
--darky: #262625;
--thickness: 0.1vmin;
--half: 50%;
--border: var(--thickness) solid var(--smokey);
--border-radius: var(--half);
}
容器
该容器不仅包含齿轮,而且还起到齿轮主体的外围作用。
#container {
position: relative;
display: flex;
border: var(--border);
justify-content: center;
align-items: center;
border-radius: var(--border-radius);
}
为了使容器呈圆形,我们将边框半径设置为 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;
}
齿轮必须安装在轴上。
接下来,我们将添加着陆孔。
为了保持布局简洁,我们在封面元素之前使用一个伪元素:
#container .cover::before {
width: var(--half);
height: var(--half);
border-radius: var(--border-radius);
content: "";
border: var(--border);
}
为了使着陆孔居中,我们使用覆盖元素的弹性属性。
齿
我们身体的最后一个组成部分是牙齿。
虽然大部分设置都在 JavaScript 部分完成,但仍然有一些 CSS 规则。
首先,牙齿元素使用了绝对定位。其次,我们利用了 CSS 的 box-sizing 规则来避免破坏布局。
#container .tooth {
position: absolute;
box-sizing: border-box;
}
为了好玩,我添加了三种牙齿形状:方形、圆形和三角形。
每种形状都是通过before伪元素构建的。
正方形
这是默认类型,因此没有单独的类名。
这是一个带边框的正方形,具有绝对定位功能:
#container .tooth::before {
position: absolute;
width: 100%;
height: 100%;
border: var(--border);
content: "";
background: var(--darky);
}
圆圈
对于圆形,我们将应用一个边框半径技巧:
#container .tooth.circle::before {
border-radius: var(--border-radius);
}
三角形
要把正方形变成三角形,我们只需将其旋转 45 度:
#container .tooth.triangle::before {
transform: rotateZ(45deg);
}
JavaScript
核心变量存储在全局范围内。它们定义了对象的所有参数:容器的 DOM 引用、齿轮半径、齿数、齿高和齿形、轮廓粗细以及齿轮旋转角度。
该 API 由一系列函数组成。其中一些函数非常基础,旨在处理用户输入:setTeeth、setHeight、setShape和setAngle。以下是此类函数的一个示例:
/**
* set modifier for tooth height
* @param {number} value tooth height modifier
*/
function setHeight(value) {
height = value;
update();
}
值得一提的是setThickness函数,因为它会改变 CSS 变量--thickness的值:
/**
* set thickness
* @param {number} value thickness value
*/
function setThickness(value) {
document.documentElement.style.setProperty(
"--thickness",
`${value / 10}vmin`
);
}
构建装备的重型功能名称已更新。
我们将分步骤进行分析,以便了解发生了什么。
在执行操作之前,我们将计算基本设置。
首先,我们需要知道容器的尺寸。接下来,我们将找出牙齿的基本参数值。
// 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;
现在我们来画牙齿:
- 创建元素。
- 使用正确的类名。
- 根据当前形状设置宽度和高度。
- 旋转牙齿并将其放在牙圈上。
- 将牙齿放入容器中。
// 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);
让我们总结一下:
/**
* 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);
}
}
CodePen
结论
现在你知道如何制作齿轮状物体了。
虽然本文没有介绍控件,但您可以使用 API 动态修改牙齿数量、对象的旋转角度、设置牙齿高度、从三种牙齿形状中进行选择以及设置轮廓粗细。
文章来源:https://dev.to/peacefullatom/the-interactive-gear-shape-object-made-with-css-and-javascript-2n8f




