ホームページ >ウェブフロントエンド >htmlチュートリアル >(動的) テキストの作成方法 fill_html/css_WEB-ITnose
これは、CSS や SVG などのさまざまなテクニックを使用して、テキストのさまざまなタイプの (動的な) 塗りつぶしとストロークを作成する方法に関するチュートリアルです。
デモのダウンロード ソース コードを表示
未来はすでにここにあると思います。 CSS と SVG には、以前は想像することしかできなかった多くのエキサイティングな可能性がすでにあります。たとえば、現在では、動的な塗りつぶしを含むテキストを作成するためのメソッドが多数あります。
約 1 年前、Sara Soueidan はテクスチャ付きテキストを作成するテクニックに関する記事を書き、Codrops で公開しました。この素晴らしい記事では、キャンバスなどの最新の Web テクノロジーを使用して、さまざまなテクスチャのテキストを作成する方法について説明します。
私はこのトピックに非常に興味がありますが、別の観点からです。いくつか質問があります: 追加されたテキスト パディングは動的にできますか?テキストに動的な影やグラデーションを追加できますか?それともビデオを使ってテキストを入力しますか?
この投稿では、私の実験のいくつかと、パターンで埋められたテキストを作成する 5 つの方法を共有します。これら 5 つのケースのうち 3 つでは、テキストを選択できる機能が維持されます。もちろん、あらゆる状況でテキストを選択できるようにしたいのですが、いくつかの回避策を使用することで、この問題を解決することもできます。
各テクノロジーについて、ブラウザーのサポート、テキストを選択する機能、および動的塗りつぶしの追加の可能性 (非常に実験的) を示します。
ここではすべてのコードを載せるわけではなく、最も重要な部分の一部だけを載せますが、ダウンロードしたファイルですべてのコードを見つけて、自分で試してみることができます。
さて、始めましょう。
注: 一部のテクノロジーは実験段階にあり、すべてのブラウザーで動作するとは限りません。そのため、各セクションの前にあるブラウザのサポート状況を確認してください。 IE がサポートしているものはほとんどありません。
ブラウザのサポート: Chrome サポート、Firefox サポートなし、IE サポートなし、Safari サポート、Opera サポート。
これは思い浮かぶ最も直接的な方法ですが、background-clip: text は現在 Webkit ベースのブラウザーでのみサポートされており、接頭辞 -webkit- を追加するだけです。
注: このセクションのデモは、Chrome、Opera、Safari でのみ動作します。
タグは次のとおりです:
<div class="box-with-text">Text</div>
CSSは次のとおりです:
.box-with-text { background-image: url(IMAGE URL); -webkit-text-fill-color: transparent; -webkit-background-clip: text;}
テキストはテキストのプロパティを保持しているため、テキストを選択してコピーできます。欠点は、ブラウザーがサポートされていないことです。 Firefox と IE でのプレビューは次のとおりです:
ただし、-webkit- プレフィックスを付けた CSS グラデーションを使用して、Webkit 以外のブラウザで背景を削除できます (CSS3 はカンマで区切られた複数の背景画像をサポートしています):
.box-with-text { background-image: -webkit-linear-gradient(transparent, transparent),url(IMAGE URL); -webkit-text-fill-color: transparent; -webkit-background-clip: text;}
したがって、サポートされていないブラウザは背景全体を直接無視するため、背景画像が表示されることを回避でき、恥ずかしいことはありません。
このデモを Firefox または IE で表示すると、以下に示すように、結果は黒い背景に白いテキストが表示されます。
グラデーションを使用したこの簡単なトリックは、Webkit 以外のブラウザーで表示されない画像を修正するのに役立ちますが、この作業範囲では、この方法はテクスチャ付きテキストには適切な選択ではないと思います。
塗りつぶしをアニメーションさせたい場合、CSS 背景を使用するのは困難です。背景の位置や大きさを動かすだけでアニメーションを付けることはできますが、色が滑らかに変化することはありません。
デモ 3: グラデーションを使用して、背景画像の位置を移動してアニメーションを追加します
背景クリップ: テキストを使用するこの手法は、優れたクロスブラウザ ソリューションではなく、動的な塗りつぶしの可能性も限られています。
ブラウザのサポート: Chrome サポート、Firefox サポート、IE サポート、Safari サポート、Opera サポート。
SVG は優れた形式であり、幅広いブラウザーをサポートしています。 SVG を使用してパターン テキストを作成するには、次の 3 つの方法があります:
次は、塗りつぶしから始めて、これら 3 つのテクニックについて説明します
SVG に慣れていない場合は、 SVG 仕様、Sara Soueidan の記事、または WebPlatform.org の SVG チュートリアルを読むことをお勧めします。
以下では、SVG でテキストを作成します:
<svg viewBox="0 0 600 300"> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text" > Text </text></svg>
これは、選択してコピーできる非常に普通のテキストです。まず結果を見てみましょう:
SVG のテキストは、他の図形 (円、四角形など) と同じプロパティを持ちます。塗りつぶしやストロークのほか、単色、グラデーションやパターンなどの他の多くのプロパティを持つことができます。
単純なグラデーションのタグ:
<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>
グラデーションの作成の詳細については、Joni Trythall の記事: Getting Started with SVG Gradients を参照してください
元素的填充可以使用 fill 属性添加。当使用渐变或图案的时候,需要通过在 url() 中放置对应 id 来完成,如下:
<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中定义填充:
.text { fill: url(#gr-simple);}
我们可以在CSS中设置渐变的颜色,但是我们需要使用SMIL来获取对于渐变的其它属性的控制:
<!-- Gradient --><radialGradient id="gr-radial" cx="50%" cy="50%" r="70%"> <!-- Animation for radius of gradient --> <animate attributeName="r" values="0%;150%;100%;0%" dur="5s" repeatCount="indefinite" /> <!-- Animation for colors of stop-color --> <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) 一文。
现在我们来看看图案。SVG中的图案可以包含各种类型的SVG图形和图像。图案可以简单也可以非常复杂。SVG图案可以调整,而且不会失去锐度。
圆形图案的标签如下:
<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,因为Sass可以使用迭代:
$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:
.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图案的内容,可以查看MDN上的SVG教程中的 图案 这一节。
使用图案时,相对使用普通的SVG图形,在给元素添加动画方面有更少的选择。例如,图案中图形的变换,在Firefox中不能工作。但是我们可以让描边动起来,以获得类似缩放的效果。
下面的Demo我也是使用了Sass,但是在这里我不仅设置了颜色,还有 animation-delay 。这可以让星星依次动起来:
$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); } }}/* Change stroke-width within animation */@keyframes stroke { 50% { stroke-width: 10; }}
转换成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;}/* Change stroke-width within animation */@keyframes stroke { 50% { stroke-width: 10; }}
如果你看了这个Demo的代码,你会发现图形比预期的多。当我们增大描边的时候,有一些图形可能会被图案的边边切断。通过使用重复的形状,就可以解决这个问题啦。
实际上我们也可以使用动态GIF来进行填充。但是通常gif图是比较大的,但它们确实可以用来创建非常棒的效果:
要创建一个图像填充,我们可以使用图案 pattern 元素来完成。包含图像的图案的标签如下:
<pattern id="p-fire" viewBox="30 100 186 200" patternUnits="userSpaceOnUse" width="216" height="200" x="-70" y="35" > <image xlink:href="http://yoksel.github.io/about-svg/assets/img/parts/fire.gif" width="256" height="300"/></pattern>
和 background-clip: text 不同,这个文本在大多数现代浏览器中都是可以正确显示的。
现在来看看描边。对于HTML文本,我们可以使用 text-shadow 创建一个跨浏览器的描边,但是这种类型的描边有非常多的限制:
手工用CSS写这种类型的描边是非常繁琐而且无聊的,所以我在Sass中使用了一个小函数来完成。我们可以设置 color 和 width 为参数。尽管这个函数很方便,生成的代码也是相当多而且笨重的。
和在HTML中不同,SVG中所有元素都可以添加描边,包括文本。描边除了可以是纯色的,还可以是渐变和图案。
描边也可以是虚线,然后用另一种方式让它动起来:
对于这种类型的描边,我们需要复制很多份文本,用于应用多种颜色。完成这项繁琐工作的一个好方法是,使用 symbol :
<svg viewBox="0 0 600 300"> <!-- Symbol --> <symbol id="s-text"> <text text-anchor="middle" x="50%" y="50%" dy=".35em"> Text </text> </symbol> <!-- Duplicate symbols --> <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>
下面是我们控制颜色和动画的Sass代码:
$colors: #F2385A, #F5A503, #E9F1DF, #56D9CD, #3AA1BF;$max: length($colors);$dash: 70;$dash-gap: 10;$dash-space: $dash * ($max - 1) + $dash-gap * $max;$time: 6s;$time-step: $time/$max;.text { fill: none; stroke-width: 6; stroke-linejoin: round; stroke-dasharray: $dash $dash-space; stroke-dashoffset: 0; animation: stroke $time infinite linear; @for $item from 1 through $max { &:nth-child(#{$max}n + #{$item}){ $color: nth($colors, $item); stroke: $color; animation-delay: -($time-step * $item); } }}@keyframes stroke { 100% { stroke-dashoffset: -($dash + $dash-gap) * $max; }}
转换成CSS的结果:
.text { fill: none; stroke-width: 6; stroke-linejoin: round; stroke-dasharray: 70 330; stroke-dashoffset: 0; animation: stroke 6s infinite linear;}.text:nth-child(5n + 1) { stroke: #F2385A; animation-delay: -1.2s;}.text:nth-child(5n + 2) { stroke: #F5A503; animation-delay: -2.4s;}.text:nth-child(5n + 3) { stroke: #E9F1DF; animation-delay: -3.6s;}.text:nth-child(5n + 4) { stroke: #56D9CD; animation-delay: -4.8s;}.text:nth-child(5n + 5) { stroke: #3AA1BF; animation-delay: -6s;}@keyframes stroke { 100% { stroke-dashoffset: -400; }}
对于每一个 symbol ,我们都单独设置了一个动画延迟,所以描边的部分不会在一个地方积聚,而是沿着字母的轮廓传播。
使用这种方法,文本可以使用CSS定义样式。我们也可以选中和复制文本。另一个很大的优点是SVG确实有非常棒的浏览器支持。所以要创建这些类型的填充,SVG是最好的候选之一。
使用SVG的一个缺点是处理文本的能力限制。例如,一般文本中的单词不会在文档边界的地方中断,我们可以使用一些技巧来获取换行符。但是在这里文本可能会在单词中间就中断,所以这种方法更适合于短文本和logo。
浏览器支持:Chrome支持,Firefox支持,IE支持,Safari支持,Opera支持。
SVG中有两种类型的蒙版。CSS中也有可以应用于HTML元素的蒙版,但是 浏览器支持一般般 ,所以我们来看看SVG mask吧。
SVG mask也可以应用于HTML元素,但是目前该功能只适用于Firefox。应用于SVG元素的SVG mask则可以在所有现代浏览器中工作。而且 clippath 和 mask 都可以包含文本。
mask 和 clip-path 之间有什么区别呢?
使用 clippath 的例子,标签如下:
<clippath id="cp-text"> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text--line"> Text </text></clippath>
这是应用了裁剪路径的图形组的标签:
<g clip-path="url(#cp-text)"> <circle r="70%" cx="300" cy="150" class="c-fill--color"/> <circle r="70%" cx="300" cy="150" class="c-fill"/></g>
根据你要做的,这个图形可以替换为其它任何的图形。在这个demo中我使用了两个 circle 元素,第二个使用图案填充,第一个(在第二个后面)使用纯色填充。需要隐藏第二个图形里图案之间的细线。简单的情况下使用一个图形也已经够了。
mask 中可以包含 symbol 的内容。当我们需要复制多份文本时,这对于应用了丰富效果的文本来说非常方便。
<symbol id="s-text"> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text" > Text </text></symbol><!--Mask--><mask id="m-text" maskunits="userSpaceOnUse" maskcontentunits="userSpaceOnUse"> <use xlink:href="#s-text" class="text-mask" ></use></mask>
用于组合的标签是相同的,但是蒙版使用 mask 属性应用:
<g mask="url(#m-text)"> ...</g>
mask 和 clippath 中的文本都可以添加样式。例如,我们可以改变 font-family 和 font-size 。但是文本不可选中。
这个问题可以通过从 mask / clippath 中复制文本来解决,把它放在被添加蒙版的元素之上,然后设置 fill: transparent 去掉它的填充。这样我们得到一个透明的可以选中和复制的文本。
复制文本的最好方法是使用 symbol 。但是 symbol 在 clippath 中不支持,但是如果你使用的是 mask ,你可以使用一个 symbol 作为 mask ,然后一个作为透明文本。
symbol 的副本必须放在带 mask 或 clip-path 的元素之下。
尝试在下面的demo中选中和复制文本:
有一点很重要,因为 fill:none 不工作,但 fill: transparent 可以。还有,带有描边但是没有填充的图形可以完成相同的效果。文本也是可选中的。
这种技术的巨大优点是各种各样的添加动态填充的可能性。你可以使用任何SVG元素的组合,然后用很多不同的方法给它们添加动画。在这种情况下,可以使用变换,填充和描边来添加动画。
现在我们有一组带 clip-path 的添加了动画的内容,包含图案描边动画:
下面的这个Demo展示了一组使用 clip-path 裁剪的动画图形:
还有很多方法可以填充文本。在SVG中使用HTML是可能的,通过使用 foreignObject 元素,所以给HTML元素应用SVG mask / clippath 是可能的,还可以添加CSS效果和动画,甚至视频。虽然这种技术也有一些限制。例如,Chrome中播放视频会忽略蒙版。所以我们现在不能使用它,尽管它真的非常有趣。但是我们还有其它方法可选。
相比SVG文本,这种技术有更多添加动画的可能性。
浏览器支持:Chrome实验模式下支持,Firefox支持,IE不支持,Safari支持,Opera实验模式下支持。
注意:要查看这一节中的demo,你需要使用Firefox或Safari,或者Chrome中激活了试验性web平台的flag→打开 chrome://flags/#enable-experimental-web-platform-features (需要重启Chrome)。要在Opera中查看demo,同样需要激活→ opera://flags/#enable-experimental-web-platform-features ,然后重启浏览器。
这种使用图案文本的方法是实验性的,并不能在所有浏览器中都工作,但是确实非常有趣,因为我们可以使用任何东西作为文本的填充。目前,浏览器支持并不是非常好。
如果你对于blend mode不熟悉,推荐这篇文章: Getting to Know CSS Blend Modes 。
有关于Blend Mode更多的教程,可以点击这里。
它的工作原理:不同的(混合模式)blend mode根据它们应用的图层的颜色而不同地工作。例如, lighten 模式只显示内容中亮的内容,而暗的内容会消失。另一个方面, darken 模式则会选择暗的内容,然后亮的内容会显示。这允许我们创建一个具有复杂形状的透明内容的HTML图层,即使常规形状的文本也可以改变。
下面是简化版本的标签:
<div class="box-with-text"> <div class="text">Text</div></div>
这是CSS:
.box-with-text { background: url(IMAGE URL) 50% 70% / cover; } .text { background: black; color: white; mix-blend-mode: darken; }
所有的这些魔法效果都包含在 mix-blend-mode: darken 这一行中。通过这一行混合模式的定义,所有白色的内容都会变成完全透明,我们可以看到其父元素的背景。
这种技术的缺点是我们不可以裁剪文本周围的内哦让。这种方法不允许我们把图案文本放在另一层带有填充的文本之上(但是可以使用SVG蒙版完成)。事实上,这只是一个有孔的图层,通过它我们可以看到下一层的元素。但是在这个图层之下,我们可以放置任何我们能想象到的任何东西,例如,CSS动画效果,甚至视频。
有一个问题,出现在文本块周围的细线,特别是在Firefox中。这可以通过伪元素解决,给伪元素设置一个和背景想听颜色的边框。
.box-with-text { background: url(IMAGE URL) 50% 70%/cover; /* Hack to hide thin transparent lines while resizing objects */}.box-with-text:after { content: ''; position: absolute; top: -2px; right: -2px; bottom: -2px; left: -2px; display: block; border: 4px solid black;}.text { background: black; color: white; mix-blend-mode: darken;}
这种方法的最主要缺点是缺少浏览器支持,所以目前这种技术还是更适合用户实验,而不是在真正的网站项目中。
浏览器支持情况:Chrome支持,Firefox支持,IE支持,Safari支持,Opera支持。
最后一种技术也是有一点点古怪的。它和前一个很相似,但是它有更好的浏览器支持,因为,它是SVG!
我把这种方法称为“反向遮罩”。它是使用SVG的 mask 来获取一个纯色填充的图层,以及一个文本形状的透明区域。然后,这个图层可以被放到任何的HTML元素上。
我们不会把包含内容的图层的额外部分裁剪(和我们前面使用 mask 和 clip-path 时一样)。相反,我们会把我们需要的图形挖空,放在纯色填充的图层上,和印刷类似。如下:
对于这种情况,SVG可以分为两个部分。第一个部分是不可见的,是一个包含文本和蒙版的 symbol 元素。
<svg viewBox="0 0 600 300" class="svg-defs"> <!-- Symbol with text --> <symbol id="s-text"> <text text-anchor="middle" x="50%" y="50%" dy=".35em" class="text"> Text </text> </symbol> <!-- Mask with text --> <mask id="m-text" maskunits="userSpaceOnUse" maskcontentunits="userSpaceOnUse"> <rect width="100%" height="100%" class="mask__shape"/> <use xlink:href="#s-text" class="mask__text"/> </mask></svg>
在简单的情况下,你不需要添加symbol,但是它可以让你的代码更有可读性。在比较复杂的情况下,它会帮你做一些有趣的效果。
在这种情况下,我们需要反转蒙版,这也是为什么我们需要设置图形为白色,来填充蒙版:
.mask__shape { fill: white;}
文本的颜色必须是黑色的,因为蒙版中的透明区域必须是文本的形状。
同时,我们还需要一个比较复杂的HTML结构:
<div class="box-with-text"> <!-- Content for text --> <div class="text-fill"></div> <!-- SVG to cover text fill --> <svg viewBox="0 0 600 300" class="svg-inverted-mask"> <!-- Big shape with hole in form of text --> <rect width="100%" height="100%" mask="url(#m-text)" class="shape--fill"/> <!-- Transparent copy of text to keep patterned text selectable --> <use xlink:href="#s-text" class="text--transparent"/> </svg></div>
最底层包含HTML元素,我们可以给它应用一个背景或者使用一些HTML内容进行填充。在简单的情况下,背景可以应用于父元素,但为了更多的灵活性,最好使用一个单独的元素。
下一层是包含填充和蒙版的SVG。这是一块文本形状透明区域的可见图层。在这个图层上面,我们放一个包含文本的 symbol ,以保持文本可访问性。
这种技术的缺点是,包含内容的图层不是被蒙版裁剪的。下面的图层可以通过上面图层的透明区域看到。我们不能把文本从背景上裁剪,然后把它放到其它图层上。
但是这种技术也是有一定优势的。第一个优点是HTML是放在SVG外边的,可以包含任何我们想要的东西:动画和媒体内容。
如果你想让文本的填充变成动画的话,是非常简单的。但是注意性能可能不太好:
你想要用视频来填充文本?没问题:
在这些Demo中,尺寸管理看起来可能有点复杂。如果你不想调整文本块的大小,你可能不需要那一块的代码了。
第二个优点是,和使用混合模式不同,带有蒙版的图层的填充,不会和下面的图层混合,所以它可以包含渐变和图案填充。
现在你已经了解了一些创建文本图案填充,包括动画填充的技巧了。即使有一些技术我们目前还不能用,我相信我们将来总可以用得上的。现在,我想是时间让你自己来实践,创建一些impressive的文本效果了~
下载文件中包含所有这篇教程中介绍到的技术(动画和非动画文本填充)。如果你想看看这篇文章中的demo,可以 点击这里下载文件 。
注意,你需要调整下载文件中的一些实例的图案路径,如:在style 11中我们使用了一个纹理作为描边,是这样引用的: stroke: url(URL/index11.html#p-spots) 。但是你需要设置正确的URL。
查看DEMO 下载源码
本文根据 @yoksel 的《 How to Create (Animated) Text Fills 》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处: http://tympanus.net/codrops/2015/02/16/create-animated-text-fills/ 。
現役の学生で、コンピューターサイエンスを専攻する学部生です。私は面白いです、フロントエンドが大好き、人生が大好き、CSS が好き、JavaScript が好き、SVG が好き、PS をプレイするのが大好き、AI をプレイするのが大好き、面白いソフトウェアが大好きです。一生懸命取り組み、積み重ねて進歩してください。