有没有办法使用 SVG 渐变作为置换贴图的输入?
Is there a way to use a SVG gradient as input to a displacement map?
我正在尝试生成一个渐变,我可以将其用作 feDisplacementMap 来扭曲 SVG 中的文本。需要怎么设置?
我试过将它创建为 SVG 的一部分,并隐藏渐变,但我无法以这种方式工作。
<svg
filter="url(#f)"
overflow="auto"
viewBox="0,0,200vw,200vh"
width="100%"
height="100vh"
>
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
<filter id="f" primitiveUnits="objectBoundingBox">
<feImage result="pict2" xlink:href="#witness"></feImage>
<feDisplacementMap
scale=".05"
xChannelSelector="R"
yChannelSelector="R"
in2="pict2"
in="SourceGraphic"
></feDisplacementMap>
</filter>
<pattern id="imageFill" width="1" height="1" viewBox="0 0 300 300">
<image id="ripples" width="300" height="300" xlink:href="" />
</pattern>
</defs>
<text height="100vh" text-anchor="middle" class="svgText">
<tspan height="100vh" x="50%" y="50%">text</tspan>
</text>
<rect
id="witness"
width="100%"
height="100%"
stroke="none"
opacity="0"
fill="url(#rg)"
/>
</svg>
我希望能够使用生成的渐变扭曲文本,同时保持文本隐藏。非常感谢您的时间和帮助:)。
为了使其正常工作,您需要为 feImage
使用数据 uri。我正在使用你的渐变,但你使用的过滤器有一种小规模的方式。我正在使用 scale="15"
<svg width="300" height="300">
<defs>
<filter id="f" filterUnits="userSpaceOnUse" x="0" y="0" width="300" height="300">
<feImage xlink:href="data:image/svg+xml;utf8,%3Csvg width='300' height='300' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E %3CradialGradient id='rg' r='.7'%3E %3Cstop offset='0%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='10%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='20%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='30%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='40%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='50%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='60%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='70%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='80%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='90%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='100%25' stop-color='%23f00'%3E%3C/stop%3E% %3C/radialGradient%3E%3C/defs%3E%3Crect fill='url(%23rg)' width='300' height='300'%3E%3C/rect%3E%3C/svg%3E" result="pict2"/>
<feDisplacementMap scale="15" xChannelSelector="R" yChannelSelector="R" in2="pict2" in="SourceGraphic"/>
</filter>
</defs>
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" height="300" width="300" filter="url(#f)" />
</svg>
在你的代码中你也有几个错误:
1、viewBox
属性不能带单位。这不会做:viewBox="0,0,200vw,200vh"
2. 你也不能这样做: 或者这样: 但是你可以给你的文字一个字体大小。
- 应用于文本的径向渐变。
.container {
width:100%;
height:100%;
}
#txt1 {
font-size: 200px;
font-weight:bold;
font-family: 'Signika', sans-serif;
fill:url(#rg);
}
<div class="container">
<svg viewBox="0 0 750 300" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
</defs>
<text id="txt1" x="15%" y="75%" >Stack</text>
</svg>
</div>
- 添加过滤器
feTurbulence
和feDisplacementMap
通过更改 baseFrequency
和 scale
过滤器属性的值,您可以获得有趣的效果
下面是一个带有渐变的文本变形动画示例:
悬停文本时动画开始 begin =" txt1.mouseover "
动画结束 - end =" txt1.mouseout "
,或者在动画结束时 - dur =" 18s "
#txt1 {
font-size: 200px;
font-weight:bold;
font-family: 'Signika', sans-serif;
fill:url(#rg);
filter:url(#myFilter);
}
<div class="container">
<svg width="750" height="300" version="1.1"
viewBox="0 0 750 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" >
<animate attributeName="baseFrequency"
dur="18s"
values="0.0001;0.02;0.0001;0.02;0.0001"
begin="txt1.mouseover"
end="txt1.mouseout" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
</defs>
<text id="txt1" x="1%" y="50%" >Stack</text>
</div>
- 动画图像和文本失真的示例
.container {
width:75%;
height:75%;
}
#txt1 {
font-size: 100px;
font-weight:bold;
font-family: 'Signika', sans-serif;
fill:url(#rg);
filter:url(#myFilter);
pointer-events:none;
}
<div class="container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 300">
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" >
<animate attributeName="baseFrequency" dur="18s" values="0.0001;0.02;0.0001;0.02;0.0001" begin="img1.mouseover" end="img1.mouseout" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
</defs>
<image id="img1" xlink:href="https://i.stack.imgur.com/hHGO8.jpg" width="100%" height="100%" filter="url(#myFilter)" />
<text id="txt1" x="35%" y="35%" >Stack</text>
</svg>
</div>
根据我使用 Firefox 的经验,置换贴图过滤器基元中唯一允许作为 in2
的输入是 feturbulence
元素的输出。因此,您必须使用 feturbulence
作为源来创建渐变。对于从左到右的线性渐变,从颜色 r1, g1, b1 到 r2, g2, b2 并填充 space 从 0,0
到 100,100
,你必须创建 xn feturbulence
输出,其中 xn可以是任意数,但越大,梯度越平滑。
每个 n:th feturbulence
输出,然后必须使用 fecolormatrix
如下更改其颜色通道:c = c1 * (1 - n/xn) + c2 * (n/xn)
,其中 c是具体输出的通道值,c1是通道的起始值,c2是结束值价值。每个元素的高度必须设置为 100
,宽度设置为 100/xn
,x 位置设置为 n/xn*100
。然后使用 femergenode
将所有这些输出合并为一个输出,然后可以用作 fedisplacementmap
中的 in2
。
我正在尝试生成一个渐变,我可以将其用作 feDisplacementMap 来扭曲 SVG 中的文本。需要怎么设置?
我试过将它创建为 SVG 的一部分,并隐藏渐变,但我无法以这种方式工作。
<svg
filter="url(#f)"
overflow="auto"
viewBox="0,0,200vw,200vh"
width="100%"
height="100vh"
>
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
<filter id="f" primitiveUnits="objectBoundingBox">
<feImage result="pict2" xlink:href="#witness"></feImage>
<feDisplacementMap
scale=".05"
xChannelSelector="R"
yChannelSelector="R"
in2="pict2"
in="SourceGraphic"
></feDisplacementMap>
</filter>
<pattern id="imageFill" width="1" height="1" viewBox="0 0 300 300">
<image id="ripples" width="300" height="300" xlink:href="" />
</pattern>
</defs>
<text height="100vh" text-anchor="middle" class="svgText">
<tspan height="100vh" x="50%" y="50%">text</tspan>
</text>
<rect
id="witness"
width="100%"
height="100%"
stroke="none"
opacity="0"
fill="url(#rg)"
/>
</svg>
我希望能够使用生成的渐变扭曲文本,同时保持文本隐藏。非常感谢您的时间和帮助:)。
为了使其正常工作,您需要为 feImage
使用数据 uri。我正在使用你的渐变,但你使用的过滤器有一种小规模的方式。我正在使用 scale="15"
<svg width="300" height="300">
<defs>
<filter id="f" filterUnits="userSpaceOnUse" x="0" y="0" width="300" height="300">
<feImage xlink:href="data:image/svg+xml;utf8,%3Csvg width='300' height='300' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink'%3E%3Cdefs%3E %3CradialGradient id='rg' r='.7'%3E %3Cstop offset='0%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='10%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='20%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='30%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='40%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='50%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='60%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='70%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='80%25' stop-color='%23f00'%3E%3C/stop%3E%3Cstop offset='90%25' stop-color='%23000'%3E%3C/stop%3E%3Cstop offset='100%25' stop-color='%23f00'%3E%3C/stop%3E% %3C/radialGradient%3E%3C/defs%3E%3Crect fill='url(%23rg)' width='300' height='300'%3E%3C/rect%3E%3C/svg%3E" result="pict2"/>
<feDisplacementMap scale="15" xChannelSelector="R" yChannelSelector="R" in2="pict2" in="SourceGraphic"/>
</filter>
</defs>
<image xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/222579/beagle400.jpg" height="300" width="300" filter="url(#f)" />
</svg>
在你的代码中你也有几个错误:
1、viewBox
属性不能带单位。这不会做:viewBox="0,0,200vw,200vh"
2. 你也不能这样做:
- 应用于文本的径向渐变。
.container {
width:100%;
height:100%;
}
#txt1 {
font-size: 200px;
font-weight:bold;
font-family: 'Signika', sans-serif;
fill:url(#rg);
}
<div class="container">
<svg viewBox="0 0 750 300" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
</defs>
<text id="txt1" x="15%" y="75%" >Stack</text>
</svg>
</div>
- 添加过滤器
feTurbulence
和feDisplacementMap
通过更改 baseFrequency
和 scale
过滤器属性的值,您可以获得有趣的效果
下面是一个带有渐变的文本变形动画示例:
悬停文本时动画开始 begin =" txt1.mouseover "
动画结束 - end =" txt1.mouseout "
,或者在动画结束时 - dur =" 18s "
#txt1 {
font-size: 200px;
font-weight:bold;
font-family: 'Signika', sans-serif;
fill:url(#rg);
filter:url(#myFilter);
}
<div class="container">
<svg width="750" height="300" version="1.1"
viewBox="0 0 750 300" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" >
<animate attributeName="baseFrequency"
dur="18s"
values="0.0001;0.02;0.0001;0.02;0.0001"
begin="txt1.mouseover"
end="txt1.mouseout" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
</defs>
<text id="txt1" x="1%" y="50%" >Stack</text>
</div>
- 动画图像和文本失真的示例
.container {
width:75%;
height:75%;
}
#txt1 {
font-size: 100px;
font-weight:bold;
font-family: 'Signika', sans-serif;
fill:url(#rg);
filter:url(#myFilter);
pointer-events:none;
}
<div class="container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 500 300">
<defs>
<radialGradient id="rg" r=".9">
<stop offset="0%" stop-color="#f00"></stop>
<stop offset="10%" stop-color="#000"></stop>
<stop offset="20%" stop-color="#f00"></stop>
<stop offset="30%" stop-color="#000"></stop>
<stop offset="40%" stop-color="#f00"></stop>
<stop offset="50%" stop-color="#000"></stop>
<stop offset="60%" stop-color="#f00"></stop>
<stop offset="70%" stop-color="#000"></stop>
<stop offset="80%" stop-color="#f00"></stop>
<stop offset="90%" stop-color="#000"></stop>
<stop offset="100%" stop-color="#f00"></stop>
</radialGradient>
<filter id="myFilter" >
<feTurbulence type="turbulence" baseFrequency="0.0001" numOctaves="1" result="turbulence" >
<animate attributeName="baseFrequency" dur="18s" values="0.0001;0.02;0.0001;0.02;0.0001" begin="img1.mouseover" end="img1.mouseout" />
</feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="25" in="SourceGraphic" in2="turbulence" />
</filter>
</defs>
<image id="img1" xlink:href="https://i.stack.imgur.com/hHGO8.jpg" width="100%" height="100%" filter="url(#myFilter)" />
<text id="txt1" x="35%" y="35%" >Stack</text>
</svg>
</div>
根据我使用 Firefox 的经验,置换贴图过滤器基元中唯一允许作为 in2
的输入是 feturbulence
元素的输出。因此,您必须使用 feturbulence
作为源来创建渐变。对于从左到右的线性渐变,从颜色 r1, g1, b1 到 r2, g2, b2 并填充 space 从 0,0
到 100,100
,你必须创建 xn feturbulence
输出,其中 xn可以是任意数,但越大,梯度越平滑。
每个 n:th feturbulence
输出,然后必须使用 fecolormatrix
如下更改其颜色通道:c = c1 * (1 - n/xn) + c2 * (n/xn)
,其中 c是具体输出的通道值,c1是通道的起始值,c2是结束值价值。每个元素的高度必须设置为 100
,宽度设置为 100/xn
,x 位置设置为 n/xn*100
。然后使用 femergenode
将所有这些输出合并为一个输出,然后可以用作 fedisplacementmap
中的 in2
。