某日,群里有这样一个问题,如何实现这样的表盘刻度:

这其实是个挺有意思的问题,方法也有很多。

单标签,使用 conic-gradient 实现表盘刻度

最简单便捷的方式,就是利用角向渐变的方式 conic-gradient,代码也非常简单,首先,我们实现一个重复角向渐变:

其实比较难理解的是 calc((360 / 60) * 1deg),这是因为表盘一共通常有 60 个刻度。效果大概是这样:

接下来,只需要将中间镂空即可。如果背景色是白色,直接叠加一个圆形即可,当然,更好的方式是通过 mask 属性进行镂空:

这样,我们就得到了一个表盘刻度:

这是使用一个标签就能实现的方式,当然,缺点也很明显:

  1. 锯齿感严重,渐变的通病
  2. 由于是使用的角向渐变,刻度存在头重脚轻的现象,越向内部,宽度越窄(刻度愈大,差异愈加明显)

使用多个标签实现

如果不介意使用太多的标签,那么通常而言,更容易想到的方法就是利用 60 个标签,加上旋转实现:

像是这样,我们通过 60 个 div 标签,利用 SASS 的 for 语法减少重复的代码量,批量实现每个元素逐渐绕一点旋转一定的角度,也是可以实现一个表盘刻度的:

这个方案的好处是,每个刻度粗细一致,并且,不会产生锯齿。

借助 -webkit-box-reflect 减少标签数

当然,上述方案的缺点就在于,使用了 60 个标签去完成这样一个简单的图形,有点太奢侈了。

我们希望尽可能的优化优化标签的个数。此时,我们很容易的想到 — -webkit-box-reflect,倒影效果属性。

-webkit-box-reflect 是一个非常有意思的属性,它让 CSS 有能力像镜子一样,反射我们元素原本绘制的内容。

-webkit-box-reflect 的语法非常简单,最基本的用法像是这样:

其中,below 可以是 below | above | left | right 代表下上左右,也就是有 4 个方向可以选。

假设我们有如下一张图片:

加上 -webkit-box-reflect: right,也就是右侧的倒影:

效果如下,生成了一个元素右侧的镜像元素:

借助 -webkit-box-reflect: right,我们至少可以从 60 个标签减少到 15 个标签的使用。简单的嵌套两层即可。

我们简单改变一下 HTML 结构:

这一次,我们只需要实现 1/4 圆的刻度即可:

我们可以得到这样一个图形:

基于这个图形,我们只需要先向左侧倒影一次,再向下倒影一次即可:

效果如下:

大致的效果就出来了,当然,0点、3点、6点、9点上左下右 4 个刻度有点问题。不过 -webkit-box-reflect 也提供距离调整功能,再简单修改下代码:

这次,效果就是我们想要的最终效果:

我们就成功地借助 -webkit-box-reflect 节约了 3/4 的标签数量。完整的代码:CodePen Demo — Clock ticks

-webkit-box-reflect 与剪纸艺术

到这里,我不由得想到,这种对折、再对折,镜像再镜像的方式,与我们小时候的折纸艺术非常的类似

那么,基于这样一个模板:

我只需要绘制 .g-item 里面的内容,将他通过 2 次 -webkit-box-reflect 镜像,就能得到一个剪纸图形

而如何得到随机有意思的不规则图形呢?

clip-path 是个很不错的选择,我们通过 clip-path 随机对一个矩形进行裁剪:

效果如下:

经过两次镜像后的效果如下:

是不是有那么点意思了?可以随机利用 clip-path 多尝试几次,可以得到不同的效果:

CodePen Demo — Pure CSS Page Cutting

-webkit-box-reflect 配合 clip-path 配合 mask

但是上面的图形看着还是太简单了,几个原因,一是对折的次数和角度不够,缺少对折次数和不同角度的对折,二是图形不够负责。

我又想起了之前看到过的一篇类似的剪纸相关的文章 — Paper Snowflakes: Combining Clipping and Masking in CSS

再上述的基础上,还使用了 mask,将图形切割的更细。

我们再来一次,还是同样的结构,当然,为了得到更负责的图形,我们设置了 4 个 .g-item

首先,还是设置一个 clip-path 切割后的图形:

效果如下:

这个图可能它会特别的奇怪,没有问题,我们继续。

如果,我们将一个矩形,从左下角开始算,分为 4 份,那么每一个份就是 90° / 4 = 22.5°,我们希望切割得到其中一份:

image

我们可以借助 mask 去完成这个切割:

上述的图形,就被切割成了这样:

OK,基于此,我们可以得到同样的第二份图形,但是我们给它加一个 rotateY(180deg)

效果如下:

我们再通过 rotateZ(),给第二图形旋转一定的角度,让他和第一个贴合在一起:

就得到了一个斜向角度的镜像图像:

因为 .g-item 被切割成了 4 份,所以第 3、4 个图形如法炮制即可,这样,整个 .g-item 的效果如下:

再打开 -webkit-box-reflect,整个的图形效果如下:

这样,一个剪纸图形就诞生啦!

当然,为了得到不一样的效果,我们可以借助 JavaScript 去随机生成 CSS 中的各类参数,完整的代码,大概是这样:

这样,每次点击鼠标,我们都能得到不同的随机剪纸图案:

看看这个简单录制的 GIF:

完整的代码,你可以猛击这里 CodePen Demo — Pure CSS Art Page Cutting

最后

本文到此结束,希望对你有帮助

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注