Fill color SVG path with animation - javascript

I have use following way to fill color of SVG paths. Is there a way to add animation to it. Color filling starting from center and spread.
$(function(){
$("#btn-test1").on("click",function(){
$("#path1").attr("fill","#0000");
});
});

This answer provides four different options to animate the fill color of a SVG path using jQuery.animate(), CSS #keyframes and SVG SMIL-Animation:
#1 jQuery.animate() and SVG <radialGradient>
$(function(){
$("button").on("click",function(){
$(this).animate(
{
textIndent: 1, // or whatever
}, {
duration: 3000,
step: function ( now, fx ) {
// arguments:
// now: numeric value of the property being animated at each step
// fx: reference to the jQuery.fx prototype object
// fx.start: first value of the animated property
// fx.end: last value of the animated property
var from = 0,
to = 700,
r = from + to * ( now - fx.start ) / ( fx.end - fx.start ); // animate r from 0 to 700
$("#gradient").attr( "r", r + "px" );
},
complete: function () {
$("#path").attr("fill", "#000"); // callback
}
}
);
});
});
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<body>
<button>Start Animation</button>
<svg height="150" width="300">
<defs>
<radialGradient id="gradient" r="0px" gradientUnits="userSpaceOnUse">
<stop offset="20%" style="stop-color: #000; stop-opacity: 1" />
<stop offset="100%" style="stop-color: #000; stop-opacity: 0" />
</radialGradient>
</defs>
<path id="path" d="M 0 0 Q 300 300 300 0 z" fill="url(#gradient)" />
</svg>
</body>
#2 jQuery.animate() and SVG transform attribute
$(function(){
$("button").on("click",function(){
$(this).animate(
{
textIndent: 1, // or whatever
}, {
duration: 3000,
step: function ( now, fx ) {
// arguments:
// now: numeric value of the property being animated at each step
// fx: reference to the jQuery.fx prototype object
// fx.start: first value of the animated property
// fx.end: last value of the animated property
var from = 0,
to = 1,
scale = from + to * ( now - fx.start ) / ( fx.end - fx.start ); // animate r from 0 to 700
$("#path").attr( "transform", "scale(" + scale + ")" );
}
}
);
});
});
#path {transform-origin: 50% 50%;}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<button>Start Animation</button>
<svg height="150" width="300">
<path id="path" d="M 0 0 Q 300 300 300 0 z" fill="#000" />
</svg>
</body>
Maybe that isn’t the result you expected, but it’s an option.
#3 CSS #keyframes
stop {
stop-opacity: 0;
animation: 3s animateStopOpacity;
}
stop:last-child {
animation-delay: 2s;
}
#keyframes animateStopOpacity {
from {stop-opacity: 0;}
to {stop-opacity: 1;}
}
<body>
<svg height="150" width="300">
<defs>
<radialGradient id="gradient" r="50%" gradientUnits="userSpaceOnUse">
<stop offset="0%" style="stop-color: #000; stop-opacity: 1" />
<stop offset="100%" style="stop-color: #000; stop-opacity: 0" />
</radialGradient>
</defs>
<path id="path" d="M 0 0 Q 300 300 300 0 z" fill="url(#gradient)" />
</svg>
</body>
#4 SVG SMIL Animation
<body>
<svg height="150" width="300">
<defs>
<radialGradient id="gradient" r="100px" gradientUnits="userSpaceOnUse">
<stop offset="20%" style="stop-color: #000; stop-opacity: 1" />
<stop offset="100%" style="stop-color: #000; stop-opacity: 0" />
<animate
attributeName="r"
from="0"
to="700"
dur="3s"
fill="freeze"
/>
</radialGradient>
</defs>
<path id="path" d="M 0 0 Q 300 300 300 0 z" fill="url(#gradient)" />
</svg>
</body>
I hope I could help you!

Related

Animation is too choppy when animating inline SVG with javascript according to the window's scrollbar position

