一篇文章带你用 CSS 绘制一个3D掘金 logo

开发 前端
像这种比较规则的图形还能简单通过CSS应付一下,如果有一些不规则的,或者有曲面,那就不太好实现了,而且高光也无法真正模拟出来,像这种情况还是建议通过Three.js这样专业的图形处理库才行。

尝试一下用 CSS 绘制简单的 3d 图形,比如一个掘金 logo?

图片

相比 2d 绘制,3d 有哪些需要注意的小细节呢?一起看看吧

一、金字塔形/四棱锥形

除去挖空部分,整个外形其实是一个金字塔形,或者叫四棱锥形(四角锥)。

图片

一共有5个面,所以我们可以准备5个元素。

<juejin>
<pane a></pane>
<pane b></pane>
<pane c></pane>
<pane d></pane>
<bottom></bottom>
</juejin>

其中,bottom表示底部的正方形,其余4个表示侧面4个三角形。

首先先从正方体开始。

注意,需要呈现 3d 视觉,需要添加transform-style: preserve-3d,先绘制一个侧面。

juejin{
--s: 200px;
position: relative;
width: var(--s);
height: var(--s);
transform-style: preserve-3d;
perspective: 3000px;
transform: rotateX(calc( .3 * -90deg)) rotateY(calc( .1 * 90deg));
}
pane{
position: absolute;
inset: 13.3% 0 0;
transform-origin: center bottom;
}
pane[a]{
background-color: #368dff;
transform: translate3d(0, 0, calc(var(--s) * -0.5));
}

效果如下:

图片

用同样的方式,绘制出4个侧面。

pane[b]{
background-color: #368dff;
transform: translate3d(0, 0, calc(var(--s) * 0.5));
}
pane[c]{
background-color: #1e80ff;
transform: translate3d(calc(var(--s) * -0.5), 0, 0) rotateY(90deg);
}
pane[d]{
background-color: #1e80ff;
transform: translate3d(calc(var(--s) * 0.5), 0, 0) rotateY(90deg);
}

效果如下:

图片

然后,将4个侧面裁剪成三角形,用clip-path就行了。

pane{
/**/
clip-path: polygon(50% 0, 100% 100%, 0 100%);
}

效果如下:

图片

最后,将4个侧面沿着底部旋转一个角度,使其合并在一起,由于大小完全一样,底部又是正方形,倾斜角度自然也相同,这里就不通过数学计算了,直接用一个 CSS 变量去实时比对。

juejin{
/**/
--deg: 35.3deg;
}
pane[a]{
/**/
transform: translate3d(0, 0, calc(var(--s) * -0.5)) rotateX(calc(var(--deg) * -1));
}
pane[b]{
/**/
transform: translate3d(0, 0, calc(var(--s) * 0.5)) rotateX(var(--deg));
}
pane[c]{
/**/
transform: translate3d(calc(var(--s) * -0.5), 0, 0) rotateY(90deg) rotateX(calc(var(--deg) * -1));
}
pane[d]{
/**/
transform: translate3d(calc(var(--s) * 0.5), 0, 0) rotateY(90deg) rotateX(var(--deg));
}

效果如下:

图片

这样就得到了一个金字塔形/四棱锥形。

图片

二、侧边镂空和横截面处理

前面得到了一个完整的四棱锥,现在需要先将侧面镂空。

这里有两种方式,第一,可以用透明和不透明的渐变填充,这样透明的部分就是镂空的了;还有一种方式,用​​mask​​遮罩,也能轻易的实现。

pane{
/* */
-webkit-mask: linear-gradient(to bottom, red 50%, transparent 0) 0 0/ 100% 40%;
}

效果如下:

图片

但是现在还是看着像纸片一样,需要将截断的几个面都封起来,我们再加一个标签,用两个伪元素将顶部覆盖。

<juejin>
<!-- -->
<top></top>
</juejin>
top{
position: absolute;
inset: 0;
background-color: #1677f7;
transform: translate3d(0, calc(var(--s) * 0.36), 0) rotateX(90deg) scale(.8);
transform-style: preserve-3d;
box-shadow: inset 0 0 calc(var(--s) * 0.3) rgb(255 255 255 / 45%);
}
top::before{
content: '';
position: absolute;
inset: 0;
background-color: inherit;
transform: translate3d(0, 0, calc(var(--s) * 0.285)) scale(.5);
box-shadow: inherit;
}

