当前位置: 首页 > 科技观察

离谱的CSS!从刻度盘刻度到剪纸艺术

时间:2023-03-22 17:31:21 科技观察

有一天,群里有个问题,这样的刻度盘刻度如何实现:这其实是个很有意思的问题,有很多种方法。单标签,使用conic-gradient实现表盘刻度最简单方便的方法就是使用conic-gradient角度渐变,代码也很简单,首先我们实现一个重复的角度渐变:

div{宽度:300px;高度:300px;边界半径:50%;background:repeating-conic-gradient(#0000,#000.8deg,transparent1deg,transparentcalc((360/60)*1deg));}其实比较难理解的是calc((360/60)*1deg),因为表盘上通常有60个刻度。效果大概是这样的:接下来只需要将中间挖空即可。如果底色是白色,直接叠加一个圆就可以了。当然更好的办法是通过mask属性挖空:{background:repeating-conic-gradient(#0000,#000.8deg,transparent1deg,transparentcalc(/60*1deg));mask:radial-gradient(transparent0,transparent140px,#000140px)}这样我们就得到了刻度盘刻度:这是使用标签的方式,当然缺点也很明显:锯齿严重,梯度是一个常见的问题。由于使用的角度梯度,秤存在头重脚轻的现象。越靠近内部,宽度越窄(尺度越大,差异越明显)。如果你不介意使用太多标签,通常更容易想到60个标签,加上轮换:
//。..总共60个
.g-item{position:absolute;宽度:4px;高度:12px;背景:#000;左:0;顶部:0;transform-origin:0150px;}@for$i从1到60{.g-item:nth-child(#{$i}){transform:rotate(#{($i-1)*6deg});}}像这样,我们使用SASS的for语法,通过60个div标签减少重复代码量,实现每个元素分批次逐渐围绕某个点旋转角度,还可以实现刻度盘:这种方案的优点是每个鳞片的厚度相同,不会出现锯齿状。使用-webkit-box-reflect减少标签数量当然,上述方案的缺点是用60个标签来完成这么简单的图形,未免有些过于奢侈了。我们希望尽可能优化优化标签的数量。至此,我们很容易想到——webkit-box-reflect,反射效果属性。-webkit-box-reflect[1]是一个非常有趣的属性,它使CSS能够像镜子一样工作,反映我们的元素最初绘制的内容。-webkit-box-reflect的语法很简单,最基本的用法是这样的:div{-webkit-box-reflect:below;}其中,below可以是below|以上|左|right代表bottom,top,left,right,也就是有4个方向可以选择。假设我们有如下图片:
div{background-image:url('https://images.pokemontcg.io/xy2/12_hires.png');}plus-webkit-box-reflect:对,就是右边的倒影:div{background-image:url('https://images.pokemontcg.io/xy2/12_hires.png');-webkit-box-reflect:right;}效果如下,在元素右侧生成一个镜像元素:使用-webkit-box-reflect:right我们可以将使用量从至少60个标签减少到15个标签。简单地嵌套两层。我们简单的改一下HTML结构:
//...一共16个这次,我们只需要实现1/4的圆比例:@for$ifrom1through16{.g-item:nth-child(#{$i}){变换:旋转(#{($i-1)*6deg});}}我们可以得到这样一个图形:基于这个图形,我们只需要先向左反射一次,然后再向下反射:.g-container{-webkit-box-reflect:below;}.g-parent{-webkit-box-reflect:left;}效果如下:大体效果出来了,当然0点、3点、6点这四个刻度有问题,和9点钟。但是-webkit-box-reflect也提供了距离调整功能,然后简单修改一下代码:.g-container{-webkit-box-reflect:below4px;}.g-parent{-webkit-box-reflect:left-4px;}这一次,效果正是我们想要的:我们设法用-webkit-box-reflect节省了标签数量的3/4。完整代码:CodePenDemo--Clockticks[2]。-webkit-box-reflect和剪纸艺术说到这里,我不禁觉得这种对折,对折,镜像,镜像的方式很像我们小时候的折纸艺术年轻的。所以,基于这样一个模板:.g-container{-webkit-box-reflect:below;}.g-parent{-webkit-box-reflect:left;}我只需要绘制.g-item里面的内容,传2次-webkit-box-reflectimage,可以得到剪纸图形。以及如何得到随机有趣的不规则图形?clip-path是一个很好的选择,我们通过clip-path随机裁剪一个矩形:.g-item{width:150px;高度:150px;背景:#000;剪辑路径:多边形(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多试几次得到不同的效果:CodePenDemo--PureCSSPageCutting[3]。-webkit-box-reflect与clip-path和mask一起使用,但上面的图形看起来太简单了。有几个原因。一是折角的数量不够,不同角度的折痕和折痕数量不足。二是图形不够负责。.想起之前看过一篇类似剪纸相关的文章——PaperSnowflakes:CombiningClippingandMaskinginCSS[4]。在上面的基础上,还使用了遮罩,将图形切割得更细。再来一遍,还是一样的结构,当然为了得到更负责的图形,我们设置了4个.g-item:首先,设置一个clip-path切图:.g-item:nth-child(1){width:150px;高度:150px;背景:#000;剪辑路径:多边形(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){宽度:150px;高度:150px;背景:#000;剪辑路径:多边形(.....);mask:conic-gradient(from0turnat0100%,#000,#00022.5deg,transparent22.5deg,transparent);}上面的图形裁成这样:OK,基于此,我们可以得到相同的第二个图形,但我们添加了一个rotateY(180deg):.g-item:nth-child(2){width:150px;高度:150px;背景:#000;剪辑路径:多边形(.....);mask:圆锥梯度(从0turnat0100%,#000,#00022.5deg,transparent22.5deg,transparent);transform:rotateY(180deg);}效果如下:我们使用rotateZ()将第二个图形旋转一定角度,使其与第一个保持一致合在一起:.g-item:nth-child(2){剪辑路径:多边形(.....);掩码:圆锥梯度(从0turnat0100%,#000,#00022.5deg,transparent22.5deg,transparent);transform:rotateY(180deg)rotateZ(-45deg);}得到一个斜角的镜像:因为.g-item被切割成4份,所以第3和第4个图形可以用同样的方式处理。这样,整个.g-item的效果如下:然后打开-webkit-box-reflect,整个图形效果如下:这样,一个clip纸质图形诞生!当然,为了得到不同的效果,我们可以使用JavaScript在CSS中随机生成各种参数。完整代码大概是这样的:.g-item{位置:绝对;顶部:0;左:0;底部:0;右:0;背景:#000;变换原点:0100%;剪辑路径:var(--多边形,多边形(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(from0turnat0100%,#000,#00022.5deg,transparent22.5deg,transparent);}@对于$i从1到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;}constele=document.querySelectorAll('.g-item');文档.addEventListener('click',function(e){letnum=Math.floor(Math.random()*30+10);constmaskR=Math.floor(Math.random()*22.5+22.5)+'deg';constr1=Math.floor(Math.random()*100)+'%';constr2=Math.floor(Math.random()*100)+'%';letpolygon='polygon('+r1+''+r2+',';for(leti=0;i{item.setAttribute('style',`--polygon:${polygon};-webkit-mask:conic-gradient(from0turnat0100%,#000,#000${maskR},transparent${maskR},transparent)`);});});整个效果是纯CSS的,JavaScript在这里这里的作用只是帮助生成随机的clip-pathpatterns和不同的maskcuttingangle,让我们每次点击鼠标都能得到不同的随机剪纸图案:看看这个简单录制的GIF:完整代码,可以点击到这里CodePenDemo--纯CSS美术页面裁剪[5]本文到此结束,希望对你有所帮助:)参考资料[1]-webkit-box-reflect:https://developer.mozilla。org/en-US/docs/Web/CSS/-webkit-box-reflect。[2]CodePen演示——时钟滴答:https://codepen.io/Chokcoco/pen/eYybEpW。[3]CodePen演示--纯CSS页面切割:https://codepen.io/Chokcoco/pen/oNpJewQ。[4]纸雪花:在CSS中结合剪裁和遮罩:https://css-irl.info/paper-snowflakes-combining-clipping-and-masking-in-css/。[5]CodePenDemo--纯CSS美术切页:https://codepen.io/Chokcoco/pen/zYpeJBZ。