【CSS】使用新版 CSS sin() 和 cos() 三角函数创建简约时钟和图片库

简介: SS三角函数来了!好吧,如果您使用的是最新版本的 Firefox 和 Safari,那就是这样。CSS 中拥有这种数学能力开启了一大堆可能性。在本教程中,我们应该好好来感受一下几个新函数:sin()和cos()。

CSS三角函数来了!好吧,如果您使用的是最新版本的 Firefox 和 Safari,那就是这样。CSS 中拥有这种数学能力开启了一大堆可能性。在本教程中,我们应该好好来感受一下几个新函数:sin()cos()

目前还有其他三角函数,比如tan(),为什么只关注sin()cos()? 那是因为它非常适合我想要实现的想法,就是沿着圆的边缘放置文本。在CSS-Tricks上,Chris分享了一种使用Sass mixin的方法来实现这一点。那是六年前的事情了,所以让我们来尝试一下最新的技术。

以下是简单的效果。再次强调,目前只在Firefox和Safari浏览器中支持:
点我查看例子

如何实现

所以,它并不完全像单词形成一个圆形,而是我们将字符沿着圆形排列,形成一个时钟的面板。下面我们就来使用html逐步分分析时钟结构:

<div class="clock">
  <div class="clock-face">
    <time datetime="12:00">12</time>
    <time datetime="1:00">1</time>
    <time datetime="2:00">2</time>
    <time datetime="3:00">3</time>
    <time datetime="4:00">4</time>
    <time datetime="5:00">5</time>
    <time datetime="6:00">6</time>
    <time datetime="7:00">7</time>
    <time datetime="8:00">8</time>
    <time datetime="9:00">9</time>
    <time datetime="10:00">10</time>
    <time datetime="11:00">11</time>
  </div>
</div>

这段CSS样式主要是用于给.clock-face设置一个容器的基本属性和样式,记住嗷,要考的:

  • --_ow: clamp(5rem, 60vw, 40rem);:这是一个CSS变量,用于设置容器的宽度。它使用了clamp函数,其中第一个参数表示最小宽度(5rem),第二个参数表示视窗宽度的百分比(60vw),第三个参数表示最大宽度(40rem)。

  • --_w: 88cqi;:这是另一个CSS变量,用于设置容器的宽度。

  • aspect-ratio: 1;:设置容器的宽高比为1,即正圆形。

  • background-color: tomato;:设置容器的背景颜色为番茄红。

  • border-radius: 50%;:设置容器的圆角半径为50%,使其呈现圆形。

  • container-type: inline;:设置容器的类型为内联元素,即与其他元素在一行上显示。

  • display: grid;:将容器的显示模式设置为网格布局。

  • height: var(--_ow);:设置容器的高度为之前定义的变量--_ow的值。

  • place-content: center;:将容器内容在网格布局中居中对齐。

  • position: relative;:设置容器的定位方式为相对定位。

  • width: var(--_ow);:设置容器的宽度为之前定义的变量--_ow的值。

这些样式通过定义CSS变量和一些基本属性来创建一个圆形的容器,并使其在网格布局中居中显示。

.clock {
   
   
  --_ow: clamp(5rem, 60vw, 40rem);
  --_w: 88cqi;
  aspect-ratio: 1;
  background-color: tomato;
  border-radius: 50%;
  container-type: inline;
  display: grid;
  height: var(--_ow);
  place-content: center;
  position: relative;
  width var(--_ow);
}

这一步呢,我们把轮廓画出来,给它稍微装饰下,以至于让我们知道大概思路。并且我们存入了css变量。

Large tomato colored circle with a vertical list of numbers 1-12 on the left.

看起来像不像一个艺术品...好了,现在引入一个新的变量 --_r,用于存储圆的半径,该半径等于圆的宽度的一半。这样,如果宽度 --_w 发生变化,半径值 --_r 也会更新,这要归功于另一个 CSS 数学函数 calc()

.clock {
   
   
  --_w: 300px;
  --_r: calc(var(--_w) / 2);
  /* 其他样式 */
}

现在需要用到一些数学知识。一个圆有 360 度。时钟上有 12 个标签,所以我们希望每 30 度(360 / 12)放置一个数字。在数学上,圆开始于 3 点钟位置,所以正午实际上是从那个位置减去 90 度,即 270 度(360 - 90)。

让我们再添加一个变量 --_d,可以用来为时钟面上的每个数字设置一个角度值。我们将递增这些值以完成整个圆:

.clock time:nth-child(1) {
   
    --_d: 270deg; }
.clock time:nth-child(2) {
   
    --_d: 300deg; }
.clock time:nth-child(3) {
   
    --_d: 330deg; }
.clock time:nth-child(4) {
   
    --_d: 0deg; }
.clock time:nth-child(5) {
   
    --_d: 30deg; }
.clock time:nth-child(6) {
   
    --_d: 60deg; }
.clock time:nth-child(7) {
   
    --_d: 90deg; }
