在CSS3和SVG出现之前,我们脑海里可能会有一些酷炫的想法,因为技术的不支持一直没办法实现。但是,随着技术的发展,这些高大上的想法越来越有实现的可能。例如,我们现在有很多的方式来实现文字填充动画。
大概一年前,Sara Soueidan发表了一篇Techniques for Creating Textured Text的文章。这篇神奇的文章告诉我们如何使用一些现代web技术、包括canvas等,来实现创建纹理文字的效果。如图:
看到这个,我们就会想,能不能让里面文字填充的背景动起来?我们可以实现文字的阴影或渐变的动画?或者使用一个视频(video
)来填充文本如何?
这篇文章我将会分享如何创建图案填充的文本动画。当然,最好还要保留文本的文字选择能力,用于复制、粘贴等。
因为是高度实验性的代码,可能有大部分浏览器不支持,为了更好的体验效果请用chrome最新版浏览器来阅读该文章,谢谢。
方法1:使用background-clip
这个方式可能是我们脑海里第一个蹦出来的想法,虽然只有WebKit内核的浏览器支持,所以要加上-webkit-
前缀。
html标签如下:
1 2 3
| <div class="box-with-text"> Text </div>
|
CSS是这样的:
1 2 3 4 5
| .box-with-text{ background-image:url('img/1.jpg'); -webkit-text-fill-color: transparent; -webkit-background-clip: text; }
|
效果如下:
文字依然文本,所以我们可以选择和复制。其缺点是缺乏浏览器的支持。
但我们可以用CSS渐变与-webkit-前缀以除去非Webkit的浏览器的背景:
1 2 3 4 5 6
| .box-with-text{ background-image:-webkit-linear-gradient(transparent, transparent), url('img/1.jpg'); -webkit-text-fill-color: transparent; -webkit-background-clip: text; }
|
不支持的浏览器将完全忽略了整个字符串,我们能够避免完全显示的背景图像。这简单的一招将使我们能够解决非Webkit内核的浏览器,如果我们不希望显示的图像话。
如果我们要实现填充动画,CSS可以实现。但是我们CSS动画只能实现改变背景的位置和大小,不能平滑地改变颜色。效果如图
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| // scss @include keyframes(stripes) { 100% { background-position: 0 -50px; } }
.box-with-text{ background-image: -webkit-linear-gradient(crimson 50%, #FD0 50%); background-repeat: repeat; background-position: 0 0; background-size: 100% 50px; -webkit-text-fill-color: transparent; -webkit-background-clip: text; @include animation(stripes 2s linear infinite); }
|
结论
使用该技术实现:只支持WebKit内核浏览器,有限的填充文字的动画效果。
方法2:使用SVG
SVG是一种奇妙的格式,它具有良好的浏览器支持。在SVG中,我们有三种方式来使文章填充图案:
我将会逐一使用这些方式来展示文字填充图案的效果。
如果你不了解SVG,建议你阅读SVG规范,或者其他SVG教程等。
html使用方法如下:
1 2 3 4 5
| <svg viewBox="0 0 600 300"> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text"> Text </text> </svg>
|
在它的常规文本中,我们也可以自由的复制粘帖
在SVG中添加一个简单的linearGradient标签:
1 2 3 4 5 6 7 8 9 10 11
| <svg viewBox="0 0 600 300"> <linearGradient id="gr-simple" x1="0" y1="0" x2="100%" y2="100%"> <stop stop-color="hsl(50, 100%, 70%)" offset="10%"/> <stop stop-color="hsl(320, 100%, 50%)" offset="90%"/> </linearGradient> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text"> Text </text> </svg>
|
1 2 3 4 5
| .text { font: 12.5em/1 Open Sans, Impact; text-transform: uppercase; fill: url(#gr-simple); }
|
就可以实现渐变填充的效果:
想了解更多关于gradients
的知识可以阅读Joni Trythall的文章Getting Started with SVG Gradients
使用fill
来填充颜色的方式也可以直接写在text
的属性fill
上,要使用gradients
是必须定义ID,并且将之插入到url()
中。
1 2 3 4 5
| <svg viewBox="0 0 600 300"> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text" fill="url(#gr-simple)"> Text </text> </svg>
|
当然,你喜欢使用css的话也行。
1 2 3
| .text { fill: url(#gr-simple); }
|
我们可以设置gradient
的字体颜色,但是我们需要使用SMIL来控制gradient
的其他属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <radialGradient id="gr-radial" cx="50%" cy="50%" r="70%">
<animate attributeName="r" values="0%;150%;100%;0%" dur="5s" repeatCount="indefinite" />
<stop stop-color="#FFF" offset="0"> <animate attributeName="stop-color" values="#333;#FFF;#FFF;#333" dur="5s" repeatCount="indefinite" /> </stop> <stop stop-color="rgba(55,55,55,0)" offset="100%"/> </radialGradient>
|
效果如下
想了解更多关于SMIL的知识可以阅读Sara Soueidan的文章A Guide to SVG Animations (SMIL)
现在我们来使用<pattern>
试试。
<pattern>
标签的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12
| <pattern id="p-spots" viewBox="0 0 80 80" patternUnits="userSpaceOnUse" width="60" height="60" x="5" y="5" > <g class="g-spots"> <circle r="5" cx="10" cy="10"/> <circle r="7" cx="30" cy="30"/> <circle r="5" cx="50" cy="10"/> <circle r="9" cx="70" cy="30"/> <circle r="11" cx="50" cy="50"/> <circle r="5" cx="10" cy="50"/> <circle r="7" cx="30" cy="70"/> <circle r="9" cx="70" cy="70"/> </g> </pattern>
|
这里仅定义了圆的大小和位置,样式需要在css中定义。或者使用sass:
1 2 3 4 5 6 7 8 9 10 11
| $colors: #1D4259, #0A7373, #30BF7C, #BAF266, #EEF272; $max: length($colors);
.g-spots circle { @for $item from 1 through $max { &:nth-child(#{$max}n + #{$item}){ fill: nth($colors, $item); } } }
|
这样就会生成下面的css:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| .g-spots circle:nth-child(5n + 1) { fill: #1D4259; } .g-spots circle:nth-child(5n + 2) { fill: #0A7373; } .g-spots circle:nth-child(5n + 3) { fill: #30BF7C; } .g-spots circle:nth-child(5n + 4) { fill: #BAF266; } .g-spots circle:nth-child(5n + 5) { fill: #EEF272; }
|
想了解更多有关于SVG patterns的,可以阅读MDN-SVG教程相关文章。
我是使用sass来做css的预编译的,所以可以很方便的指定动画的延时。代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| $colors: #551F7A, #BA2799, #D9587A, #FFDD00, #FFF3A1; $max: length($colors);
$time: 2s; $time-step: $time/$max;
.g-stars polygon { stroke-width: 0; animation: stroke $time infinite;
@for $item from 1 through $max { &:nth-child(#{$max}n + #{$item}){ $color: nth($colors, $item); fill: $color; stroke: $color; animation-delay: -($time-step*$item); } } }
@keyframes stroke { 50% { stroke-width: 10; } }
|
// 编译后的css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| // css .g-stars polygon { stroke-width: 0; animation: stroke 2s infinite; } .g-stars polygon:nth-child(5n + 1) { fill: #551F7A; stroke: #551F7A; animation-delay: -0.4s; } .g-stars polygon:nth-child(5n + 2) { fill: #BA2799; stroke: #BA2799; animation-delay: -0.8s; }
.g-stars polygon:nth-child(5n + 3) { fill: #D9587A; stroke: #D9587A; animation-delay: -1.2s; } .g-stars polygon:nth-child(5n + 4) { fill: #FFDD00; stroke: #FFDD00; animation-delay: -1.6s; } .g-stars polygon:nth-child(5n + 5) { fill: #FFF3A1; stroke: #FFF3A1; animation-delay: -2s; }
@keyframes stroke { 50% { stroke-width: 10; } }
|
接下来我们把里面的圆圈替换成星星,并且让他放大缩小。
因为代码比较长,就不放出了,大家可以自己审查元素来查看。
当然我们也可以使用gif动画,虽然体积会比较庞大,但是可以创建出很好的效果。
pattern中用来使用图片的方法如下:
1 2 3
| <pattern id="p-fire" viewBox="30 100 186 200" patternUnits="userSpaceOnUse" width="216" height="200" x="-70" y="35" > <image xlink:href="/img/post/AnimateTextFills/fire.gif" width="256" height="300"/> </pattern>
|
不同于background-clip
,文本文字将正确的显示在最新的浏览器。
接下来我们来谈谈stroke
,对于html来说,我们可以使用text-shadow
的方式来模拟一个类stroke
,但是这种方式很大的局限性。
如图,实现这样的效果可以使用如下代码:
1 2 3 4 5
| .box-with-text { text-shadow: -0px -0px 0 yellowgreen, 0px -0px 0 yellowgreen, 0px 0px 0 yellowgreen, -0px 0px 0 yellowgreen, -1px -1px 0 yellowgreen, 1px -1px 0 yellowgreen, 1px 1px 0 yellowgreen, -1px 1px 0 yellowgreen, -2px -2px 0 yellowgreen, 2px -2px 0 yellowgreen, 2px 2px 0 yellowgreen, -2px 2px 0 yellowgreen, 0 5px 15px rgba(0, 0, 0, 0.2); font: 26vmax/.85 Open Sans, Impact; color: #FFF; }
|
用text-shadow实现起来确实非常的繁琐,而且代码相当的臃肿。
不同于HTML,stroke
是可用于SVG的所有元素,包括文本。并且除了作为线条它们也可填充渐变和图案。
对于这种类型的stroke
,我们需要把许多颜色置入到文本中,可以使用下面的方法来实现。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div class="demo"> <svg viewBox="0 0 600 300" class="demo6"> <symbol id="s-text"> <text text-anchor="middle" x="50%" y="50%" dy=".35em"> Text </text> </symbol> <use xlink:href="#s-text" class="text"></use> <use xlink:href="#s-text" class="text"></use> <use xlink:href="#s-text" class="text"></use> <use xlink:href="#s-text" class="text"></use> <use xlink:href="#s-text" class="text"></use> </svg> </div>
|
用样式控制颜色和动画
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| $colors: #551F7A, #BA2799, #D9587A, #FFDD00, #FFF3A1; $max: length($colors);
@include keyframes(stroke2) { 100% { stroke-dashoffset: -400; } }
.text { fill: none; stroke-width: 6; stroke-linejoin: round; stroke-dasharray: 70 330; stroke-dashoffset: 0; @include animation(stroke2 6s infinite linear); @for $item from 1 through $max { &:nth-child(#{$max}n + #{$item}){ $color: nth($colors, $item); stroke: $color; @include animation-delay(#{-(1.2 * $item)}s); } } }
|
编译出来的css就是这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| .text { fill: none; stroke-width: 6; stroke-linejoin: round; stroke-dasharray: 70 330; stroke-dashoffset: 0; animation: stroke2 6s infinite linear; }
.text:nth-child(5n + 1) { stroke: #551F7A; animation-delay: -1.2s; }
.text:nth-child(5n + 2) { stroke: #BA2799; animation-delay: -2.4s; }
.text:nth-child(5n + 3) { stroke: #D9587A; animation-delay: -3.6s; }
.text:nth-child(5n + 4) { stroke: #FFDD00; animation-delay: -4.8s; }
.text:nth-child(5n + 5) { stroke: #FFF3A1; animation-delay: -6s; }
@keyframes stroke { 100% { stroke-dashoffset: -400; } }
|
对于每一个stroke
,我们单独设置一个动画延时,所有他们的路径就不会积聚在同一个地方,而是通过在一个字母上不同的位置循环。
结论
使用这种方法的文本可以使用CSS样式。我们也可以选择和复制的文本。另一大优势是,SVG具有非常好的浏览器的支持。因此,创建这类文本,SVG是最好的人选之一。
未完待续……