Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SVG: Is it possible to use random or non-static values?

I am animating a polygon shape all within an SVG (so it can be used as a background in CSS). I am curious if there is a way to randomly generate a value to use, or some other way so the animation does not always start at the same position each time it is loaded (without using an external SVG library and without using JavaScript)?

Here is the current SVG:

<polygon style="stroke:rgb(255,0,0);fill:transparent;" points="0,0 121.5,150 600,0 ">
    <animate attributeName="points" dur="24s" values="0,20 121.5,150 600,0; 0,100 571.5,150 306.5,0; 0,20 121.5,150 600,0" repeatCount="indefinite" keyTimes="0; 0.5; 1" calcMode="spline" keySplines=".5 0 .5 1; .5 0 .5 1" />
</polygon>
like image 345
gokujou Avatar asked Nov 04 '14 17:11

gokujou


People also ask

Can you use random in CSS?

Elements cannot act randomly in CSS because we have no random function to control them with, but elements can still appear to act randomly by using an intricate form of animation.

Does svgs support animation?

SVG supports the ability to change vector graphics over time, to create animated effects. SVG content can be animated in the following ways: Using SVG's animation elements [svg-animation]. SVG document fragments can describe time-based modifications to the document's elements.

Which of the following is a method of randomization in CSS?

random in sass is like randomly choosing the name of a main character in a story. it's only random when written. it doesn't change. In other words, as soon as the CSS is processed, randomization is over.


2 Answers

I am curious if there is a way to randomly generate a value to use, or some other way so the animation does not always start at the same position each time it is loaded (without using an external SVG library and without using JavaScript)?

Short answer: No

It is theoretically impossible to fulfill your condition without JS in SVG since there is no function for generating random numbers
Also in SVG there are no arrays where you could store the coordinates of polygons and call them for rendering in a random way.

But in SVG, you can create the illusion of random movement, for example, the letters of any word.
Letters in SVG are vector elements, so each letter has its own x and y coordinates
If you add for example the word Stackoverflow using the tag<text>

<text id="text1" x="200" y="500" font-size="90">Stackoverflow</text>

Then each letter of this word will have its own coordinates, changing which you can achieve the illusion of random movement of letters

Look at the code, the coordinates are written like an array. If you start the animation of coordinates, then the illusion of random movement of letters will be created.

In the example below, the animation will start after clicking

<style>
 #text1 {

fill:#D0FF00;
}
 
</style>
<svg id="svg1" width="70%" height="70%" viewBox="0 0 1000 1000" 
  xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
  xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMinYMin meet">
 
    <title>Animation of text x and y attributes</title> 
    

<defs>
<linearGradient id="grad"
    x1="0" y1="0" x2="0" y2="100%"
    gradientUnits="userSpaceOnUse">
        <stop offset="2%" stop-color="#151515" />
          <stop offset="70%" stop-color="yellowgreen" />
    </linearGradient>
</defs> 
 <rect width="100%" height="100%" fill="url(#grad)" />
<text  x="200 " y="500" 
font-size="90" fill="#d3d3d3" stroke-width="1" stroke="#d3d3d3">Stackoverflow</text> 
<text id="text1" x="200" y="500"
font-size="90">Stackoverflow</text> 

<animate xlink:href="#text1" 
      attributeName="x" 
      attributeType="XML"
    values="200 233 266 299 332 365 400 431 464 497 530 563 596;
    100 600 200 365 700 465 465 563 530 398 431 850 900; 
    200 500 900 950 150 531 300 620 150 266 365 650 900;
    332 233 820 300 800 633 200 670 300 850 800 530 266;
    464 900 900 900 820 670 430 900 530 600 233 365 100;
    332 100 100 100 500 100 800 563 900 700 900 100 100;
    200 233 266 299 332 365 400 431 464 497 530 563 596"
    dur="4s"
    begin="svg1.click"
    repeatCount="2" />
<animate xlink:href="#text1"
      attributeName="y" 
      attributeType="XML"
    values="500 500 500 500 500 500 500 500 500 500 500 500 500;
    100 200 850 100 250 175 750 100 750 720 850 500 50; 
    100 600 600 250 200 450 50 200 520 550 300 300 750;
    500 100 650 650 600 150 550 50 150 550 200 550 400; 
    800 300 100 750 150 650 75 350 550 700 755 120 800;
    800 600 300 150 750 350 700 650 200 250 500 650 100;
    500 500 500 500 500 500 500 500 500 500 500 500 500"
        dur="3s"
      begin="svg1.click"
        repeatCount="2" />
</svg>

One more example

<style>
 #text1 {

fill:yellow;
}
 
</style>
<svg id="svg1" width="70%" height="70%" viewBox="0 0 1000 1000" 
  xmlns="http://www.w3.org/2000/svg" version="1.1" baseProfile="tiny"
  xmlns:xlink="http://www.w3.org/1999/xlink" preserveAspectRatio="xMinYMin meet">

<defs>
<linearGradient id="grad"
    x1="0" y1="0" x2="0" y2="100%"
    gradientUnits="userSpaceOnUse">
        <stop offset="2%" stop-color="black" />
        <stop offset="75%" stop-color="red" />
    </linearGradient>
</defs> 
 <rect width="100%" height="100%" fill="url(#grad)" />
<text  x="200 " y="500" 
font-size="90" fill="#E4E4E4" stroke-width="1" stroke="#E4E4E4">Stackoverflow</text> 
<text id="text1" x="200" y="500"
font-size="90">Stackoverflow</text> 

