CSS3 SVG实现可爱的动物哈士奇和狐狸动画

澳门新葡亰网址 1

本文由码农网 –
小峰原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿计划!

关于CSS反射倒影的研究思考,css反射倒影

原文地址:

译者:nzbin

友情提示:该文章篇幅较长,内容庞杂,有一定难度。而我本人学识有限,加之时间仓促,所翻译内容可能有不恰当及晦涩之处。欢迎大家拍砖指正。

 

我最近在codepen上看到了这个
加载程序,一个纯CSS制作的带有渐变反射的3D旋转竖条。它的制作方法是,为每个竖条创建一个元素,然后通过复制每一个元素来创建反射倒影,最后在反射倒影上添加渐变背景来创建渐隐的效果。听上去有点复杂,而且创建渐隐效果的渐变背景在非纯色背景下是无效的。有没有更好的CSS方法呢?

.loader 元素以及在其中创建10个 .bar
元素

HTML

<div class='loader'>
  <div class='bar'></div>
  <!-- repeat to create 9 more bars -->
</div>

把同样的事情写很多遍是一件痛苦的事,所以在该情况下使用一个预处理器会变得很简单。我们在这里使用
Haml 模板,当然也有人会选择其他的模板。

Haml

.loader
  - 10.times do
  .bar

 我们通过绝对定位把所有元素放到视图的中间。大多数情况下,我们使用 top: 50% ,但是现在,使用 bottom: 50% 会使后面的操作更简单。

CSS

div {
  position: absolute;
  bottom: 50%; left: 50%;
}

我们给竖条设置 width 和 height ,为了能看到它再设置一个 background 

SCSS

$bar-w: 1.25em;
$bar-h: 5 * $bar-w;

.bar {
  width: $bar-w; 
  height: $bar-h;
  background: currentColor;
}

我们希望竖条的底部贴合视图的水平中心线。设置 bottom: 50% 已经可以了。

现在所有的竖条都重合在一起,它们的左边贴在垂直中心线上,底部贴在水平中心线上。

See the Pen bar loader 1.1 creating the bars by Zongbin Niu (@nzbin) on
CodePen.

 

今天,我想向大家展示如何巧妙地使用HTML、CSS排序动画和SVG滤镜把生活中可能最可爱的东西之一——动物画到网页上。我们将探讨绘制动物的两种技术:一种使用纯HTML和CSS,另一种使用内联SVG背景图像。

#定位竖条

我们需要让最左边的竖条和最右边的竖条到垂直中心线的距离相等。这个距离就是竖条数量( $n )的一半乘以竖条的宽度( $bar-w
)。原始demo用的是普通的CSS,我们会使用Sass来减少代码量。

See the Pen initial (stacked) vs. final (distributed) by Zongbin Niu
(@nzbin) on CodePen.

这意味着,从竖条的起始位置开始,我们需要将第一个竖条向左移动 .5 * $n * $bar-w
。左侧是x轴的负方向,需要在前面加负号。所以第一个竖条的 margin-left 就是 -.5 * $n * $bar-w 。

第二个竖条(以0为基数,索引值是1)就是向右(x轴的正方向)移动 1 个竖条的宽度。所以第二个竖条的 margin-left 就是 -.5 * $n * $bar-w + $bar-w 。

第三个竖条(以0为基数,索引值是2)就是向右(x轴的正方向)移动 2 个竖条的宽度。所以第三个竖条的 margin-left 就是 -.5 * $n * $bar-w + 2 * $bar-w 。

最后一个(以0为基数,索引值是
$n - 1)就是向右(x轴的正方向)移动 $n –
1 个竖条的宽度。所以最后一个竖条 margin-left 就是 -.5 * $n * $bar-w + ($n – 1) * $bar-w 。

See the Pen bar distribution by Zongbin Niu (@nzbin) on CodePen.

通常情况下,如果我们认为当前竖条的索引值是 $i (以0为基数),那么 $i 竖条的 margin-left 就是 -.5 * $n * $bar-w + $i * $bar-w
,可以简化为 ($i – .5 * $n) * $bar-w

这就允许我们使用Sass的循环来定位竖条。

SCSS

$n: 10;

@for $i from 0 to $n {
  .bar:nth-child(#{$i + 1}) {
  margin-left: ($i - .5 * $n) * $bar-w;
  }
}

 为了看清楚竖条的边界,我们给它一个 box-shadow 。

See the Pen bar loader 1.2 positioning the bars by Zongbin Niu (@nzbin)
on CodePen.

 

此演示高度实验性质——动画SVG滤镜目前仅在Chrome中可用。

