离谱的 CSS!从表盘刻度到剪纸艺术
某日,群里有这样一个问题,如何实现这样的表盘刻度:
这其实是个挺有意思的问题,方法也有很多。
单标签,使用 conic-gradient 实现表盘刻度
最简单便捷的方式,就是利用角向渐变的方式 conic-gradient
,代码也非常简单,首先,我们实现一个重复角向渐变:
<div></div>
div {width: 300px;height: 300px;border-radius: 50%;background: repeating-conic-gradient(#000 0, #000 .8deg, transparent 1deg, transparent calc((360 / 60) * 1deg));
}
其实比较难理解的是 calc((360 / 60) * 1deg)
,这是因为表盘一共通常有 60 个刻度。效果大概是这样:
接下来,只需要将中间镂空即可。如果背景色是白色,直接叠加一个圆形即可,当然,更好的方式是通过 mask 属性进行镂空:
{background: repeating-conic-gradient(#000 0, #000 .8deg, transparent 1deg, transparent calc(360 / 60 * 1deg));mask: radial-gradient(transparent 0, transparent 140px, #000 140px)
}
这样,我们就得到了一个表盘刻度:
这是使用一个标签就能实现的方式,当然,缺点也很明显:
锯齿感严重,渐变的通病
由于是使用的角向渐变,刻度存在头重脚轻的现象,越向内部,宽度越窄(刻度愈大,差异愈加明显)
使用多个标签实现
如果不介意使用太多的标签,那么通常而言,更容易想到的方法就是利用 60 个标签,加上旋转实现:
<div class="g-container"><div class="g-item"></div>// ... 一共 60 个<div class="g-item"></div></div>
.g-item {position: absolute;width: 4px;height: 12px;background: #000;left: 0;top: 0;transform-origin: 0 150px;
}
@for $i from 1 through 60 { .g-item:nth-child(#{$i}) {transform: rotate(#{($i - 1) * 6deg});}
}
像是这样,我们通过 60 个 div 标签,利用 SASS 的 for 语法减少重复的代码量,批量实现每个元素逐渐绕一点旋转一定的角度,也是可以实现一个表盘刻度的:
这个方案的好处是,每个刻度粗细一致,并且,不会产生锯齿。
借助 -webkit-box-reflect 减少标签数
当然,上述方案的缺点就在于,使用了 60 个标签去完成这样一个简单的图形,有点太奢侈了。
我们希望尽可能的优化优化标签的个数。此时,我们很容易的想到 -- -webkit-box-reflect
,倒影效果属性。
-webkit-box-reflect[1] 是一个非常有意思的属性,它让 CSS 有能力像镜子一样,反射我们元素原本绘制的内容。
-webkit-box-reflect
的语法非常简单,最基本的用法像是这样:
div {-webkit-box-reflect: below;
}
其中,below 可以是 below | above | left | right 代表下上左右,也就是有 4 个方向可以选。
假设我们有如下一张图片:
<div></div>
div {background-image: url('https://images.pokemontcg.io/xy2/12_hires.png');
}
加上 -webkit-box-reflect: right
,也就是右侧的倒影:
div {background-image: url('https://images.pokemontcg.io/xy2/12_hires.png');-webkit-box-reflect: right;
}
效果如下,生成了一个元素右侧的镜像元素:
借助 -webkit-box-reflect: right
,我们至少可以从 60 个标签减少到 15 个标签的使用。简单的嵌套两层即可。
我们简单改变一下 HTML 结构:
<div class="g-parent"><div class="g-container"><div class="g-item"></div>// ... 一共 16 个<div class="g-item"></div></div>
</div>
这一次,我们只需要实现 1/4 圆的刻度即可:
@for $i from 1 through 16 { .g-item:nth-child(#{$i}) {transform: rotate(#{($i - 1) * 6deg});}
}
我们可以得到这样一个图形:
基于这个图形,我们只需要先向左侧倒影一次,再向下倒影一次即可:
.g-container {-webkit-box-reflect: below;
}
.g-parent {-webkit-box-reflect: left;
}
效果如下:
大致的效果就出来了,当然,0点、3点、6点、9点上左下右 4 个刻度有点问题。不过 -webkit-box-reflect
也提供距离调整功能,再简单修改下代码:
.g-container {-webkit-box-reflect: below 4px;
}
.g-parent {-webkit-box-reflect: left -4px;
}
这次,效果就是我们想要的最终效果:
我们就成功地借助 -webkit-box-reflect
节约了 3/4 的标签数量。完整的代码:CodePen Demo -- Clock ticks[2]
-webkit-box-reflect 与剪纸艺术
到这里,我不由得想到,这种对折、再对折,镜像再镜像的方式,与我们小时候的折纸艺术非常的类似。
那么,基于这样一个模板:
<div class="g-parent"><div class="g-container"><div class="g-item"></div></div>
</div>
.g-container {-webkit-box-reflect: below;
}
.g-parent {-webkit-box-reflect: left;
}
我只需要绘制 .g-item
里面的内容,将他通过 2 次 -webkit-box-reflect
镜像,就能得到一个剪纸图形。
而如何得到随机有意思的不规则图形呢?
clip-path
是个很不错的选择,我们通过 clip-path
随机对一个矩形进行裁剪:
.g-item {width: 150px;height: 150px;background: #000;clip-path: polygon(25% 0%,71% 66%,59% 0%,79% 23%,95% 4%,100% 40%,77% 100%,38% 100%,47% 71%,36% 30%,23% 60%,0% 100%,5% 37%);
}
效果如下:
经过两次镜像后的效果如下:
是不是有那么点意思了?可以随机利用 clip-path
多尝试几次,可以得到不同的效果:
CodePen Demo -- Pure CSS Page Cutting[3]
-webkit-box-reflect 配合 clip-path 配合 mask
但是上面的图形看着还是太简单了,几个原因,一是对折的次数和角度不够,缺少对折次数和不同角度的对折,二是图形不够负责。
我又想起了之前看到过的一篇类似的剪纸相关的文章 -- Paper Snowflakes: Combining Clipping and Masking in CSS[4]。
再上述的基础上,还使用了 mask,将图形切割的更细。
我们再来一次,还是同样的结构,当然,为了得到更负责的图形,我们设置了 4 个 .g-item
:
<div class="g-parent"><div class="g-container"><div class="g-item"></div><div class="g-item"></div><div class="g-item"></div><div class="g-item"></div></div>
</div>
首先,还是设置一个 clip-path
切割后的图形:
.g-item:nth-child(1) {width: 150px;height: 150px;background: #000;clip-path: polygon(17% 41%,6% 39%,16% 91%,18% 78%,56% 11%,28% 71%,99% 67%,25% 65%,69% 72%,46% 28%,90% 76%,67% 34%,48% 30%,79% 36%,59% 15%,23% 92%,16% 1%,32% 81%,72% 38%,50% 59%,71% 98%,66% 87%,83% 14%,36% 71%,49% 7%,9% 25%,52% 76%,10% 83%,17% 41%);
}
效果如下:
这个图可能它会特别的奇怪,没有问题,我们继续。
如果,我们将一个矩形,从左下角开始算,分为 4 份,那么每一个份就是 90° / 4 = 22.5°
,我们希望切割得到其中一份:
我们可以借助 mask 去完成这个切割:
.g-item:nth-child(1) {width: 150px;height: 150px;background: #000;clip-path: polygon(.....);mask: conic-gradient(from 0turn at 0 100%, #000, #000 22.5deg, transparent 22.5deg, transparent);
}
上述的图形,就被切割成了这样:
OK,基于此,我们可以得到同样的第二份图形,但是我们给它加一个 rotateY(180deg)
:
.g-item:nth-child(2) {width: 150px;height: 150px;background: #000;clip-path: polygon(.....);mask: conic-gradient(from 0turn at 0 100%, #000, #000 22.5deg, transparent 22.5deg, transparent);transform: rotateY(180deg);
}
效果如下:
我们再通过 rotateZ()
,给第二图形旋转一定的角度,让他和第一个贴合在一起:
.g-item:nth-child(2) {clip-path: polygon(.....);mask: conic-gradient(from 0turn at 0 100%, #000, #000 22.5deg, transparent 22.5deg, transparent);transform: rotateY(180deg) rotateZ(-45deg);
}
就得到了一个斜向角度的镜像图像:
因为 .g-item
被切割成了 4 份,所以第 3、4 个图形如法炮制即可,这样,整个 .g-item
的效果如下:
再打开 -webkit-box-reflect
,整个的图形效果如下:
这样,一个剪纸图形就诞生啦!
当然,为了得到不一样的效果,我们可以借助 JavaScript 去随机生成 CSS 中的各类参数,完整的代码,大概是这样:
<div class="g-parent"><div class="g-container"><div class="g-item"></div><div class="g-item"></div><div class="g-item"></div><div class="g-item"></div></div>
</div>
.g-container,
.g-parent {position: relative;display: flex;width: 150px;height: 150px;
}
.g-item {position: absolute;top: 0;left: 0;bottom: 0;right: 0;background: #000;transform-origin: 0 100%;clip-path: var(--polygon, polygon(40% 0%,0% 91%,52% 100%,0% 37%,77% 23%,77% 76%,43% 22%,55% 88%,100% 100%,100% 10%));
}
.g-item {mask: conic-gradient(from 0turn at 0 100%, #000, #000 22.5deg, transparent 22.5deg, transparent);
}
@for $i from 1 through 5 { .g-item:nth-child(#{$i}) {transform: rotateZ(calc(22.5deg * #{$i - 1}));}
}
.g-item:nth-child(2) {transform: rotateY(180deg) rotateZ(-60deg);
}
.g-item:nth-child(4) {transform: rotateY(180deg) rotateZ(-105deg);
}
.g-container {-webkit-box-reflect: below;
}
.g-parent {-webkit-box-reflect: left;
}
const ele = document.querySelectorAll('.g-item');document.addEventListener('click', function(e) {let num = Math.floor(Math.random() * 30 + 10);const maskR = Math.floor(Math.random() * 22.5 + 22.5 ) + 'deg';const r1 = Math.floor(Math.random() * 100) + '%';const r2 = Math.floor(Math.random() * 100) + '%'; let polygon = 'polygon(' + r1 + ' ' + r2 + ',';for (let i=0; i<num; i++) {const newR1 = Math.floor(Math.random() * 100) + '%';const newR2 = Math.floor(Math.random() * 100) + '%';polygon += newR1 + ' ' + newR2 + ','}polygon += r1 + ' ' + r2 + ')';[...ele].forEach(item => {item.setAttribute('style', `--polygon:${polygon};-webkit-mask:conic-gradient(from 0turn at 0 100%, #000, #000 ${maskR}, transparent ${maskR}, transparent)`);});
});
整个效果是纯 CSS 的,JavaScript 在这里的作用仅仅是辅助生成随机的 clip-path 图案,以及不同的 mask 切割角度,这样,每次点击鼠标,我们都能得到不同的随机剪纸图案:
看看这个简单录制的 GIF:
完整的代码,你可以猛击这里 CodePen Demo -- Pure CSS Art Page Cutting[5]
最后
本文到此结束,希望对你有帮助 :)
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
参考资料
[1]
-webkit-box-reflect
: https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-box-reflect
[2]
CodePen Demo -- Clock ticks: https://codepen.io/Chokcoco/pen/eYybEpW
[3]
CodePen Demo -- Pure CSS Page Cutting: https://codepen.io/Chokcoco/pen/oNpJewQ
[4]
Paper Snowflakes: Combining Clipping and Masking in CSS: https://css-irl.info/paper-snowflakes-combining-clipping-and-masking-in-css/
[5]
CodePen Demo -- Pure CSS Art Page Cutting: https://codepen.io/Chokcoco/pen/zYpeJBZ
往期干货:26个经典微信小程序+35套微信小程序源码+微信小程序合集源码下载(免费) 干货~~~2021最新前端学习视频~~速度领取前端书籍-前端290本高清pdf电子书打包下载
点赞和在看就是最大的支持❤️
离谱的 CSS!从表盘刻度到剪纸艺术相关推荐
- opencv 表识别 工业表智能识别 数字式表盘识别,指针式表盘刻度识别,分为表检测,表盘纠正,刻度分割,刻度拉直识别
opencv 表识别 工业表智能识别 数字式表盘识别,指针式表盘刻度识别,分为表检测,表盘纠正,刻度分割,刻度拉直识别 _:34400640060136589IT干将
- opencv 表识别 工业表智能识别 数字式表盘识别,指针式表盘刻度识别,分为表检测
opencv 表识别 工业表智能识别 数字式表盘识别,指针式表盘刻度识别,分为表检测,表盘纠正,刻度分割,刻度拉直识别 YYID:37400640060136589
- 计算机毕业设计ssm基于Andriod的剪纸艺术平台3swaq系统+程序+源码+lw+远程部署
计算机毕业设计ssm基于Andriod的剪纸艺术平台3swaq系统+程序+源码+lw+远程部署 计算机毕业设计ssm基于Andriod的剪纸艺术平台3swaq系统+程序+源码+lw+远程部署 本源码技 ...
- Photoshop:中国剪纸艺术后的效果
Photoshop:中国剪纸艺术后的效果[@more@] 中国的剪纸起源于汉代至南北朝时期,然而真正繁盛却是在清朝中期以后.古老的剪纸多在乡间,以剪刀铰出为主:剪纸进入城市后,剪纸艺人为了省工,一刀多 ...
- 第10章第25节:使用Paper Cut Art Generator创建剪纸艺术图像 [PowerPoint精美幻灯片实战教程]
当前网站可以创建剪纸艺术图像,修改此处的参数,可以调整层级的数量. 修改此处的参数,可以调整沟隙的高度. 修改此处的参数,可以调整沟隙的平铺数量. 点击此处的按钮,可以生成随机的剪纸艺术图像. 点击此 ...
- css html 实现刻度,vue语法css实现刻度尺
更新记录 1.0.2(2021-04-09) 滑动小于半个格时,刻度线不会回弹问题 1.0.1(2021-03-28) vue语法css实现刻度尺 横向整数.小数点 竖向整数.小数点 查看更多 平台兼 ...
- 基于HTML+CSS制作静态页面【剪纸文化15页】传统文化设计题材 dreamweaver制作静态html网页设计作业作品...
- css html 实现刻度,用CSS划一把刻度尺
刻度尺 .ruler { position: relative; width: 70%; margin: 20px auto; height: 14px; } .ruler .cm, .ruler . ...
- 基于HTML+CSS制作静态页面【剪纸文化15页】传统文化设计题材 dreamweaver制作静态html网页设计作业作品
最新文章
- java好还是python好-现在学Python还是Java好呢?
- C语言递归算法十进制数转换为八进制(附完整源码)
- spring 整合mongodb报NoSuchMethodError错误
- 使用wrapper将java程序注册程windows服务后不生效
- 大公司稳定工作和创业之间如何选择?
- AsyncTask实现登录功能,上传图片,get,post
- flink网络缓冲池
- 1065. 单身狗(25)-PAT乙级真题
- Android 存储学习之在外部存储中读写文件
- mod sim tcp配置_ModSim32-ModScan32Modbus调试工具使用及配置说明.pdf
- 031. 静以修身,俭以养德,非淡泊无以明志,非宁静无以致远。
- mysql 日志重做,設置MySQL重做日志大小
- 获取input上传图片之后的文件大小,以及路径
- 巧用搜索引擎---如何在指定网站中搜索
- 基于NLP的软件安全研究(二)
- 十年磨一剑,霜刃未曾试(纪念最爱——加内特)
- 数字魔方c语言程序,关于数字魔方的问题
- 计算机ppt制作总结,大神教你如何玩转PPT 制作PPT技巧心得
- 快手引流卖什么暴利?很多人现在都觉得在各大平台引流很难
- windows 10对应驱动下载和应用