.clock time:nth-child(8) {
   
    --_d: 120deg; }
.clock time:nth-child(9) {
   
    --_d: 150deg; }
.clock time:nth-child(10) {
   
    --_d: 180deg; }
.clock time:nth-child(11) {
   
    --_d: 210deg; }
.clock time:nth-child(12) {
   
    --_d: 240deg; }

通过以上代码,我们为时钟的每个数字设置了相应的角度值。这些角度值按照每次递增 30 度来完成整个圆的布局。

好的,现在是时候动手使用 sin()cos() 函数了!我们想要使用它们来获取每个数字的 X 和 Y 坐标,以便将它们正确地放置在时钟面上。

X 坐标的公式是 radius + (radius * cos(degree))。让我们将其插入到我们的新变量 --_x 中:

--_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));

Y 坐标的公式是radius + (radius * sin(degree))。我们已经掌握了计算它所需的内容:

--_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));

还有一些基础设置,让我们对数字进行一些基本样式设置,以确保它们绝对定位并根据我们的坐标放置:

.clock-face time {
   
   
  --_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));
  --_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));
  --_sz: 12cqi;
  display: grid;
  height: var(--_sz);
  left: var(--_x);
  place-content: center;
  position: absolute;
  top: var(--_y);
  width: var(--_sz);
}

注意到 --_sz 这个变量,我们将在稍后用它来设置数字的宽度和高度。让我们看看目前为止我们得到了什么结果。

image.png

不错...这看起来更像是一个时钟了,大家要注意每个数字的左上角都正确地位于圆周上的相应位置。在计算每个数字的位置时,我们需要“缩小”半径。在计算半径之前,我们可以从圆的大小(--_w)中减去数字的大小(--_sz):

--_r: calc((var(--_w) - var(--_sz)) / 2);

这样,我们可以将数字的大小考虑在内,确保它们在正确的位置上放置。继续下一步操作~


A white clock face with numbers against a dark gray background. The clock has no arms.

想要达到这种效果,我们需要给它优化下外观就可以了。

我们已经实现了在圆圈周围放置文本的目标,对吧?但是没有指针来显示小时、分钟和秒钟的时钟算什么呢?

使用一个CSS动画来完成。首先,在我们的标记中添加三个额外的元素:

<div class="clock">
  <!-- 在 <time> 标签之后 -->
  <span class="arm seconds"></span>
  <span class="arm minutes"></span>
  <span class="arm hours"></span>
  <span class="arm center"></span>
</div>

然后为所有三个指针添加一些常见的标记。同样,大部分内容只是确保指针被绝对定位并相应地放置:

.arm {
   
   
  background-color: var(--_abg);
  border-radius: calc(var(--_aw) * 2);
  display: block;
  height: var(--_ah);
  left: calc((var(--_w) - var(--_aw)) / 2);
  position: absolute;
  top: calc((var(--_w) / 2) - var(--_ah));
  transform: rotate(0deg);
  transform-origin: bottom;
  width: var(--_aw);
}

我们将为所有三个指针使用相同的动画:

@keyframes turn {
   
   
  to {
   
   
    transform: rotate(1turn);
  }
}

唯一的区别在于各个指针完成一次完整旋转所需的时间。对于小时指针,需要12小时完成一次完整旋转。animation-duration 属性只接受毫秒和秒的值。让我们选择秒,也就是43,200秒(60秒 60分钟 12小时)。

animation: turn 43200s infinite;

分钟指针需要1小时完成一次完整旋转。但是我们希望这是一个多步动画,所以指针之间的移动是交错的,而不是线性的。我们需要60个步骤,对应每一分钟:

animation: turn 3600s steps(60, end) infinite;

秒钟指针与分钟指针几乎相同,只是持续时间为60秒而不是60分钟:

animation: turn 60s steps(60, end) infinite;

然后更新一下我们在公共样式中创建的属性:

.seconds {
   
   
  --_abg: hsl(0, 5%, 40%);
  --_ah: 145px;
  --_aw: 2px;
  animation: turn 60s steps(60, end) infinite;
}

.minutes {
   
   
  --_abg: #333;
  --_ah: 145px;
  --_aw: 6px;
  animation: turn 3600s steps(60, end) infinite;
}

.hours {
   
   
  --_abg: #333;
  --_ah: 110px;
  --_aw: 6px;
  animation: turn 43200s linear infinite;
}

如果我们想要从当前时间开始呢?可以用过JS来实现:

const time = new Date();
const hour = -3600 * (time.getHours() % 12);
const mins = -60 * time.getMinutes();
app.style.setProperty('--_dm', `${
     
     mins}s`);
app.style.setProperty('--_dh', `${
     
     (hour+mins)}s`);

我在时钟面上添加了 id="app",并在其上设置了两个新的自定义属性,用于设置负数的动画延迟,就像 Mate Marschalko 在共享纯CSS时钟时所做的那样。JavaScript 的 Date 对象的 getHours() 方法使用的是24小时制,因此我们使用余数运算符将其转换为12小时制。

