头图 CSS 绘制一个时钟

简介: 头图CSS 绘制一个时钟
欢迎关注微信公众号: 前端侦探


练习 CSS 一个很好的方法就是绘制各式各样的 UI,比如这样一个时钟?


image.png

你也可以访问这个 CSS clock点击预览查看实际效果


CSS 绘制这样一个布局有几个难点:


  1. 环形排列的刻度
  2. 环形分布的数字
  3. 自动运行的指针


下面就来一一实现它,相信能学到很多 CSS 绘制和动画的小技巧

一、环形排列的刻度


提到“环形”,可以想到锥形渐变 conic-gradient。假设有这样一个容器

<clock></clock>


加上一点锥形渐变

clock{
  width: 300px;
  height: 300px;
  background: conic-gradient(#333 0 15deg, #cddc39 0deg 30deg);
}


可以得到这样的效果


image.png

如何做出交错相间的效果呢?可以试试 repeating-conic-gradient

clock{
  /**/
  background: repeating-conic-gradient(#333 0 15deg, #cddc39 0deg 30deg);
}


效果如下


image.png

还是看不出和刻度有啥关系?没关系,我们把黑色部分的角度改小一点

clock{
  /**/
  background: repeating-conic-gradient(#333 0 1deg, #cddc39 0deg 30deg);
}


效果如下


image.png

这样绘制出来的几条线是不是刚好可以对应时钟的刻度?


然后将整个形状变成圆环,可以用 MASK 来实现,实现如下

clock{
  /**/
  border-radius: 50%;
  -webkit-mask: radial-gradient(transparent 145px, red 0);
}


效果如下


image.png

其实,这里还有一个小细节,黑色部分并不是居中的,需要修正一下(可以更改起始角度,指定 from)。然后,将这个草绿色换成透明就可以了,完整代码如下

clock{
  /**/
  background: repeating-conic-gradient(from -.5deg, #333 0 1deg, transparent 0deg 30deg);
  border-radius: 50%;
  -webkit-mask: radial-gradient(transparent 145px, red 0);
}


最终效果


image.png

分钟的刻度也是同样的道理,因为共有 60 个刻度,所以最小角度是 6 度(360 / 60),实现如下

clock{
  /**/
  background: repeating-conic-gradient(#333 0 1deg, #cddc39 0deg 6deg);
}


image.png

利用 CSS 背景可以无限叠加的特性,可以将这两个背景绘制在同一个元素下,所以完整代码如下

clock{
  /**/
  background: repeating-conic-gradient(from -.5deg, #333 0 1deg, transparent 0deg 30deg), 
    repeating-conic-gradient(from -.5deg, #ccc 0 1deg, transparent 0deg 6deg);
  border-radius: 50%;
  -webkit-mask: radial-gradient(transparent 145px, red 0);
}


最终表盘刻度效果如下


image.png

二、环形分布的数字


看到这种布局,我的第一反应其实是 textPath,这个 SVG 元素可以让文本沿着指定路径进行排列,比如下面这个 MDN 上的例子

<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
  <path id="MyPath" fill="none" stroke="red"
        d="M10,90 Q90,90 90,45 Q90,10 50,10 Q10,10 10,40 Q10,70 45,70 Q70,70 75,50" />
  <text>
    <textPath href="#MyPath">
      Quick brown fox jumps over the lazy dog.
    </textPath>
  </text>
</svg>


效果如下


image.png

但是,这种方式有一个缺陷,无法改变文字的角度,只能沿着路径垂直方向,而时钟的数字方向都是正常的。


经过一番琢磨,发现还有一种方式也有类似沿着路径的布局方式,那就是 offset-path! 下面是 MDN 上的一个演示效果


image.png

那么和环形排列数字有什么关系呢?假设有这样一个布局

<clock-pane>
    <num>1</num>
</clock-pane>


然后将这个数字指定到一个圆形的路径上(目前仅支持 path

num{
  offset-path: path('M250 125c0 69.036-55.964 125-125 125S0 194.036 0 125 55.964 0 125 0s125 55.964 125 125z');
}


效果如下(起始点是跟随 path 路径的)


image.png

然后,可以通过 offset-distance来改变元素在路径上的位置,并且支持百分比

num{
  offset-path: path('M250 125c0 69.036-55.964 125-125 125S0 194.036 0 125 55.964 0 125 0s125 55.964 125 125z');
  offset-distance: 100%
}


下面是从 0 到 100% 的变化


image.png

默认情况下元素的角度也是自适应垂直于路径的,和 textPath 比较类似。但是我们可以手动指定固定角度,需要 offset-rotate,指定为 0deg 就行了

num{
  offset-path: path('M250 125c0 69.036-55.964 125-125 125S0 194.036 0 125 55.964 0 125 0s125 55.964 125 125z');
  offset-rotate: 0deg;
  offset-distance: 100%
}


效果如下,角度已经完全归正了


image.png

如果有类似的布局需求,是不是可以参考这个案例呢?


接下来,我们通过 CSS 变量,把 12 个数字自动归位到指定位置

<clock-pane>
  <num style="--i:1">1</num>
  <num style="--i:2">2</num>
  <num style="--i:3">3</num>
  <num style="--i:4">4</num>
  <num style="--i:5">5</num>
  <num style="--i:6">6</num>
  <num style="--i:7">7</num>
  <num style="--i:8">8</num>
  <num style="--i:9">9</num>
  <num style="--i:10">10</num>
  <num style="--i:11">11</num>
  <num style="--i:12">12</num>
</clock-pane>


配合 calc 计算,完整代码如下

num{
  position: absolute;
  offset-path: path('M250 125c0 69.036-55.964 125-125 125S0 194.036 0 125 55.964 0 125 0s125 55.964 125 125z');
  offset-distance: calc( var(--i) * 10% / 1.2 - 25%);
  offset-rotate: 0deg;
}


效果如下


image.png

三、自动运行的指针


三个指针的绘制应该没有太大的难度,假设结构如下

<hour></hour>
<min></min>
<sec></sec>


需要注意一下旋转的中心

hour{
  position: absolute;
  width: 4px;
  height: 60px;
  background: #333;
  transform-origin: center bottom;
  transform: translateY(-50%) rotate(30deg);
}
min{
  position: absolute;
  width: 4px;
  height: 90px;
  background: #333;
  transform-origin: center bottom;
  transform: translateY(-50%) rotate(60deg);
}
sec{
  position: absolute;
  width: 2px;
  height: 120px;
  background: red;
  transform-origin: center bottom;
  transform: translateY(-50%) rotate(90deg);
}
sec::after{
  content: '';
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  left: 50%;
  bottom: 0;
  background: #fff;
  border: 4px solid #333;
  transform: translate(-50%, 50%);
}


效果如下


image.png

到这一步静态布局就算完成了,那么如何运行呢?


之前在这篇文章 还在使用定时器吗?CSS 也能实现电子时钟 有详细讲解到,不借助定时器,也完全可以用 CSS 动画来实现!


回到这里,运行的原理很简单,就是一个无限循环的 CSS 动画,如下

@keyframes clock {
  to {
    transform: translateY(-50%) rotate(360deg);
  }
}


不同的是,时针、分针、秒针的周期不一样,时针转一圈是 12 小时、分针是 60 分钟、秒针是 60 秒,各自需要换算成 秒数(CSS 单位只支持 毫秒),为了方便测试,这里将速度调快了 60s → 6s


代码实现就是(--step 是一分钟)

hour{
  /**/
  transform: translateY(-50%) rotate(0);
  animation: clock calc(var(--step) * 60 * 12) infinite;
}
min{
  /**/
  transform: translateY(-50%) rotate(0);
  animation: clock calc(var(--step) * 60) infinite;
}
sec{
  /**/
  transform: translateY(-50%) rotate(0);
  animation: clock var(--step) infinite;
}


效果如下


image.png

是不是有些奇怪?秒针在旋转时先慢慢变快,然后又慢慢变慢,这是由于默认的动画函数是ease,所以需要改成linear

sec{
  /**/
  animation: clock var(--step) infinite linear;
}


image.png

这样就好多了。不过平时所见的时钟,秒针通常都那种走一下,停下的,还有一种“滴答滴答”的节奏感,并不是这种无缝的。在 CSS 动画中,是不是有点像阶梯状,没错,可以用到 CSS 的 steps 函数,不了解这个的可以参考张老师的这篇文章:CSS3 animation属性中的steps功能符深入介绍,实现如下

sec{
  /**/
  animation: clock var(--step) infinite steps(60);
}


效果如下

image.png

接下来需要通过 JS 初始化时间,仅此而已。需要注意的是,在获取的时候加上偏移量,比如 12:30,分针其实是 12.5,以此类推。代码实现如下

const d = new Date()
const h = d.getHours();
const m = d.getMinutes();
const s = d.getSeconds();
clock.style.setProperty('--ds', s)
clock.style.setProperty('--dm', m + s/60)
clock.style.setProperty('--dh', h + m/60 + s/3600)


然后 CSS 中可以通过 animation-delay来指定动画的起始位置

hour{
  /**/
  animation: clock calc(var(--step) * 60 * 12) infinite linear;
  animation-delay: calc( -1 * var(--step) * var(--dh) * 60);
}
min{
  /**/
  animation: clock calc(var(--step) * 60) infinite linear;
  animation-delay: calc( -1 * var(--step) * var(--dm));
}
sec{
  /**/
  animation: clock var(--step) infinite steps(60);
  animation-delay: calc( -1 * var(--step) * var(--ds) / 60 );
}


然后加点轮廓装饰,就实现了文章开头的效果


image.png

完整代码可以查看 CSS clock点击预览


四、简单总结一下


以上就是CSS 绘制时钟的全部过程了,本文更侧重于绘制过程,特别是是环形布局技巧,这里简单总结一下


  1. 碰到环形图案可以想到 conic-gradient
  2. 环形刻度绘制的原理是 conic-gradient 和 MASK 裁剪
  3. 文字沿路径排列可以使用 textPath
  4. textPath 不支持改变文字角度
  5. offset-path 可以让元素沿指定路径进行布局
  6. offset-path 可以设置元素在路径的偏移和角度
  7. 时钟自动运行的原理的是 CSS 动画
  8. 时钟、分钟、秒钟的区别是动画时长不同
  9. “滴答滴答”的效果可以用 steps 实现
  10. 时间初始化可以通过 animation delay 实现


当然本文重点并不仅仅是在于实现了一个时钟,而是在于 CSS 绘制技巧的积累和掌握。有了相关的积累,以后在碰到类似的布局,在脑子里过滤一下,马上就能找到解决方案。最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤


欢迎关注微信公众号: 前端侦探
相关文章
html+js+css实现的建筑方块立体数字时钟源码
html+js+css实现的建筑方块立体数字时钟源码
759 33
css3实现3D数字时钟滚动特效代码
css3实现3D数字时钟滚动特效代码
598 18
一个好看的小时钟html+js+css源码
一个好看的小时钟html+js+css源码
361 24
|
JavaScript
jQuery和CSS3精美翻页式电子时钟特效
jQuery和CSS3精美翻页式电子时钟特效
|
前端开发 JavaScript
CSS动画篇之炫酷时钟之时钟墙
CSS动画篇之炫酷时钟之时钟墙
256 1
|
前端开发 算法 JavaScript
html+css+js实现时钟
html+css+js实现时钟
319 0
|
Web App开发 存储 前端开发
【CSS】使用新版 CSS sin() 和 cos() 三角函数创建简约时钟和图片库
SS三角函数来了!好吧,如果您使用的是最新版本的 Firefox 和 Safari,那就是这样。CSS 中拥有这种数学能力开启了一大堆可能性。在本教程中,我们应该好好来感受一下几个新函数:sin()和cos()。
【CSS】使用新版 CSS sin() 和 cos() 三角函数创建简约时钟和图片库
|
前端开发 容器
「CSS畅想」七夕寄情,我绘制了一副双色莲花图
用技术实现梦想,用梦想打开创意之门。七夕寄情,我用CSS绘制了一副双色莲花图。
437 1
「CSS畅想」七夕寄情,我绘制了一副双色莲花图
|
前端开发 JavaScript 容器
【CSS畅想】萤星漫舞,我用CSS绘制了一个属于夏日的回忆
用技术实现梦想,用梦想打开创意之门。萤星漫舞,我用CSS绘制了一个属于夏日的回忆
447 1
|
存储 前端开发 JavaScript
🏆使用 HTML、CSS 和 JavaScript 的酷黑主题模拟时钟
🏆使用 HTML、CSS 和 JavaScript 的酷黑主题模拟时钟
401 0

热门文章

最新文章

  • 1
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    646
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    502
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    504
  • 4
    (CSS)使用Flex布局,帮助你快速了解各种基本的Flex布局属性以及帮你让元素快速达到布局中的指定位置!
    324
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    611
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    793
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1568
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    366
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1283
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    618