I am trying to use JavaScript to retrieve inline SVG elements and set their transform attributes in order to translate them in response to scrolling down the screen. I am using window.requestAnimationFrame() in order to do so.
The animation is very choppy so far and I haven't found a solution to remedy this yet. Any suggestions??
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body style="margin: 0px">
<svg viewBox="0 0 1440 1024" fill="none" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="">
<g id="AbstractBackground">
<rect id="backgroundRect" width="1440" height="1024" fill="#BDD8DE"/>
<rect id="greenCircleGrad" x="-338" y="-444" width="1440" height="1440" fill="url(#paint0_radial_2005_534273)"/>
<path id="wave1" d="M516 228.015C212 228.015 74 34.0154 -170 36.0154C-414 38.0154 -634 228.015 -634 228.015V988.015H1692V200.015C1692 200.015 1459 36.0154 1208 36.0154C957 36.0153 820 228.015 516 228.015Z" fill="#60AB9E"/>
<rect id="turquoiseCircleGrad" x="508" y="-208" width="1440" height="1440" fill="url(#paint1_radial_2005_534273)"/>
<path id="wave2" d="M872 553.015C568 553.015 430 359.015 186 361.015C-58 363.015 -278 553.015 -278 553.015V1313.02H2048V525.015C2048 525.015 1815 361.015 1564 361.015C1313 361.015 1176 553.015 872 553.015Z" fill="#77ABBB"/>
<rect id="blueCircleGrad" x="-128" y="-42" width="1440" height="1440" fill="url(#paint2_radial_2005_534273)"/>
<path id="wave3" d="M376 853.015C72 853.015 -66 659.015 -310 661.015C-554 663.015 -774 853.015 -774 853.015V1613.02H1552V825.015C1552 825.015 1319 661.015 1068 661.015C817 661.015 680 853.015 376 853.015Z" fill="#C6DAD4"/>
<rect id="blackCircleGrad" x="207" y="221" width="1753" height="1753" fill="url(#paint3_radial_2005_534273)"/>
<defs>
<radialGradient id="paint0_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(382 276) rotate(90) scale(720)">
<stop stop-color="#7B3A5D" stop-opacity="0.67"/>
<stop stop-color="#6DA060" stop-opacity="0.83"/>
<stop offset="0.442708" stop-color="#6DA360" stop-opacity="0.71"/>
<stop offset="1" stop-color="#6CA95D" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint1_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1228 512) rotate(90) scale(720)">
<stop stop-color="#71EFE3"/>
<stop stop-color="#71EFE3"/>
<stop offset="1" stop-color="#71EFE3" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint2_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(592 678) rotate(90) scale(720)">
<stop stop-color="#8A78B1"/>
<stop stop-color="#58B4C8"/>
<stop offset="1" stop-color="#67C0D4" stop-opacity="0"/>
</radialGradient>
<radialGradient id="paint3_radial_2005_534273" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(1083.5 1097.5) rotate(90) scale(876.5)">
<stop stop-color="#8A78B1" stop-opacity="0.73"/>
<stop stop-color="#20665E" stop-opacity="0.53"/>
<stop offset="0.713542" stop-color="#2F9262" stop-opacity="0"/>
</radialGradient>
</defs>
</svg>
</body>
<script>
// IDs of SVG elements in the SVG background that animate when scrolling down
const SLO_SCROLL_TRANSFORM_IDS = ["turquoiseCircleGrad","wave1"];
const MED_SCROLL_TRANSFORM_IDS = ["blueCircleGrad","wave2"];
const FST_SCROLL_TRANSFORM_IDS = ["blackCircleGrad","wave3"];
const [SLO_SCROLL_DIST, MED_SCROLL_DIST, FST_SCROLL_DIST] = [50, 100, 200];
/**
* applies css translate transformation to an svg element
* #param id svg element id to apply transformation to
* #param distance vertical distance to translate svg element
*/
function translateSvgVertically(id, distance) {
document.querySelector("svg #"+id).setAttribute('transform',"translate(0,"+distance+")");
}
let h = document.documentElement;
let b = document.body;
/**
* returns how much of the page has been scrolled through as a decimal
* #returns {number} returns a decimcal [0,1]
*/
function getScrollFraction() {
return (h['scrollTop']||b['scrollTop']) / ((h['scrollHeight']||b['scrollHeight']) - h.clientHeight);
}
let lastKnownScrollFraction = 0;
let ticking = false;
document.addEventListener("scroll", (e) => {
lastKnownScrollFraction = getScrollFraction();
if (!ticking) {
window.requestAnimationFrame(function() {
SLO_SCROLL_TRANSFORM_IDS.forEach((id) => translateSvgVertically(id, SLO_SCROLL_DIST*lastKnownScrollFraction));
MED_SCROLL_TRANSFORM_IDS.forEach((id) => translateSvgVertically(id, MED_SCROLL_DIST*lastKnownScrollFraction));
FST_SCROLL_TRANSFORM_IDS.forEach((id) => translateSvgVertically(id, FST_SCROLL_DIST*lastKnownScrollFraction));
ticking = false;
});
ticking = true;
}
});
</script>
</html>

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>

