离谱的 CSS!从表盘刻度到艺术剪纸
作者:chokcoco
来源:SegmentFault 思否社区
某日,群里有这样一个问题,如何实现这样的表盘刻度:
这其实是个挺有意思的问题,方法也有很多。
单标签,使用 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)
}
这样,我们就得到了一个表盘刻度:
这是使用一个标签就能实现的方式,当然,缺点也很明显:
锯齿感严重,渐变的通病 由于是使用的角向渐变,刻度存在头重脚轻的现象,越向内部,宽度越窄(刻度愈大,差异愈加明显)
使用多个标签实现
<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});
}
}
借助 -webkit-box-reflect 减少标签数
div {
-webkit-box-reflect: below;
}
<div></div>
div {
background-image: url('https://images.pokemontcg.io/xy2/12_hires.png');
}
div {
background-image: url('https://images.pokemontcg.io/xy2/12_hires.png');
-webkit-box-reflect: right;
}
<div class="g-parent">
<div class="g-container">
<div class="g-item"></div>
// ... 一共 16 个
<div class="g-item"></div>
</div>
</div>
@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;
}
.g-container {
-webkit-box-reflect: below 4px;
}
.g-parent {
-webkit-box-reflect: left -4px;
}
-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 {
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%);
}
-webkit-box-reflect 配合 clip-path 配合 mask
<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-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%);
}
.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);
}
.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);
}
.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);
}
<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)`);
});
});
最后
关注公众号:拾黑(shiheibook)了解更多
赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号
随时掌握互联网精彩
随时掌握互联网精彩
- 美元兑人民币汇率2023年8月15日
- 卢布汇率人民币2023年8月6日
- 日元对人民币汇率2023年7月7日
- 延续摩尔定律,还看先进封装
- 巨头下场,互联网家装市场战事再起
- Linux kernel 5.14 来了:13000 项提交,删除全部遗留 IDE 代码
- 小米举办春季发布会;索尼将关闭 PS3 等线上游戏商店;微信iOS版更新|Do早报
- 紧跟时事,如何围观苏伊士运河堵船
- iPhone 13 Pro正测试三星120Hz屏幕,新iPad Pro将搭载A14X芯片
- 云版 Android 系统来了?
- 互动竟能点燃年轻人看晚会的热情?
- 我为“十四五”建言丨赛迪智库信软所:发挥信息化创新引领赋能全域作用 着力推进产业数字化转型
赞助链接