当然,这里需要多多调整一下细节,确保横截面的大小和位置刚好吻合。

图片

同样还有底部的截面。

bottom::before,
bottom::after{
content: '';
position: absolute;
inset: 0;
background-color: inherit;
transform: translate3d(0, 0, calc(var(--s) * 0.285)) scale(.595);
box-shadow: inherit;
}
bottom::after{
transform: translate3d(0, 0, calc(var(--s) * 0.568)) scale(.195)
}

效果如下:

图片

三、其他光影细节和鼠标跟随效果

首先是底部的投影,这是通过​​filter: blur​​实现的,可以让整个场景更具空间感。

juejin::after{
position: absolute;
content: '';
width: var(--s);
height: var(--s);
top: 80%;
background-color: rgba(0, 0, 0, 0.1);
transform: rotateX(90deg) scale(1.2);
filter: blur(20px);
}

图片

然后是截面的高光处理,这里是通过内阴影实现的,让整体光影看着更加自然,就像上方有光线一样

top{
/**/
box-shadow: inset 0 0 calc(var(--s) * 0.3) rgb(255 255 255 / 45%);
}

图片

最后是鼠标跟随效果,这里是通过 CSS 变量实现的,通过 JS 获取鼠标的相对位置,然后通过 CSS 变量 传递,实时改变 transform 的旋转角度。

juejin{
/* */
transform: rotateX(calc( (var(--y) - 0.3) * -90deg)) rotateY(calc( (var(--x) - 0.3) * 90deg));
}

JS 监听mousemove就可以了。

document.body.addEventListener('mousemove', function(ev){
document.body.style.setProperty('--x', ev.clientX / document.body.offsetWidth)
document.body.style.setProperty('--y', ev.clientY / document.body.offsetHeight)
})

这样就得到了文章开头所示效果:

图片

四、总结一下

总的来说,绘制这样一个的 3d 图形还是比较轻松的,下面总结一下

  1. 添加transform-style: preserve-3d才能呈现 3d 视觉。
  2. 掘金 logo 整体上是一个金字塔形,或者叫四棱锥形(四角锥)。
  3. 整个绘制就是通过translate3d、rotate3d等基础操作组合而成。
  4. 镂空部分可以通过渐变填充,或者mask遮罩实现。
  5. 横截面需要多多调整一下细节,确保横截面的大小和位置刚好吻合。
  6. 为了让整个模型更加真实,需要添加合理的高光和投影。
  7. 鼠标跟随效果可以通过 CSS 变量传递实现。

当然,像这种比较规则的图形还能简单通过CSS应付一下,如果有一些不规则的,或者有曲面,那就不太好实现了,而且高光也无法真正模拟出来,像这种情况还是建议通过three.js这样专业的图形处理库才行。

责任编辑:姜华 来源: 前端侦探
相关推荐

2021-05-31 09:30:36

Css前端CSS 特效

2020-11-03 19:18:28

CSS对齐文本

2022-12-14 08:03:27

CSS变量前端

2021-01-15 18:37:49

CSS3Filters视觉

2021-04-07 06:11:37

Css前端CSS定位知识

2021-01-25 05:39:54

Css前端Border

2021-01-20 05:31:29

CSS3Filters图像

2020-12-18 05:40:37

CSS clearHtml

2020-11-27 08:51:29

CSSOpacity透明度

2020-11-17 11:10:21

CSS选择器HTML

2023-07-30 15:18:54

JavaScript属性

2021-05-18 08:30:42

JavaScript 前端JavaScript时

2023-09-06 14:57:46

JavaScript编程语言

2021-01-26 23:46:32

JavaScript数据结构前端

2021-03-05 18:04:15

JavaScript循环代码

2021-03-09 14:04:01

JavaScriptCookie数据

2024-01-30 13:47:45

2021-06-24 09:05:08

JavaScript日期前端

2021-09-27 09:18:30

ListIterato接口方法

2020-12-08 08:09:49

SVG图标Web
点赞
收藏

51CTO技术栈公众号