w3ctech

CSS绘画

好久没写博客了,最近一直在用React Native写公司的用户端App,感觉还不错,唯一让我感到蛋疼的便是React Native切图太蛋疼了,甚是想念写htmlcss的小日子。居然想玩CSS,那玩点什么好呢,想起去年在广州由w3ctech举行的第三届CSS大会中,压轴的女神现场用CSS撸出一个moustache(小胡须)惊艳了现场的每一个人。让我们先睹为快,看看我们要画的小胡须长啥样(与原版略有出入)。

alt

大家看到这个性感的胡须,有没有想过怎么去实现呢。在开始之前,我们去温习一下相关的CSS知识。

温故

伪元素(preudo element)

每一个div都自带两个伪元素,即beforeafter元素,这样的话,每个div元素都提供3个可供我们操控的三个视觉元素,即三个矩形。


div::before { }
div::after {}

border-radius

border-radius用于设置边框的圆角,使用一个半径时为圆形,使用两个半径时(长轴和短轴)为椭圆形。

border-radius

border-top-left-radius, 
border-top-right-radius, 
border-bottom-right-radius,
border-bottom-left-radius

的缩写属性。

box-shadow

box-shadow用于设置元素的阴影效果,一个元素可以用逗号分隔分隔列表来实现多个阴影效果。另外,若元素设置了border-radius,则阴影也会出现圆角效果。

box-shadow可接受2~5个参数:

  • 两个参数,box-shadow: x y, x 为阴影区域相对于元素在X轴上的偏移量, y为阴影区域相对于元素在Y轴上的偏移量,此时阴影的颜色与元素的字体颜色保持一致
  • 三个参数, box-shadow: x y color, color为阴影的颜色。
  • 四个参数,box-shadow: x y blue color, blur定义了阴影的模糊半径,从不透明到透明。
  • 五个参数, box-shadow: x y blue spred color,spread 定义了阴影的缩放半径。

默认阴影在元素框外,使用inset可以使阴影在元素框内(背景之下,内容之上)

知新

根据上面的 CSS 知识,我们很容易的就可以实现上面的效果,talk is cheap, show me the code。

首先我们先定义一个 如下的 dom 结构:

<div class="moustache"></div>

此时对应的 CSS为:

.moustache {
  width: 1px;
  height: 1px;
  border-radius: 50%;
  position: relative;
 box-shadow: 50px 50px 0 50px black, -50px 50px 0 50px black;
}

很抱歉,这个时候页面上啥也不看见,与我们要画的东西还差的十万八千里,不要着急,我们先给.moustache加上一个box-shadow,页面上会出现如下俩个对称的黑圆圈,我们要画的东西的雏型是不是出现了? alt

接下来我们要绘制的是两个弯曲的部分,此刻页面上只有一个 dom 元素,没办法在已经存在 dom 画出花来了,但您别忘了,我们还有用伪元素(每个 div 元素都自带beforeafter伪元素)来画其他的部分。

.moustache::before, .moustache::after {
  content: '';
  position: absolute;
  width: 100px;
  height: 100px;
  top: -100px;
  border-bottom: solid 100px ;
}

效果如下:

alt

很明显现在只有右边有长方形,而且长方形的边并不在两个yuan的中心上。我们只需要将before 伪元素左移50px,after 伪元素右移50px。

.moustache::before {
  right: 50px;
  border-radius: 0 0 0 100%;
}
.moustache::after {
  left: 50px;
  border-radius: 0 0 100%;
}

alt

接下来要做的不过是将左右伪元素按照一定的角度旋转而已,但要注意的是,默认的旋转中心,是元素的左上角。因此,我们需要调整 before 元素和 after 元素的旋转中心。

:root {
  --radius: 40deg;
}

.moustache::before {
  right: 50px;
  border-radius: 0 0 0 100%;
  transform-origin: right 150px;
  transform: rotate(calc(-1 * var(--radius)));
}
.moustache::after {
  left: 50px;
  border-radius: 0 0 100% 0;
  transform-origin: left 150px;
  transform: rotate(var(--radius));
}

最好大功告成。

alt

也许你注意到上面 css 中的var(--radius)的写法,没错这就是所谓的 CSS 变量,具体使用参考 MDN 的使用 CSS 变量。我们可以很简单的通过 js改变 radius 变量的值,让小胡须动起来。

let root = document.documentElement;
document.addEventListener('mousemove', function (evt){
  let x = evt.clientX / innerWidth;
  const value = (x * 20 + 30);
  root.style.setProperty('--radius', value + 'deg');
});

alt

最后,由w3ctech和前端圈联合主办的第三届FEDAY将于8月26与国家会议中心举行,一大波干货在等着你哦。

w3ctech微信

扫码关注w3ctech微信公众号

共收到0条回复