#给竖条添加渐变

 竖条的背景色是从最左边的深蓝色( #1e3f57 )过渡到最右边的浅蓝色( #63a6c1 )。这听上去很像 the Sass mix()
function
所做的。第一个参数是浅蓝色,第二个参数是深蓝色,第三个参数(称作相对权重)表示将多少(百分比表示)浅蓝色混合进去。

对于第一个竖条,这个数量就是 0%
( 0%
数量的浅蓝色),混合结果就是深蓝色。

对于最后一个竖条,这个数量是 100%
( 100% 数量的浅蓝色,也就是 0% 数量的深蓝色),得到的背景色就是浅蓝色。

对于剩下的竖条,我们需要平均分布的中间值。如果我们有 $n 个竖条,第一个竖条在 0% 的位置,最后一个竖条在 100%
的位置,那么我们需要在两者之间平分成 $n-1 个区间。

See the Pen distribute n points on 100% interval (interactive) by
Zongbin Niu (@nzbin) on CodePen.

一般来说,索引值为 $i
的竖条的相对权重是 $i * 100% / ($n –
1) ,这意味着我们要添加如下代码:

SCSS

$c: #63a6c1 #1e3f57; // 1st = light 2nd = dark

@for $i from 0 to $n {
  // list of mix() arguments for current bar
  $args: append($c, $i * 100% / ($n - 1));

  .bar:nth-child(#{$i + 1}) {
  background: mix($args...);
  }
}

现在这些竖条看起来就和原始demo的一样了:

See the Pen bar loader #1.3 shading the bars by Zongbin Niu (@nzbin) on
CodePen.

 

 

所涉及的动画也很复杂,因此本教程将重点介绍创建这些动物以及栩栩如生的动作所涉及的不同技术。放飞你的创意,自行创作独特和俏皮的动物动画吧。

探索反射的方案

 

话不多说,开始咯!

#WebKit浏览器:-webkit-box-reflect

很遗憾,这不是一个标准属性!我不知道为什么这个属性没有标准化。这一属性首次出现在Safari浏览器上时,我还不知道CSS。
但是对于WebKit内核的浏览器,这是一个非常好的实现方法。它做了很多工作。它的使用很简单,即使在不支持该属性的浏览器上,除了不显示反射以外,并没有什么其他影响。

让我们看看它是怎么工作的,它需要三个参数值:

  • 方向:包含 below , left , above , right 
  • 偏移值(可选):指定反射的开始位置到元素的底边的距离(这是一个CSS长度值)。
  • 图片遮罩(可选):可以是CSS渐变值。 

See the Pen how `-webkit-box-reflect` works by Ana Tudor
(@thebabydino) on CodePen.

注意linear-gradient()可以有更多的颜色断点,也可以用radial-gradient()替换。

在我们的demo中,我首先想到的就是给 .loader 元素添加这一属性。

SCSS

.loader {
  -webkit-box-reflect: below 0 linear-gradient(rgba(#fff), rgba(#fff, .7));
}

澳门新葡亰网址,但是在WebKit浏览器中测试时,我们并没有看到反射。

See the Pen bar loader 2.1.1 -webkit-box-reflect by Zongbin Niu (@nzbin)
on CodePen.

这里发生了什么?我们给所有的元素设置了绝对定位,但是并没有设置 .loader
元素的尺寸。所以这是一个宽高都为0的元素。

让我们给 .loader
元素一个明确的尺寸,高度 height 等于竖条的高度 $bar-h ,宽度等于所有竖条的宽度之和 $n * $bar-w
。为了看清元素的边界,我们暂时给它一个 box-shadow 。

SCSS

$loader-w: $n * $bar-w;

.loader {
  width: $loader-w; height: $bar-h;
  box-shadow: 0 0 0 1px red;
}

我之所以用 box-shadow 而不用 outline
是因为如果子元素溢出父元素,在不同的浏览器上使用 outline
突出物体的效果是不一样的。

outline属性在WebKit浏览器中的对比。Edge(上)vs. Firefox(下)

 

添加以上代码后的结果可以在WebKit浏览器中看到:

See the Pen bar loader 2.1.2 explicitly sizing the loader by Zongbin Niu
(@nzbin) on CodePen.

如果你用的不是WebKit浏览器,看下面的图片,就是这个样子:

bottom: 0 。

SCSS

.loader { margin-left: -.5 * $loader-w; }

.bar { bottom: 0; }

修正位置之后的样子如下:

See the Pen bar loader 2.1.3 tweaking loader and bar positions by
Zongbin Niu (@nzbin) on CodePen.

 

澳门新葡亰网址 1

#火狐浏览器 element() + mask

##用 element() 制作反射

  element() 
函数(现在仍然有效,必须在火狐浏览器中并且添加 -moz-
前缀)给我们提供了一个像真实图片一样可以任意使用的图像值。它需要一个参数值,就是我们希望以 background 还是 border-image 显示的被选元素的 id
。这允许我们做很多事情,比如使用可以控制的图片作为背景。我们也可以在Firefox中制作一个反射元素。

需要了解的一个重要事情就是 element()
函数不是递归函数,我们不能创建使用元素作为自身背景的图像。这在创建反射的loader元素的伪类上使用是安全的,因此我们不用创建额外的元素。

好吧,让我们看看如何操作。首先,我们给 .loader 元素一个 id
。转到样式表,我们从适用WebKit浏览器的CSS着手。我们在loader元素上添加一个 ::after 伪类

CSS

.loader::after {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  box-shadow: 0 0 0 2px currentColor;
  color: crimson;
  content: 'REFLECTION';
}

为了在最终效果中看清伪类的边界和方向,我们设置了一些暂时性的样式,我们想让它是颠倒的。

See the Pen bar loader 2.2.1 adding a pseudo by Zongbin Niu (@nzbin) on
CodePen.

现在我们需要以底边为基准把 ::after
伪类镜像过来。为了做到这一点,我们使用 scaleY() 属性并且选择合适的 transform-origin 。

以下的可交互demo说明了包含多个缩放因子以及变换中心的定向缩放是如何工作的:

See the Pen how CSS scaling w.r.t. various origins works by Ana Tudor
(@thebabydino) on CodePen.

注意:缩放因子的数值和变换中心可以超出demo中规定的限制。

在我们的例子中,我们需要 scaleY(-1)
并且 transform-origin 在 ::after 伪类的底边上。

使用scaleY(-1)和一个合适的 transform-origin 来镜像元素

 

我们把这些设置添加到代码中,并且用 element
() 函数把 ::after
伪类的背景设置为 #loader 

CSS

.loader::after {
  transform-origin: 0 100%;
  transform: scaleY(-1);
  background: -moz-element(#loader);
}

注意:由于特别的原因我们使用 .loader 作为选择器并且由于element() 函数参数的需要我们设置它的 id 为 #loader 。

添加以上代码后的效果如下所示(只在Firefox浏览器中有效)

See the Pen bar loader 2.2.2 -moz-element() for reflecting pseudo by
Zongbin Niu (@nzbin) on CodePen.

对于在其他浏览器阅读这篇文章的朋友,以下是截图

在Firefox中使用 element() 制作的反射效果

 

##用 mask 制作渐变

 我们使用和WebKit情况下一样的方法给反射添加渐变。在WebKit的情况下,遮罩是 -webkit-box-reflect
属性的一部分。而现在,我们讨论CSS的 mask 属性,它需要引用SVG作为值。

CSS

mask: url(#fader);

 #fader
元素是一个包含长方形的SVG mask 元素。

SVG

<svg>
  <mask id='fader' maskContentUnits='objectBoundingBox'>
    <rect width='1' height='1'/>
  </mask>
</svg>

我们可以用Haml模板压缩一下

Haml

%svg
  %mask#fader(maskContentUnits='objectBoundingBox')
    %rect(width='1' height='1')

但是,如果我们加上以上代码,我们的反射倒影消失了,在Firefox中查看如下demo

See the Pen bar loader 2.2.3 adding a SVG mask by Zongbin Niu (@nzbin)
on CodePen.

这是因为,默认情况下,SVG图形会有一个纯黑色的 fill ,完全不透明,但是,我们的 遮罩
默认是有透明度的。因此为了实现反射渐变的效果我们需要给长方形一个 fill (需引入SVG linearGradient )

Haml

%rect(width='1' height='1' fill='url(#grad)')

一个SVG linearGradient
由定义的两个点 x1 , y1 , x2
, y2 组成。 x1 和 y1
是渐变线的起始点(0%)坐标,而 x2
和 y2
是这条线的终点(100%)坐标。如果这些数值是空的,默认设为 0% , 0%
, 100% , 0% 。这些数值描绘了从指定元素(由于 gradientUnits 的默认值是 objectBoundingBox )的左上( 0% 0% )到右上( 100%
0% )的一条线。这意味着,默认情况下,渐变是从左到右。

但是在我们的例子中,我们希望渐变从上到下,所以我们将 x2 的值从 100% 设置为 0% 并且将 y2 的值从 0% 设置为 100%
。这使得指定元素的渐变向量从左上角( 0%
0% )指向左下角( 0% 100% )。

Haml

%linearGradient#grad(x2='0%' y2='100%')

在 linearGradient
元素之内,我们有至少两个 stop
元素。其中有三个特定的属性, 偏移值 , 颜色断点 , 透明度断点。

我们需要记住我们应用渐变遮罩的伪类已经通过 scaleY(-1)
属性镜像过来了,这意味着渐变遮罩的底部在视觉上是顶端。因此我们的渐变是从顶部(视觉下端)的完全透明到底部(视觉上端)的 .7 。

因为我们的渐变从上到下,所以第一个 stop 是完全透明的。

Haml

%linearGradient#grad(x2='0%' y2='100%')
  %stop(offset='0' stop-color='#fff' stop-opacity='0')
  %stop(offset='1' stop-color='#fff' stop-opacity='.7')

添加线性渐变之后,在Firefox中就是我们想要的结果了

实时效果如下:

See the Pen bar loader 2.2.4 linearGradient it by Zongbin Niu (@nzbin)
on CodePen.

 

在线演示
 
源码下载

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

相关文章

网站地图xml地图