Smooth animate for svg fill - javascript

I have an SVG thermometer and I'm trying to animate filling it smoothly for each class.
I did thermometer with toggle classes. I'm trying to animate smoothly up-down, and down-up animation for each class I have.
https://lore1ei.github.io/ -thermometer.
var firstStop = document.getElementById('F1gst1');
percentage = '0%';
firstStop.setAttribute('offset', percentage);
var CountAllCheckboxes = $('.analysis-li').length;
var CountChecked = 0;
$(".analysis-li").click(function() {
$(this).toggleClass("check");
CountChecked = $('.analysis-li.check').length;
percentage = ((CountChecked / CountAllCheckboxes) * 100) + '%';
firstStop.setAttribute('offset', percentage);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js"></script>
<svg class="thermometr" id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44.3 333.8">
<linearGradient y2="0%" x2="0%" y1="100%" x1="0%" id="F1g">
<stop stop-color="#00FF00" offset="0%" id="F1gst1"/>
<stop stop-color="#FFFFFF" offset="0%" id="F1gst2"/>
</linearGradient>
<path fill="url(#F1g)" class="st0" d="M30.5 297.5V4.6c0-2.5-2.1-4.6-4.6-4.6-2.5 0-4.6 2.1-4.6 4.6v292.9c-7.9 2-13.8 9.2-13.8 17.8 0 10.2 8.2 18.4 18.4 18.4s18.4-8.2 18.4-18.4c0-8.5-5.9-15.7-13.8-17.8"/>
<path fill="url(#F1g)" class="st0" d="M9 290.2h7.5v.5H9zM9 284.3h7.5v.6H9zM9 278.4h7.5v.5H9zM9 272.5h7.5v.6H9zM0 266.6h16.5v.6H0zM9 260.7h7.5v.5H9zM9 254.8h7.5v.6H9zM9 248.9h7.5v.5H9zM9 243h7.5v.6H9zM0 237.1h16.5v.6H0zM9 231.3h7.5v.5H9zM9 225.4h7.5v.6H9zM9 219.5h7.5v.6H9zM9 213.6h7.5v.6H9zM0 207.7h16.5v.6H0zM9 201.8h7.5v.6H9zM9 195.9h7.5v.6H9zM9 190h7.5v.6H9zM9 184.1h7.5v.5H9zM0 178.2h16.5v.6H0zM9 172.3h7.5v.6H9zM9 166.4h7.5v.5H9zM9 160.5h7.5v.6H9zM9 154.7h7.5v.6H9zM0 148.8h16.5v.6H0zM9 142.9h7.5v.6H9zM9 137h7.5v.5H9zM9 131.1h7.5v.5H9zM9 125.2h7.5v.6H9zM0 119.3h16.5v.5H0zM9 113.4h7.5v.6H9zM9 107.5h7.5v.6H9zM9 101.6h7.5v.5H9zM9 95.7h7.5v.6H9zM0 89.8h16.5v.6H0zM9 83.9h7.5v.6H9zM9 78.1h7.5v.6H9zM9 72.2h7.5v.6H9zM9 66.3h7.5v.6H9zM0 60.4h16.5v.6H0zM9 54.8h7.5v.6H9zM9 48.9h7.5v.6H9zM9 43h7.5v.5H9zM9 37.1h7.5v.6H9zM0 31.2h16.5v.5H0zM9 26h7.5v.6H9zM9 20.1h7.5v.5H9zM9 14.2h7.5v.6H9zM9 8.3h7.5v.6H9zM0 2.4h16.5V3H0z"/>
</svg>

One solution is to animate it using javascript only instead of using css and/or svg-props. For example:
function anim(fromPercentage) {
var topLimit = 25;
fromPercentage += 1;
if(fromPercentage < topLimit) {
$('#F1gst1').attr('offset', fromPercentage + '%');
setTimeout( function() {
anim(fromPercentage);
}, 35);
}
};
/*
* Animates the bar from 10 to 25 percentage.
* Change the topLimit inside the anim-function to the current desired top level.
* Also tweek the timeout to get smoother transition.
*/
anim(10);

#Thomas But i need this for ((CountChecked / CountAllCheckboxes) * 100) + '%'. It will be so many mask and functions.
it's one mask and one function, here a quick snippet:
const scale = Array.from(Array(101), (_,i,a) => 90*(100-i)/100);
document.querySelector("svg #scale").setAttributeNS(null, "d", scale.filter((v,i) => i && i<100 && i%10 === 0).map(v => `M20,${v},25,${v}`).join(""));
setInterval(function(){
let percent = Math.floor(Math.random() * 100);
document.querySelector("div").textContent = percent + "%";
document.querySelector("svg #red").style.setProperty("transform", `translateY(${scale[percent]}px)`)
}, 1000);
svg {
max-width: 100px;
max-height: 200px;
}
svg #red {
transition: transform 300ms;
}
<div></div>
<svg viewbox="0,0,50,100">
<mask id="myMask">
<line x1=25 y1=5 x2=25 y2=80 stroke="white" stroke-width="10" stroke-linecap="round" />
<circle cx=25 cy=90 r=10 fill="white" />
</mask>
<g mask="url(#myMask)">
<rect x=0 y=0 width=50 height=100 fill="#AAA" />
<rect id="red" x=0 y=0 width=50 height=100 fill="red" />
<path id="scale" stroke="#888" stroke-width="0.5" d=""/>
</g>
</svg>

<linearGradient y2="0%" x2="0%" y1="100%" x1="0%" id="F1g">
<stop stop-color="#00FF00" offset="0%" id="F1gst1">
<animate id="g0" attributeName="offset" to="5%" dur="0.5s" begin="indefinite" />
<animate id="g1" attributeName="offset" to="19.285714285714285%" dur="0.5s" begin="indefinite" />
<animate id="g2" attributeName="offset" to="33.57142857142857%" dur="0.5s" begin="indefinite" />
<animate id="g3" attributeName="offset" to="47.857142857142854%" dur="0.5s" begin="indefinite" />
<animate id="g4" attributeName="offset" to="62.14285714285714%" dur="0.5s" begin="indefinite" />
<animate id="g5" attributeName="offset" to="76.42857142857143%" dur="0.5s" begin="indefinite" />
<animate id="g6" attributeName="offset" to="90.71428571428571%" dur="0.5s" begin="indefinite" />
<animate id="g7" attributeName="offset" to="105%" dur="0.5s" begin="indefinite" />
</stop>
<stop stop-color="#FFFFFF" offset="0%" id="F1gst2"/></linearGradient>
<path fill="url(#F1g)" class="st0" d="M30.5 297.5V4.6c0-2.5-2.1-4.6-4.6-4.6-2.5 0-4.6 2.1-4.6 4.6v292.9c-7.9 2-13.8 9.2-13.8 17.8 0 10.2 8.2 18.4 18.4 18.4s18.4-8.2 18.4-18.4c0-8.5-5.9-15.7-13.8-17.8"/><path fill="url(#F1g)" class="st0" d="M9 290.2h7.5v.5H9zM9 284.3h7.5v.6H9zM9 278.4h7.5v.5H9zM9 272.5h7.5v.6H9zM0 266.6h16.5v.6H0zM9 260.7h7.5v.5H9zM9 254.8h7.5v.6H9zM9 248.9h7.5v.5H9zM9 243h7.5v.6H9zM0 237.1h16.5v.6H0zM9 231.3h7.5v.5H9zM9 225.4h7.5v.6H9zM9 219.5h7.5v.6H9zM9 213.6h7.5v.6H9zM0 207.7h16.5v.6H0zM9 201.8h7.5v.6H9zM9 195.9h7.5v.6H9zM9 190h7.5v.6H9zM9 184.1h7.5v.5H9zM0 178.2h16.5v.6H0zM9 172.3h7.5v.6H9zM9 166.4h7.5v.5H9zM9 160.5h7.5v.6H9zM9 154.7h7.5v.6H9zM0 148.8h16.5v.6H0zM9 142.9h7.5v.6H9zM9 137h7.5v.5H9zM9 131.1h7.5v.5H9zM9 125.2h7.5v.6H9zM0 119.3h16.5v.5H0zM9 113.4h7.5v.6H9zM9 107.5h7.5v.6H9zM9 101.6h7.5v.5H9zM9 95.7h7.5v.6H9zM0 89.8h16.5v.6H0zM9 83.9h7.5v.6H9zM9 78.1h7.5v.6H9zM9 72.2h7.5v.6H9zM9 66.3h7.5v.6H9zM0 60.4h16.5v.6H0zM9 54.8h7.5v.6H9zM9 48.9h7.5v.6H9zM9 43h7.5v.5H9zM9 37.1h7.5v.6H9zM0 31.2h16.5v.5H0zM9 26h7.5v.6H9zM9 20.1h7.5v.5H9zM9 14.2h7.5v.6H9zM9 8.3h7.5v.6H9zM0 2.4h16.5V3H0z"/></svg>
This is solution from my friend.
var firstStop = document.getElementById('F1gst1');
percentage = '5%'; firstStop.setAttribute('offset',percentage);
var CountAllCheckboxes = $('.analysis-li').length;
var CountChecked = 0;
$(".analysis-li").click(function(){
$(this).toggleClass("check");
CountChecked = $('.analysis-li.check').length;
percentage = ((CountChecked / CountAllCheckboxes) * 100 + 5)+'%';
$('#g'+CountChecked)[0].beginElement();
setTimeout("firstStop.setAttribute('offset',percentage)", 450);
});

Related

CSS3 - Animate SVG if visible in viewport (Page Scroll)

I have been pulling my hair out trying to get this to work. Such a challenge.
The goal is to start the css animation when the object is visible, when it scrolls into view, and not before.
Using Javascript from here.
To make things easy, I have a code pen: https://codepen.io/studiotwofold/pen/dyYJWrV
Any ideas on how to fix this?
HTML:
<div class="icon-container" style="width:100px;">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 44 44" style="enable-background:new 0 0 44 44;" xml:space="preserve">
<defs>
<linearGradient id="icon-gradient" gradientUnits="userSpaceOnUse">
<stop offset="0%" style="stop-color:#E21C79"/>
<stop offset="100%" style="stop-color:#FC4C02"/>
</linearGradient>
</defs>
<g class="stf-icon">
<line x1="26" y1="29" x2="32" y2="29"/>
<path d="M29,25h-3l-0.2-0.5c-0.5-1.6-1.5-3.1-2.7-4.4l0,0c-3.3-3.3-3.2-8.8,0.3-12l0,0c3.2-2.9,8-2.9,11.2,0l0,0
c3.5,3.2,3.6,8.6,0.3,12l0,0c-1.2,1.2-2.2,2.7-2.7,4.4L32,25"/>
<line x1="29" y1="3" x2="29" y2="1"/>
<line x1="19.8" y1="7.3" x2="18.3" y2="6"/>
<line x1="23.9" y1="4.1" x2="23.1" y2="2.3"/>
<line x1="40.4" y1="11.3" x2="42.3" y2="10.7"/>
<line x1="38.1" y1="7" x2="39.6" y2="5.7"/>
<line x1="34" y1="3.8" x2="34.8" y2="2"/>
<path d="M17,13H3c-1.1,0-2,0.9-2,2v22c0,1.1,0.9,2,2,2h18l7,4v-4h7c1.1,0,2-0.9,2-2V24"/>
<line x1="5" y1="21" x2="11" y2="21"/>
<line x1="14" y1="21" x2="18" y2="21"/>
<line x1="5" y1="25" x2="13" y2="25"/>
<line x1="16" y1="25" x2="21" y2="25"/>
<line x1="5" y1="29" x2="8" y2="29"/>
<line x1="11" y1="29" x2="23" y2="29"/>
<line x1="5" y1="33" x2="13" y2="33"/>
<line x1="16" y1="33" x2="21" y2="33"/>
<polyline points="30.2,10 27,16 31,15 28.6,21 "/>
</g>
</svg>
</div>
CSS:
.stf-icon{fill:none;stroke: url(#icon-gradient);stroke-width:1;stroke-linecap:round;stroke-miterlimit:10;}
.animated-icon {
stroke-dasharray: 110;
stroke-dashoffset: 110;
animation: icon-animation 6s linear forwards;
animation-fill-mode: forwards;
}
#keyframes icon-animation {
from {stroke-dashoffset: 110;}
to {stroke-dashoffset: 0;}
}
Jquery:
var $fade = $(".stf-icon"); //Calling the class in HTML
$(window).scroll(function () { //Using the scroll global variable
$fade.each(function () {
fadeMiddle = $(this).offset().top + (0.4 *$(this).height());
windowBottom = $(window).scrollTop() + $(window).height();
if (fadeMiddle < windowBottom) {
$(this).addClass("animated-icon"); //add the animated icon class
}
});
});
/* On Load: Trigger Scroll Once*/
$(window).scroll();
To make things easy, I have a code pen: https://codepen.io/studiotwofold/pen/dyYJWrV
EDIT
Can this be done with straight javascript?
var wrapper = document.querySelector('.icon-container');
window.onscroll = function (event) {
if (wrapper.getBoundingClientRect().top < 0) {
wrapper.className = "icon-container animated-icon";
window.onscroll = null;
}
}

Formula to calculate gauge value to draw path for gauge svg

This is my gauge, but I don't know a formula to render value of this gauge. Somebody can help me with this?
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="145" viewBox="0 0 200 145">
<defs>
<linearGradient id="b" x1="5.165%" y1="76.151%" y2="75.039%">
<stop offset="0%" stop-color="#E9F1FF"/>
<stop offset="100%" stop-color="#DBE7FF"/>
</linearGradient>
<linearGradient id="c" x1="63.192%" x2="36.891%" y1="13.157%" y2="100%">
<stop offset="0%" stop-color="#FF8600"/>
<stop offset="100%" stop-color="#FFC86A"/>
</linearGradient>
<path id="a" d="M100 0c55.228 0 100 44.772 100 100 0 15.954-3.736 31.036-10.382 44.418l-17.912-8.906c5.31-10.7 8.294-22.757 8.294-35.512 0-44.183-35.817-80-80-80s-80 35.817-80 80c0 12.843 3.027 24.98 8.405 35.735l-17.912 8.906C3.778 131.204 0 116.043 0 100 0 44.772 44.772 0 100 0z"/>
</defs>
<g fill="none" fill-rule="evenodd">
<mask id="c" fill="#fff">
<use xlink:href="#a"/>
</mask>
<use fill="url(#b)" xlink:href="#a"/>
<g stroke="#FFF" stroke-width="5" mask="url(#c)" opacity=".3">
<path d="M99.5 97V0M100.252 97.061L110.392.593M100.16 97.06l21.821-94.513M100.885 97.276l31.58-91.715M100.8 97.241l42.523-87.183M101.465 97.6l51.402-82.26M101.399 97.536l61.044-75.383M101.976 98.025l68.589-68.59M102.463 98.6l75.383-61.043M102.4 98.536l82.26-51.403M102.759 99.199l87.183-42.522M102.725 99.115l91.715-31.58M102.94 99.839l94.513-21.82M102.939 99.747l96.468-10.139M103 100.5h97M102.939 101.253l96.469 10.139M102.94 101.16l94.513 21.821M102.724 101.884l91.715 31.58M102.759 101.8l87.183 42.523M102.399 102.465l82.26 51.402M102.464 102.4l75.383 61.044M101.974 102.975l68.59 68.59M101.4 103.464l61.044 75.383M101.464 103.4l51.402 82.26M100.801 103.76l42.522 87.182M100.884 103.724l31.58 91.716M100.161 103.94l21.82 94.513M100.253 103.939l10.139 96.468M99.5 104v97M98.747 103.939l-10.139 96.468M98.839 103.94l-21.82 94.513M98.116 103.724l-31.58 91.716M98.199 103.76l-42.522 87.182M97.536 103.4l-51.402 82.26M97.6 103.464l-61.044 75.383M97.026 102.975l-68.59 68.59M96.536 102.4l-75.383 61.044M96.601 102.465l-82.26 51.402M96.241 101.8L9.058 144.324M96.276 101.884l-91.715 31.58M96.06 101.16L1.548 122.982M96.061 101.253L-.408 111.392M96 100.5H-1M96.061 99.747L-.407 89.608M96.06 99.839L1.548 78.019M96.275 99.115L4.56 67.535M96.241 99.199L9.058 56.677M96.6 98.536L14.34 47.133M96.537 98.6L21.154 37.558M97.024 98.025l-68.589-68.59M97.601 97.536L36.557 22.153M97.535 97.6L46.133 15.34M98.2 97.241L55.676 10.058M98.115 97.276L66.535 5.56M98.84 97.06L77.018 2.548M98.748 97.061L88.608.593"/>
</g>
</g>
<path fill="none" fill-rule="evenodd" stroke="url(#c)" stroke-width="20" d="M72.705 14.214C36.343 25.773 10 59.81 10 100c0 14.45 3.405 28.105 9.457 40.205"/>
</svg>
As #enxaneta pointed out, you should better use strokes.
To display percentage based value segments on your gauge you will foremost need these attributes:
stroke-dasharray: defines the length of segement
stroke-dashoffset: gives you the ability to move your segment
pathlength: changes the computation values ration applied on the stroke-dash attributes
pathlength="100" show 25/100 – useful, if you're working with percentages (e.g. retrieved by some api)
pathlength="100"
stroke-dashoffset="0"
stroke-dasharray="25 100"
pathlength="12" show 3/12 – really handy if you get 'stepped' integer values
pathlength="12"
stroke-dashoffset="0"
stroke-dasharray="3 12"
MDN: pathLength
Here is a rebuild of you gauge using strokes:
svg{
border:1px solid #ccc;
width:33%
}
.gauge-segment{
transition: 0.3s;
}
svg:hover .gauge-segment{
stroke-dashoffset:-33;
stroke-dasharray: 66 100;
}
<p>Hover will change the gauge segment</p>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 200 120">
<defs>
<linearGradient id="gradientBackground" gradientTransform="rotate(30)">
<stop offset="0%" stop-color="#E9F1FF"/>
<stop offset="100%" stop-color="#DBE7FF"/>
</linearGradient>
<linearGradient id="gradientSegment" x1="63.192%" x2="36.891%" y1="13.157%" y2="100%">
<stop offset="0%" stop-color="#FF8600"/>
<stop offset="100%" stop-color="#FFC86A"/>
</linearGradient>
</defs>
<!-- gauge path -->
<symbol id="stroke">
<path pathlength="100" fill="none" stroke-width="10" d="M55.6,103C52,96.1,50,88.3,50,80
c0-27.6,22.4-50,50-50s50,22.4,50,50c0,8.3-2,16.1-5.6,23"/>
</symbol>
<!-- gauge background -->
<g id="gaugeBackground" >
<use id="gaugeBackgroundColor" href="#stroke" stroke="url(#gradientBackground)"></use>
<use id="gaugeBackgroundDash" href="#stroke" stroke="#E9F1FF" stroke-dashoffset="0" stroke-dasharray="1 1" ></use>
</g>
<!-- percentages -->
<g id="gaugeSegments" >
<use id="segment01" class="gauge-segment" href="#stroke" filter="" stroke="url(#gradientSegment)" stroke-dashoffset="0" stroke-dasharray="33 100"></use>
</g>
</svg>

Chrome doesn’t work on the animation of the attribute offset for a linear gradient

Below is the code that works great in Firefox, but any attempts to animate the linear gradient's offset attribute in Chrome ended in nothing.
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="900" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Also tried using gradientUnits =" objectBoundingBox "
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0%" y1="0%" x2="100%" y2="100%" gradientUnits="objectBoundingBox">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Any solution to this problem will do with: SVG,css, javascript
One solution to this would be using floating numbers instead of percentages, i.e values="1;0;1" instead of values="100%;0%;100%"
svg{border:1px solid}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="50%" y2="50%" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="dodgerblue"/>
<stop offset=".52" stop-color="white">
<animate
attributeName="offset"
values="1;0;1"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="1" stop-color="gold">
<animate
attributeName="offset"
values="1;.5;1"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Here is an idea with CSS only where you can rely on two gradients and a translation/opacity animation to approximate it. I also considered a little blur effect to have a better transition between gradient.
.box {
border-radius:20px;
width:200px;
height:200px;
position:relative;
z-index:0;
overflow:hidden;
}
.box:before,
.box:after{
content:"";
position:absolute;
bottom:0;
right:0;
width:220%;
height:220%;
animation:translate 2s infinite linear alternate;
}
.box:after {
background:
linear-gradient(to bottom right,dodgerblue 0%,white 40%,gold 60%);
animation-name:translate,show;
opacity:0;
}
.box:before {
background:
linear-gradient(to bottom right,dodgerblue,white 50%,gold 50%);
animation-name:translate,fade;
}
#keyframes translate{
from {
transform:translate(48%,48%);
}
}
#keyframes show{
30%,85% {
opacity:1;
}
}
#keyframes fade{
30%,85% {
filter:blur(8px);
}
}
<div class="box">
</div>
You can always use javascript for that:
requestAnimationFrame(animateOffsets);
// if this function called as callback of requestAnimationFrame,
// so there are first argument is the time from beginning from scene start
function animateOffsets(t) {
requestAnimationFrame(animateOffsets);
t = t%5000/5000; // will change from 0 to 1 (5 sec)
t = Math.sin(t*Math.PI*2); // will change from -1 to 1
stop1.setAttribute('offset', `${50 + t*50}%`);
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="60%" y2="60%" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="50%" stop-color="white" id="stop1"/>
<stop offset="100%" stop-color="gold"/>
</linearGradient>
</defs>
<rect x="50" y="50" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
</svg>
Gradient attribute offset animation as background image
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<linearGradient id="bgg" x1="479" y1="-345" x2="479" y2="853" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#fff">
<animate
attributeName="offset"
values="0;1;1;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="0;1;1;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
</linearGradient>
<rect x="-45" y="0" width="70%" height="70%" rx="5%" fill="#ACA900" />
<rect x="65" y="80" width="50%" height="50%" rx="5%" fill="url(#bgg)" />
<image x="30" y="100" xlink:href="https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg" width="50%" height="50%" />
</svg>
Radial gradient effects
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="50%" height="50%" viewBox="0 0 900 900" >
<radialGradient id="myRadial"
fx="50%" fy="50%" r="80%">
<stop offset="0%" stop-color="gold">
<animate
attributeName="offset"
values="0;1.3;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="100%" stop-color="#EDEDED">
<animate
attributeName="offset"
values="0;1.3;1.3;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
</radialGradient>
<rect x="0" y="0" width="70%" height="70%" rx="5%" fill="#ACC400" />
<rect x="85" y="80" width="50%" height="50%" rx="5%" fill="url(#myRadial)" />
</svg>

animate fill of an SVG using anime.js (or will i have to change the fill to be something else ?)

I have an SVG who's stroke i am animating useing anime.js like so:
$(function() {
var lineDrawing = anime({
targets: '#layer1 path',
strokeDashoffset: [anime.setDashoffset, 0],
easing: 'easeInOutSine',
duration: 1500,
delay: function(el, i) {
return i * 250
},
direction: 'alternate',
loop: true
});
});
My SVG is below:
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" viewBox="0 0 195.22488 193.54251" version="1.1" id="svg8" inkscape:version="0.92.1 r15371" sodipodi:docname="star.svg">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="-99.713793"
inkscape:cy="369.29872"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-to-guides="true"
inkscape:window-width="1366"
inkscape:window-height="705"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-9.3736792,-53.001107)"
fill="none"
fill-rule="evenodd"
stroke="currentColor"
stroke-width="5"
>
<path
sodipodi:type="star"
style="fill:#d4ff2a"
id="path10"
sodipodi:sides="5"
sodipodi:cx="111.125"
sodipodi:cy="155.6369"
sodipodi:r1="97.857147"
sodipodi:r2="48.928574"
sodipodi:arg1="0.81271377"
sodipodi:arg2="1.4410323"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 178.40476,226.69642 -60.94839,-22.54231 -53.122401,37.42824 2.604927,-64.93132 -52.012102,-38.95644 62.558327,-17.58745 20.977149,-61.504647 36.05825,54.061687 64.97669,0.94447 -40.27311,50.99941 z"
inkscape:transform-center-x="3.9129994"
inkscape:transform-center-y="-5.5444732" />
</g>
</svg>
FIDDLE HERE , I went through the doc's and there are examples on how to animate the stroke of an SVG, but what i really want to do is animate the fill of the SVG, I.E. animate the fill from the bottom to up. How do i do this ?
I have gone through the doc's but i don't see much of a clue.
EDIT :- To simplify my question, how exactly would i have to modify my SVG to animate the fill(or maybe i have to modify the fill to be something else) to move from downwards to up ?
you can add a <linear gradient> and animate its <stop>s ( without the library ), check animate svg gradients for more details.
$(function() {
var lineDrawing = anime({
targets: '#layer1 path',
strokeDashoffset: [anime.setDashoffset, 0],
easing: 'easeInOutSine',
duration: 1500,
delay: function(el, i) {
return i * 250
},
direction: 'alternate',
loop: true
});
});
.svg__holder {
max-width: 300px;
margin: 0 auto;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/2.2.0/anime.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg id="layer1" width="100%" height="100%" viewBox='0 0 850 800'>
<defs>
<linearGradient id="bottom-to-top" y1="100%" x2="0%" y2="0%">
<stop offset="0" stop-color="rgb(212, 255, 42)">
<animate dur="5s" attributeName="offset" fill="freeze" from="0" to="1" />
</stop>
<stop offset="0" stop-color="#fff">
<animate dur="5s" attributeName="offset" fill="freeze" from="0" to="1" />
</stop>
</linearGradient>
</defs>
<path class="path" stroke="#000000" fill="url(#bottom-to-top)" stroke-width="3" opacity="1" d="m 178.40476,226.69642 -60.94839,-22.54231 -53.122401,37.42824 2.604927,-64.93132 -52.012102,-38.95644 62.558327,-17.58745 20.977149,-61.504647 36.05825,54.061687 64.97669,0.94447 -40.27311,50.99941 z" id="svg_1" />
</svg>
The only way I know to do this is to define the background as a pattern instead of using a fill color. I don't know anime.js but I think it should be pretty simple to manipulate the x and y values of the background as well.
Using your jsfiddle:
.. define background:
<defs
id="defs2" />
<pattern id="background" patternUnits="userSpaceOnUse" width="500" height="500" > <rect fill="#0000FF" x="0" y="150" width="500" height="500"> </image> </pattern>
...
</defs>
.. set background:
<path
sodipodi:type="star"
style="fill: url(#background)"
id="path10"
...
</path>
Here is an example: https://jsfiddle.net/z8ok9osg/

SVG button without CSS doesn't work properly

I'm making a svg button with animated gradient in mouseover event, without CSS.
The button listen to mouseout and mouseover events, without any problem, changing the radialGradient attribute between id="rellenoZoomHover" and id="rellenoZoom", depending on the listener answer.
The button has an tag in it radialGradient declaration tag, that repeats only one time.
The problem is that the script only execute the first time: second time, ignores animate.
Whath I am doing wrong?. Thanks in advance
<?xml version='1.0' encoding='UTF-8'?>
<svg version='1.1' id='project' xmlns:svg='http://www.w3.org/2000/svg'
xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
onload='init(evt)'>
<script type='text/ecmascript'>
function init(evt) {
cmdButtonZoomPrevio = document.getElementById('cmdZoomPrevio');
cmdButtonZoomPrevio.addEventListener('mouseover', manejadorDeMouseHoverEnBotones);
cmdButtonZoomPrevio.addEventListener('mouseout', manejadorDeMouseOutEnBotones);
}
<![CDATA[
function manejadorDeMouseHoverEnBotones(evt) {
var pathVolatil = cmdButtonZoomPrevio.childNodes[1];
pathVolatil.setAttribute('fill','url(#rellenoZoomHover)');
}
function manejadorDeMouseOutEnBotones(evt) {
var pathVolatil = cmdButtonZoomPrevio.childNodes[1];
pathVolatil.setAttribute('fill','url(#rellenoZoom)');
}
//El botón cmdZoomPrevio;
var cmdButtonZoomPrevio;
]]>
</script>
<g id="cmdZoomPrevio" class="boton" toggleButton="false" triStateButton="false">
<path id="bordeZoomSE" fill="url(#rellenoZoom)" stroke="#000000" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M64.925,85.116c3.529,0,7.005-0.938,10.042-2.69c9.609-5.554,12.924-17.858,7.354-27.479l34.848-20.112
c16.633,28.863,6.753,65.771-22.063,82.438c-9.188,5.294-19.581,8.093-30.167,8.093L64.925,85.116L64.925,85.116z"/>
<g id="dibujocmdZoomSE">
<rect x="105.766" y="97.561" transform="matrix(0.8707 -0.4918 0.4918 0.8707 -34.1811 65.8925)" fill="#333333" width="4.92" height="0.784"/>
<polygon fill="#663300" points="104.234,87.553 109.439,96.827 109.439,96.897 106.586,98.467 106.518,98.467 101.313,89.191
101.313,89.118 104.165,87.553 "/>
<rect x="101.312" y="86.085" transform="matrix(0.8715 -0.4904 0.4904 0.8715 -29.6865 61.2979)" width="1.641" height="2.429"/>
<polygon fill="#006633" points="98.104,99.394 88.091,93.723 88.091,93.651 98.068,87.73 98.139,87.765 98.139,99.358 "/>
<path fill="none" stroke="#006633" stroke-width="2.15" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="3" d="
M98.104,93.543h0.854c3.382,0,6.298-0.593,8.771-1.783c2.373-1.182,3.586-2.61,3.643-4.281c-0.057-1.665-1.262-3.063-3.643-4.203
c-2.474-1.23-5.391-1.854-8.771-1.854c-3.467,0-6.413,0.616-8.835,1.854c-0.139,0.047-0.288,0.117-0.432,0.213"/>
<path fill="#CCFFFF" d="M97.752,86.978c-2.122-0.014-3.947-0.788-5.49-2.313c-1.463-1.474-2.184-3.263-2.174-5.354
c-0.01-2.103,0.714-3.925,2.174-5.457c1.531-1.458,3.348-2.183,5.454-2.179c2.113-0.006,3.911,0.717,5.38,2.179
c1.535,1.527,2.313,3.354,2.314,5.457c-0.006,2.105-0.779,3.892-2.314,5.354C101.635,86.195,99.85,86.966,97.752,86.978z"/>
<path fill="none" stroke="#0000FF" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="3" d="
M97.752,86.978c-2.096,0-3.9-0.761-5.42-2.288c-1.475-1.474-2.219-3.229-2.219-5.271c0-2.09,0.744-3.9,2.219-5.421
c1.52-1.479,3.324-2.226,5.42-2.226c2.089,0,3.873,0.738,5.344,2.226c1.522,1.475,2.285,3.271,2.285,5.421
c0,2.048-0.758,3.807-2.285,5.271C101.622,86.217,99.841,86.978,97.752,86.978z"/>
</g>
<defs>
<radialGradient id="rellenoZoomHover" cx="65" cy="65" r="65" gradientUnits="userSpaceOnUse">
<stop offset="0.5" style="stop-color:#FFFFFF">
<animate attributeName="stop-color" values="#FFFFFF;#81BEF7" dur="2s" repeatCount="1"/>
</stop>
<stop offset="1" style="stop-color:#81BEF7"/>
</radialGradient>
<radialGradient id="rellenoZoom" cx="65" cy="65" r="65" gradientUnits="userSpaceOnUse">
<stop offset="0.5" style="stop-color:#FFFFFF" />
<stop offset="1" style="stop-color:#A4A4A4"/>
</radialGradient>
</defs>
</g>
</svg>
The document has a timeline that begins at 0 and stays at 0 unless some animation runs. As an animation runs the timeline advances, in this case to 2 seconds as we have 2 seconds of animation.
The next time we hover the animation timeline is at 2 seconds, so the animation does not trigger again as the animation's start time has passed.
We could either
manually trigger the animation with javascript by calling beginElement(), this would affect just one animation
force the document timeline back to 0 this would affect all animations.
The code below demonstrates both (2. is commented out as we only need one technique)
<?xml version='1.0' encoding='UTF-8'?>
<svg version='1.1' id='project' xmlns:svg='http://www.w3.org/2000/svg'
xmlns='http://www.w3.org/2000/svg'
xmlns:xlink='http://www.w3.org/1999/xlink'
onload='init(evt)'>
<script type='text/ecmascript'>
function init(evt) {
cmdButtonZoomPrevio = document.getElementById('cmdZoomPrevio');
cmdButtonZoomPrevio.addEventListener('mouseover', manejadorDeMouseHoverEnBotones);
cmdButtonZoomPrevio.addEventListener('mouseout', manejadorDeMouseOutEnBotones);
}
<![CDATA[
function manejadorDeMouseHoverEnBotones(evt) {
var pathVolatil = cmdButtonZoomPrevio.childNodes[1];
pathVolatil.setAttribute('fill','url(#rellenoZoomHover)');
document.getElementById('rellenoZoomHoverAnimate').beginElement();
//document.getElementById('project').setCurrentTime(0);
}
function manejadorDeMouseOutEnBotones(evt) {
var pathVolatil = cmdButtonZoomPrevio.childNodes[1];
pathVolatil.setAttribute('fill','url(#rellenoZoom)');
}
//El botón cmdZoomPrevio;
var cmdButtonZoomPrevio;
]]>
</script>
<g id="cmdZoomPrevio" class="boton" toggleButton="false" triStateButton="false">
<path id="bordeZoomSE" fill="url(#rellenoZoom)" stroke="#000000" stroke-width="0.5" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" d="
M64.925,85.116c3.529,0,7.005-0.938,10.042-2.69c9.609-5.554,12.924-17.858,7.354-27.479l34.848-20.112
c16.633,28.863,6.753,65.771-22.063,82.438c-9.188,5.294-19.581,8.093-30.167,8.093L64.925,85.116L64.925,85.116z"/>
<g id="dibujocmdZoomSE">
<rect x="105.766" y="97.561" transform="matrix(0.8707 -0.4918 0.4918 0.8707 -34.1811 65.8925)" fill="#333333" width="4.92" height="0.784"/>
<polygon fill="#663300" points="104.234,87.553 109.439,96.827 109.439,96.897 106.586,98.467 106.518,98.467 101.313,89.191
101.313,89.118 104.165,87.553 "/>
<rect x="101.312" y="86.085" transform="matrix(0.8715 -0.4904 0.4904 0.8715 -29.6865 61.2979)" width="1.641" height="2.429"/>
<polygon fill="#006633" points="98.104,99.394 88.091,93.723 88.091,93.651 98.068,87.73 98.139,87.765 98.139,99.358 "/>
<path fill="none" stroke="#006633" stroke-width="2.15" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="3" d="
M98.104,93.543h0.854c3.382,0,6.298-0.593,8.771-1.783c2.373-1.182,3.586-2.61,3.643-4.281c-0.057-1.665-1.262-3.063-3.643-4.203
c-2.474-1.23-5.391-1.854-8.771-1.854c-3.467,0-6.413,0.616-8.835,1.854c-0.139,0.047-0.288,0.117-0.432,0.213"/>
<path fill="#CCFFFF" d="M97.752,86.978c-2.122-0.014-3.947-0.788-5.49-2.313c-1.463-1.474-2.184-3.263-2.174-5.354
c-0.01-2.103,0.714-3.925,2.174-5.457c1.531-1.458,3.348-2.183,5.454-2.179c2.113-0.006,3.911,0.717,5.38,2.179
c1.535,1.527,2.313,3.354,2.314,5.457c-0.006,2.105-0.779,3.892-2.314,5.354C101.635,86.195,99.85,86.966,97.752,86.978z"/>
<path fill="none" stroke="#0000FF" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="3" d="
M97.752,86.978c-2.096,0-3.9-0.761-5.42-2.288c-1.475-1.474-2.219-3.229-2.219-5.271c0-2.09,0.744-3.9,2.219-5.421
c1.52-1.479,3.324-2.226,5.42-2.226c2.089,0,3.873,0.738,5.344,2.226c1.522,1.475,2.285,3.271,2.285,5.421
c0,2.048-0.758,3.807-2.285,5.271C101.622,86.217,99.841,86.978,97.752,86.978z"/>
</g>
<defs>
<radialGradient id="rellenoZoomHover" cx="65" cy="65" r="65" gradientUnits="userSpaceOnUse">
<stop offset="0.5" style="stop-color:#FFFFFF">
<animate id="rellenoZoomHoverAnimate" attributeName="stop-color" values="#FFFFFF;#81BEF7" dur="2s" repeatCount="1"/>
</stop>
<stop offset="1" style="stop-color:#81BEF7"/>
</radialGradient>
<radialGradient id="rellenoZoom" cx="65" cy="65" r="65" gradientUnits="userSpaceOnUse">
<stop offset="0.5" style="stop-color:#FFFFFF" />
<stop offset="1" style="stop-color:#A4A4A4"/>
</radialGradient>
</defs>
</g>
</svg>

Categories

Resources