有没有办法使用SVG梯度作为位移图的输入?

时间:2019-09-18 13:52:53

标签: javascript svg svg-filters

我正在尝试生成一个渐变,该渐变可以用作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>

我希望能够在保持隐藏状态的同时使用生成的渐变使文本变形。非常感谢您的时间和帮助:)。

3 个答案:

答案 0 :(得分:3)

为了使其正常工作,您将需要为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.同样,您也不能执行以下操作: 或以下操作: ,但是您可以为文本指定字体-大小。

答案 1 :(得分:1)

  • 应用于文本的径向渐变。

.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>

  • 添加过滤器feTurbulencefeDisplacementMap

通过更改baseFrequencyscale过滤器属性的值,您可以获得有趣的效果

下面是一个带有渐变的文本变形动画的示例:

当您将鼠标悬停在文本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>

答案 2 :(得分:0)

从我使用Firefox的经验来看,位移图过滤器原语中唯一允许作为in2的输入是feturbulence元素的输出。因此,您必须使用feturbulence作为来源来创建渐变。对于从左到右的线性渐变,从颜色 r1,g1,b1 r2,g2,b2 并填充从0,0到{{ 1}},您必须创建 xn 100,100输出,其中 xn 可以是任何数字,但是越大,渐变将越平滑是。 每个 n:th feturbulence输出,然后必须使用feturbulence对其颜色通道进行如下更改:fecolormatrix,其中 c 是特定输出的通道值, c1 是通道的起始值,而 c2 是结束值。并且每个元素的高度必须设置为c = c1 * (1 - n/xn) + c2 * (n/xn),宽度必须设置为100 x 位置应设置为100/xn。然后使用n/xn*100将所有这些输出放到一个输出中,然后可以在femergenode中用作in2