<animate xlink:href="#text1" 
    attributeName="x" 
    attributeType="XML"
        values="200 233 266 299 332 365 400 431 464 497 530 563 596;
    100 600 200 365 700 465 465 563 530 398 431 850 900; 
    200 500 900 950 150 531 300 620 150 266 365 650 900;
    332 233 820 300 800 633 200 670 300 850 800 530 266;
    464 900 900 900 820 670 430 900 530 600 233 365 100;
    332 100 100 100 500 100 800 563 900 700 900 100 100;
    200 233 266 299 332 365 400 431 464 497 530 563 596"
    dur="3s"
    begin="svg1.click"
    repeatCount="2" />
<animate xlink:href="#text1"
    attributeName="y" 
    attributeType="XML"
        values="500 500 500 500 500 500 500 500 500 500 500 500 500;
    100 200 850 100 250 175 750 100 750 720 850 500 50; 
    100 600 600 250 200 450 50 200 520 550 300 300 750;
    500 100 650 650 600 150 550 50 150 550 200 550 400; 
    800 300 100 750 150 650 75 350 550 700 755 120 800;
    800 600 300 150 750 350 700 650 200 250 500 650 100;
    500 500 500 500 500 500 500 500 500 500 500 500 500"
    dur="4s"
    begin="svg1.click"
    repeatCount="2" />


</svg>

Example with animation of billiard balls

<circle cx="50%" cy="20%" r="3%" fill="url(#gradB)" >

 <animate attributeName="cx" dur="3" values="3%;97%;3%"  
   repeatCount="indefinite" /> 
 <animate attributeName="cy" dur="2.8" values="3%;97%;3%"  
   repeatCount="indefinite" />
</circle>

Here, the illusion of random bouncing balls is achieved by changing the coordinates as a percentage of each other. In addition, different animation times are set for each ball.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg"  
xmlns:xlink="http://www.w3.org/1999/xlink" height="100vh" viewBox="0 0 400 400">

<rect width="100%" height="100%" rx="25"  fill="green" stroke="#9D8500" stroke-width="15"/>
<circle cx="50%" cy="20%" r="3%" fill="url(#gradB)" >

 <animate attributeName="cx" dur="3" values="3%;97%;3%"  
   repeatCount="indefinite" /> 
 <animate attributeName="cy" dur="2.8" values="3%;97%;3%"  
   repeatCount="indefinite" />
</circle>

<circle cx="30%" cy="70%" r="3%" fill="url(#gradR)" >

 <animate attributeName="cx" dur="2.7" values="97%;3%;97%"  
   repeatCount="indefinite" /> 
 <animate attributeName="cy" dur="3.1" values="3%;97%;3%"  
   repeatCount="indefinite" />
</circle>

 <radialGradient id="gradB" cx="20%" cy="20%" r="100%" fx="30%" fy="30%">
   <stop stop-color="white" offset="0"/>
   <stop stop-color="blue" offset="25%"/>
   <stop stop-color="rgb(0,0,192)" offset="50%"/>
   <stop stop-color="rgb(0,0,127)" offset="70%"/>
   <stop stop-color="rgb(0,0,64)" offset="85%"/>
   <stop stop-color="rgb(0,0,0)" offset="100%"/>
 </radialGradient>

 <radialGradient id="gradR" cx="20%" cy="20%" r="100%" fx="30%" fy="30%">
   <stop stop-color="white" offset="0"/>
   <stop stop-color="red" offset="25%"/>
   <stop stop-color="rgb(192,0,0)" offset="50%"/>
   <stop stop-color="rgb(127,0,0)" offset="70%"/>
   <stop stop-color="rgb(64,0,0)" offset="85%"/>
   <stop stop-color="rgb(0,0,0)" offset="100%"/>
 </radialGradient>

</svg>
like image 118
Alexandr_TT Avatar answered Oct 05 '22 15:10

Alexandr_TT


You may add a negative begin to the animation. The value used may be random.

In the next example I'm using the same polygon and the same animation. The only different thing is the value used for the begin

svg{border:solid;width:45%}
<svg viewBox="0 0 600 150">

  <polygon style="stroke:rgb(255,0,0);fill:transparent;" points="0,0 121.5,150 600,0 ">
    <animate attributeName="points" 
             dur="24s" 
             values="0,20 121.5,150 600,0; 
                     0,100 571.5,150 306.5,0; 
                     0,20 121.5,150 600,0" 
             repeatCount="indefinite" 
             keyTimes="0; 0.5; 1" 
             calcMode="spline" 
             keySplines=".5 0 .5 1; .5 0 .5 1"
             begin="-5s"/>
  </polygon>

  </svg>
<svg viewBox="0 0 600 150">

  <polygon style="stroke:rgb(255,0,0);fill:transparent;" points="0,0 121.5,150 600,0 ">
    <animate attributeName="points" 
             dur="24s" 
             values="0,20 121.5,150 600,0; 
                     0,100 571.5,150 306.5,0; 
                     0,20 121.5,150 600,0" 
             repeatCount="indefinite" 
             keyTimes="0; 0.5; 1" 
             calcMode="spline" 
             keySplines=".5 0 .5 1; .5 0 .5 1"
             begin="-15s"/>
  </polygon>

  </svg>
like image 37
enxaneta Avatar answered Oct 05 '22 16:10

enxaneta