Search code examples
htmlsvg-filterssvg-animate

How to animate feTurbulence to appear continuous


The feTurbulence filter is used to create clouds. By animating frequency value, generated clouds are zoomed in or out. I want them to slide from right to left. I've made so far:

<svg height="0" width="0" style=";position:absolute;margin-left: -100%;">
	<defs>
		<filter id="imagenconturbulencias" x="0" y="0" width="100%" height="100%">
			<feTurbulence result="cloud" baseFrequency=".2" seed="22" stitchTiles="nostitch" type="fractalNoise" numOctaves="3">
			<animate
				attributeName="baseFrequency"
				calcMode="spline"
				dur="5s"
				values=".2;.1;"
				repeatCount="indefinite"
			/>
			</feTurbulence>
			<feComposite operator="in" in="cloud" in2="SourceGraphic"/>
		</filter>
	</defs>
	<g stroke="none" stroke-width="4" id="rlog" fill="#eee"><path d="M34.2,13.9v19.5h-7.3V13.9H34.2z M30.5,5.2c1,0,1.8,0.3,2.6,1s1.1,1.5,1.1,2.5c0,1-0.3,1.8-1,2.5s-1.6,1-2.6,1c-1.1,0-1.9-0.3-2.6-1s-1-1.5-1-2.5c0-1,0.4-1.8,1.1-2.5S29.5,5.2,30.5,5.2z"/></g>
</svg>

<div id="a">
	<svg viewBox="0 0 230 280">
		<use filter="url(#imagenconturbulencias)" xlink:href="#rlog"></use>
	</svg>
</div>

If you look closely, after 5 seconds animation repeats itself, as should! but it does not look so pretty.

I know this filter is used to create realistic, cloud-like structures. How do we go about moving these clouds continuously ?

feTurbulence filter takes in parameters like randomSeed numberOfOctaves and baseFrequency.

In given example I've animated value of base frequency. Since there is no more attributes to animate.

How to make this animation to appear continuous? Do we use perlin noise generator combined with matrix and displacement maps on this turbulence generated thing and animate all together somehow? (just brainstorming..)

Any help, Ideas, approaches, snippets, sincerely appreciated.


this could be black&white for simplicity, but cloud animation still is not continious. Bonus snippet


Solution

  • Do not animate the base frequency. For a smooth effect use a 360 hueRotate and a colorMatrix (since hueRotate cycles back to the original value).

    <svg x="0px" y="0px" width="800px" height="500px" viewbox="0 0 800 500">
    
        <script type="text/ecmascript" xlink:href="http://www.codedread.com/lib/smil.user.js"/>
    
      <defs>
    <filter id="heavycloud" color-interpolation-filters="sRGB" x="0%" y="0%" height="100%" width="100%">
      <feTurbulence type="fractalNoise" result="cloudbase" baseFrequency=".0025" numOctaves="5" seed="24"/>
    
        <feColorMatrix in="cloudbase" type="hueRotate" values="0" result="cloud">
        <animate attributeName="values" from="0" to="360" dur="20s" repeatCount="indefinite"/>
      </feColorMatrix>
    
    
      <feColorMatrix in="cloud" result="wispy" type="matrix" 
                                   values="4 0 0 0 -1
                                           4 0 0 0 -1
                                           4 0 0 0 -1
                                           1 0 0 0 0   
                                           "/>
    
      <feFlood flood-color="#113388" result="blue"/>
    
      <feBlend mode="screen" in2="blue" in="wispy"/>
    
      <feGaussianBlur stdDeviation="4"/>
    
      <feComposite operator="in" in2="SourceGraphic"/>
    
    </filter>
      </defs>
      <text x="30" y="380" filter="url(#heavycloud)" font-size="400" font-family="arial" stroke-color="blue" font-weight="bold" kerning="-75" font-stretch="condensed">SVG!</text>
    
    
    </svg>