在CSS中,我们还需要添加 animation-delay

.minutes {
   
   
  animation-delay: var(--_dm, 0s);
  /* 其他样式 */
}

.hours {
   
   
  animation-delay: var(--_dh, 0s);
  /* 其他样式 */
}

只剩下最后一件事。使用 CSS 的 @supports 和我们已经创建的属性,我们可以为不支持 sin() 和 cos() 的浏览器提供回退方案。(感谢 Temani Afif!)

@supports not (left: calc(1px * cos(45deg))) {
   
   
  time {
   
   
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%,-50%) rotate(var(--_d)) translate(var(--_r)) rotate(calc(-1*var(--_d)))
  }
}

图片库

好了,你不会以为我们时钟只能拿来当钟用吧???当然不是!!!

可以通过替换标签 <time> 然后 <img>更新宽度 ( --_w) 和半径 ( --_r) 值来快速将时钟变成圆形图像库。

jcode

OK!!结束了,注意,注意!注意!它只在 Firefox 和 Safari 中支持。

OK!!结束了,注意,注意!注意!它只在 Firefox 和 Safari 中支持。

OK!!结束了,注意,注意!注意!它只在 Firefox 和 Safari 中支持。

本文同步我的技术文档

相关文章
|
28天前
|
前端开发
在Webpack配置文件中,如何配置loader以处理其他类型的文件,如CSS或图片
在Webpack配置文件中,通过设置`module.rules`来配置loader处理不同类型的文件。例如,使用`css-loader`和`style-loader`处理CSS文件,使用`file-loader`或`url-loader`处理图片等资源文件。配置示例:在`rules`数组中添加对应规则,指定`test`匹配文件类型,`use`指定使用的loader。
|
4天前
|
JavaScript 容器
jquery和CSS3图片排序过滤搜索插件
Filterizr是一款jquery和CSS3图片排序过滤插件。它可以对一组图片进行排序,按条件过滤和按关键字搜索。并在显示结果时使用指定的CSS3动画过渡效果。
16 2
|
10天前
|
JavaScript
jQuery和CSS3精美翻页式电子时钟特效
jQuery和CSS3精美翻页式电子时钟特效
|
25天前
|
编解码 前端开发 UED
探讨了CSS媒体查询在移动端开发中的应用,介绍了媒体查询的基本概念、常见条件及其在响应式布局、导航菜单、图片优化和字体调整等方面的具体应用
本文深入探讨了CSS媒体查询在移动端开发中的应用,介绍了媒体查询的基本概念、常见条件及其在响应式布局、导航菜单、图片优化和字体调整等方面的具体应用。通过实际案例分析和注意事项的讨论,旨在帮助开发者更好地理解和运用媒体查询,提升移动端用户体验。
42 4
|
27天前
CSS3实现的九宫格图片鼠标悬停去除遮罩层源码
CSS3实现的九宫格图片鼠标悬停去除遮罩层源码
17 0
CSS3实现的九宫格图片鼠标悬停去除遮罩层源码
|
2月前
|
前端开发 UED
Webpack 中处理 CSS 和图片资源的多 Loader 配置
【10月更文挑战第12天】 处理 CSS 和图片资源是 Webpack 配置中的重要部分。通过合理选择和配置多个 Loader,可以实现对这些资源的精细处理和优化,提升项目的性能和用户体验。在实际应用中,需要不断探索和实践,根据项目的具体情况进行灵活调整和优化,以达到最佳的处理效果。通过对 Webpack 中多 Loader 处理 CSS 和图片资源的深入了解和掌握,你将能够更好地应对各种复杂的资源处理需求,为项目的成功构建和运行提供坚实的基础。
85 1
|
4月前
|
前端开发
如何使用 CSS object-fit 进行图片的缩放和裁剪
如何使用 CSS object-fit 进行图片的缩放和裁剪
111 0
如何使用 CSS object-fit 进行图片的缩放和裁剪
|
4月前
|
前端开发
视觉冲击:CSS实现相册图片的放大效果,让网站首页更震撼!
视觉冲击:CSS实现相册图片的放大效果,让网站首页更震撼!
|
5月前
|
前端开发 容器
CSS【详解】对齐 (含文本垂直对齐,文本水平对齐、单行文本垂直居中、多行文本垂直居中、6 种方案块级元素水平垂直居中 、7 种方案图片水平垂直居中、文本自适应对齐、图标和文本对齐,图片和文本对齐等)
CSS【详解】对齐 (含文本垂直对齐,文本水平对齐、单行文本垂直居中、多行文本垂直居中、6 种方案块级元素水平垂直居中 、7 种方案图片水平垂直居中、文本自适应对齐、图标和文本对齐,图片和文本对齐等)
136 0
|
5月前
|
前端开发 C++
css 鼠标悬浮显示放大图片 vs 鼠标点击显示放大图片
css 鼠标悬浮显示放大图片 vs 鼠标点击显示放大图片
64 0