Smooth animate for svg fill

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);
});

svg gradient fill animation percentage jquery

I'm trying to get some svg animation with jquery, for each class "check" i need summs percentage offset for gradient, and when this class is remove need reduce percentage offset gradient. This all need animation down up when class added, and up down when class removed.
So i got, gradient and get offset to 5% percentage. Trying to get array but stuck. Think about get all elements with class "check" and try to summs for each class.
var firstStop = document.getElementById('F1gst1');
percentage = '5%'; firstStop.setAttribute('offset',percentage);
$(".analysis-li").click(function(){
$(this).toggleClass("check");
if($(this).hasClass('check')){
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<li class="analysis-li"></li>
<li class="analysis-li"></li>
<li class="analysis-li"></li>
<li class="list analysis-li"></li>
<li class="analysis-li"></li>
<li class="list analysis-li"></li>
<li class="analysis-li" ></li>
<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>
This is how I would do it. In order to animate the gradient I'm using requestAnimationFrame. I'm animating the second stop offset between 10% and 100% but you can choose the values you want.
Please read the comments in the code.
// the second stop
let laststop = document.getElementById('F1gst2');
// a variable used to toggle the animation
let n = 0;
// the target value of the offset attribute
let target;
// the actual value of the offset attribute
let val = 10;
//the request animation frame id
let rid = null;
$(".analysis-li").click(function(){
n++;
// set the target value
if(n%2 == 1){
target = 100;
}else{target = 10}
// if there is an animation stop it
if(rid){cancelAnimationFrame(rid); rid="null"}
// call the frame function
frame()
});
function frame(){
rid = requestAnimationFrame(frame);
//the distance between the value and the target value
dist = target - val;
//increase the value
val += dist/10;
// set the offset value
laststop.setAttributeNS(null,"offset",`${val}%`)
}
svg{border:1px solid; width:30px}
path{stroke:black;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="analysis-li">click here</p>
<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="10%" 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>
SVG created programmicaly, only one shape is translated by incoming value:
let path = (y, d, extra) => `<path d="${d}" transform="translate(0,${y})" ${extra||''}></path>`
let multi = (count, html) => Array(count).fill(0).map((e, i) => html(i)).join('');
let toggle = el => el.classList.toggle('on') |
rect.setAttribute('y', 14.6*(7-document.querySelectorAll("path.on").length)+8)
scale.innerHTML = multi(10, i => path(i*10, 'M60,10h10M65,12h5M65,14h5M65,16h5M65,18h5'));
checks.innerHTML = multi(7, i => path(i*12, 'M10,10v8h8v-8z', 'class="on" onclick="toggle(this)"') +
path(i*12, 'M12,14l2.2,2l2.2,-4'))
g#scale path {
stroke: white;
stroke-width: 0.7;
}
#checks {
position: absolute;
top: 20px;
left: 20px;
}
#checks path {
fill: none;
pointer-events: all;
stroke: #f5b53a;
cursor:pointer;
stroke-linejoin:round;
}
#checks path.on + path {
opacity:1;
}
#checks path:nth-child(2n) {
opacity: 0;
pointer-events: none;
transition: 0.5s;
stroke: white;
}
<svg viewbox="0 0 135 135" height="90vh" style="background-color:purple">
<defs><mask id="termometer">
<path d="M80,10v100" stroke="white" stroke-width="5" stroke-linecap="round"></path>
<circle r="10" cy="120" cx="80" fill="white"></circle>
<g id="scale"></g>
</mask></defs>
<rect width="130" height="130" mask="url(#termometer)" fill="white"></rect>
<rect id="rect" style="transition:1s" y="8" width="130" height="130"
mask="url(#termometer)" fill="#f5b53a"></rect>
<g id="checks"></g>
</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/

Categories

Resources