I have some SVG-s that are equipped with scripts inside (for handling the onClick event), like:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:svgjs="http://svgjs.dev/svgjs" width="200" height="200">
<defs>
<linearGradient id="borderColor" x1="0%" y1="0%" x2="90%" y2="70%">
<stop stop-opacity="0.8" stop-color="#def0ff" offset="0"/>
<stop stop-opacity="0.8" stop-color="#9bb0c2" offset="0.3"/>
<stop stop-opacity="0.8" stop-color="#def0ff" offset="0.4"/>
<stop stop-opacity="0.8" stop-color="#9bb0c2" offset="0.6"/>
<stop stop-opacity="0.8" stop-color="#def0ff" offset="0.7"/>
<stop stop-opacity="0.8" stop-color="#9bb0c2" offset="1"/>
</linearGradient>
<linearGradient x1="0" y1="0" x2="0.9" y2="0.7" id="fillColor">
<stop stop-opacity="0.4" stop-color="#dbdfe2" offset="0"/>
<stop stop-opacity="0.4" stop-color="#d8d8e1" offset="0.3"/>
<stop stop-opacity="0.4" stop-color="#c9ced3" offset="0.3"/>
<stop stop-opacity="0.5" stop-color="#dae2e9" offset="0.6"/>
<stop stop-opacity="0.5" stop-color="#e3e9ed" offset="0.6"/>
<stop stop-opacity="0.5" stop-color="#e2e9ed" offset="1"/>
</linearGradient>
<radialGradient id="circleGrad">
<stop offset="0%" stop-color="black" />
<stop offset="100%" stop-color="white" />
</radialGradient>
<mask id="myMask">
<rect width="100%" height="100%" fill="white"/>
<circle cx="20" cy="180" r="20"
fill="url(#circleGrad)"/>
<circle cx="100" cy="20" r="20"
fill="url(#circleGrad)"/>
<circle cx="180" cy="180" r="20"
fill="url(#circleGrad)"/>
</mask>
<radialGradient id="circleGrad2">
<stop offset="0%" stop-color="white" />
<stop offset="100%" stop-color="black" />
</radialGradient>
<mask id="myMask2">
<rect width="100%" height="100%" fill="black"/>
<circle cx="20" cy="180" r="20"
fill="url(#circleGrad2)"/>
<circle cx="100" cy="20" r="20"
fill="url(#circleGrad2)"/>
<circle cx="180" cy="180" r="20"
fill="url(#circleGrad2)"/>
</mask>
</defs>
<script type="application/ecmascript"><![CDATA[
function triangle_click(evt){
const fgPath = evt.target;
const newVal = fgPath.getAttribute('stroke-dasharray') === '0' ? '30 20' : 0;
fgPath.setAttribute('stroke-dasharray',newVal);
}
]]> </script>
<path d="M 20,180 L 100,20 L 180,180 Z"
stroke="#00ffff" stroke-width="3"
fill="url(#fillColor)"
mask="url(#myMask2)">
<animate
attributeName="stroke-dashoffset"
values="0;500"
dur="5s"
repeatCount="indefinite"
/>
</path>
<path id="fgPath" d="M 20,180 L 100,20 L 180,180 Z"
stroke="url(#borderColor)" stroke-width="3"
stroke-dasharray="0"
stroke-linecap="round"
fill="url(#fillColor)"
mask="url(#myMask)"
onclick="triangle_click(evt)"
>
<animate
attributeName="stroke-dashoffset"
values="0;500"
dur="5s"
repeatCount="indefinite"
/>
</path>
</svg>
Now, when I add this SVG into my react app, it throws an error on the 'onClick' event, unless I copy and paste the <script> tag in the inspector, anywhere (Uncaught ReferenceError: triangle_click is not defined at onclick).
Does that mean this script tag was not read initially, that's why it doesn't find it at first place?
Thanks,
M
I found out the issue was that I inserted the element as innerHTML. The answer can be found here: Executing <script> elements inserted with .innerHTML
I have the following code:
<lottie-player id="head" src="./assets/gradis/face_round.json" background="transparent" speed="1" style="width: 300px; height: 300px">
#shadow-root (open)
<div id="animation-container" class="main" aria-label="Lottie animation">
<div id="animation" class="animation" style="background:transparent">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 1200" width="1200" height="1200"
style="width: 100%; height: 100%; transform: translate3d(0px, 0px, 0px);" preserveAspectRatio="xMidYMid meet">
<defs>
<clipPath id="__lottie_element_95">
<rect width="1200" height="1200" x="0" y="0"></rect>
</clipPath>
<radialGradient id="__lottie_element_99" spreadMethod="pad" gradientUnits="userSpaceOnUse" cx="-1"
cy="-0.9950000047683716" r="494.7430114746094" fx="-0.3150197936550764" fy="-153.11209152463204">
<stop offset="1%" stop-color="rgb(0,195,255)"></stop>
<stop offset="29%" stop-color="rgb(0,97,255)"></stop>
<stop offset="57%" stop-color="rgb(0,0,255)"></stop>
<stop offset="76%" stop-color="rgb(128,48,224)"></stop>
<stop offset="80%" stop-color="rgb(255,96,193)"></stop>
<stop offset="88%" stop-color="rgb(128,105,190)"></stop>
<stop offset="100%" stop-color="rgb(0,113,188)"></stop>
</radialGradient>
<mask id="__lottie_element_101">
<path fill="url(#__lottie_element_100)"
d=" M467.45001220703125,0.004999999888241291 C467.45001220703125,3.615000009536743 467.4200134277344,7.224999904632568 467.3299865722656,10.8149995803833 C466.7799987792969,34.78499984741211 464.44000244140625,58.334999084472656 460.4100036621094,81.28500366210938 C460.4100036621094,81.28500366210938 460.4100036621094,81.29499816894531 460.4100036621094,81.29499816894531 C453.70001220703125,119.53500366210938 442.3500061035156,156.1750030517578 426.95001220703125,190.59500122070312 C426.95001220703125,190.59500122070312 426.95001220703125,190.59500122070312 426.95001220703125,190.60499572753906 C426.44000244140625,191.7550048828125 425.9200134277344,192.89500427246094 425.3900146484375,194.0449981689453 C351.70001220703125,355.364990234375 188.94000244140625,467.4549865722656 0,467.4549865722656 C-180.6199951171875,467.4549865722656 -337.3299865722656,365.0050048828125 -415.1499938964844,215.05499267578125 C-417.82000732421875,209.9149932861328 -420.3900146484375,204.72500610351562 -422.8599853515625,199.48500061035156 C-422.9200134277344,199.34500122070312 -422.989990234375,199.2050018310547 -423.04998779296875,199.0749969482422 C-441.5199890136719,159.89500427246094 -454.7099914550781,117.74500274658203 -461.70001220703125,73.5250015258789 C-465.19000244140625,51.48500061035156 -467.1300048828125,28.94499969482422 -467.4200134277344,5.985000133514404 C-467.45001220703125,3.994999885559082 -467.45001220703125,2.005000114440918 -467.45001220703125,0.004999999888241291 C-467.45001220703125,-2.505000114440918 -467.44000244140625,-5.034999847412109 -467.3900146484375,-7.534999847412109 C-466.8299865722656,-42.51499938964844 -462.44000244140625,-76.55500030517578 -454.6099853515625,-109.25499725341797 C-450.6099853515625,-125.96499633789062 -445.7099914550781,-142.3249969482422 -439.9700012207031,-158.28500366210938 C-421.1199951171875,-210.68499755859375 -393.1700134277344,-258.7349853515625 -358.0299987792969,-300.5450134277344 C-346.4100036621094,-314.375 -334,-327.5249938964844 -320.8800048828125,-339.9049987792969 C-237.16000366210938,-418.9849853515625 -124.2300033569336,-467.4549865722656 0,-467.4549865722656 C124.2300033569336,-467.4549865722656 237.16000366210938,-418.9849853515625 320.8800048828125,-339.9049987792969 C334.04998779296875,-327.4750061035156 346.5,-314.2749938964844 358.1600036621094,-300.3949890136719 C388.42999267578125,-264.364990234375 413.3500061035156,-223.6649932861328 431.70001220703125,-179.5749969482422 C441.1199951171875,-156.97500610351562 448.80999755859375,-133.48500061035156 454.6099853515625,-109.25499725341797 C454.6099853515625,-109.25499725341797 454.6099853515625,-109.25499725341797 454.6099853515625,-109.24500274658203 C463,-74.19499969482422 467.45001220703125,-37.6150016784668 467.45001220703125,0.004999999888241291z">
</path>
</mask>
<radialGradient id="__lottie_element_100" spreadMethod="pad" gradientUnits="userSpaceOnUse" cx="-1"
cy="-0.9950000047683716" r="494.7430114746094" fx="-0.3150197936550764" fy="-153.11209152463204">
<stop stop-color="rgb(255,255,255)" offset="0%" stop-opacity="1"></stop>
<stop stop-color="rgb(255,255,255)" offset="40%" stop-opacity="1"></stop>
<stop stop-color="rgb(255,255,255)" offset="80%" stop-opacity="1"></stop>
<stop stop-color="rgb(255,255,255)" offset="86%" stop-opacity="0.5049999952316284"></stop>
<stop stop-color="rgb(255,255,255)" offset="100%" stop-opacity="0.009999999776482582"></stop>
</radialGradient>
</defs>
<g clip-path="url(#__lottie_element_95)">
<g style="display: block;" transform="matrix(0.5199999809265137,0,0,0.5199999809265137,600,642.1569213867188)"
opacity="1">
<g opacity="1" transform="matrix(1,0,0,1,3.8459999561309814,0)">
<path fill="url(#__lottie_element_99)" mask="url(#__lottie_element_101)" fill-opacity="1"
d="M0 0 M467.45001220703125,0.004999999888241291 C467.45001220703125,3.615000009536743 467.4200134277344,7.224999904632568 467.3299865722656,10.8149995803833 C466.7799987792969,34.78499984741211 464.44000244140625,58.334999084472656 460.4100036621094,81.28500366210938 C460.4100036621094,81.28500366210938 460.4100036621094,81.29499816894531 460.4100036621094,81.29499816894531 C453.70001220703125,119.53500366210938 442.3500061035156,156.1750030517578 426.95001220703125,190.59500122070312 C426.95001220703125,190.59500122070312 426.95001220703125,190.59500122070312 426.95001220703125,190.60499572753906 C426.44000244140625,191.7550048828125 425.9200134277344,192.89500427246094 425.3900146484375,194.0449981689453 C351.70001220703125,355.364990234375 188.94000244140625,467.4549865722656 0,467.4549865722656 C-180.6199951171875,467.4549865722656 -337.3299865722656,365.0050048828125 -415.1499938964844,215.05499267578125 C-417.82000732421875,209.9149932861328 -420.3900146484375,204.72500610351562 -422.8599853515625,199.48500061035156 C-422.9200134277344,199.34500122070312 -422.989990234375,199.2050018310547 -423.04998779296875,199.0749969482422 C-441.5199890136719,159.89500427246094 -454.7099914550781,117.74500274658203 -461.70001220703125,73.5250015258789 C-465.19000244140625,51.48500061035156 -467.1300048828125,28.94499969482422 -467.4200134277344,5.985000133514404 C-467.45001220703125,3.994999885559082 -467.45001220703125,2.005000114440918 -467.45001220703125,0.004999999888241291 C-467.45001220703125,-2.505000114440918 -467.44000244140625,-5.034999847412109 -467.3900146484375,-7.534999847412109 C-466.8299865722656,-42.51499938964844 -462.44000244140625,-76.55500030517578 -454.6099853515625,-109.25499725341797 C-450.6099853515625,-125.96499633789062 -445.7099914550781,-142.3249969482422 -439.9700012207031,-158.28500366210938 C-421.1199951171875,-210.68499755859375 -393.1700134277344,-258.7349853515625 -358.0299987792969,-300.5450134277344 C-346.4100036621094,-314.375 -334,-327.5249938964844 -320.8800048828125,-339.9049987792969 C-237.16000366210938,-418.9849853515625 -124.2300033569336,-467.4549865722656 0,-467.4549865722656 C124.2300033569336,-467.4549865722656 237.16000366210938,-418.9849853515625 320.8800048828125,-339.9049987792969 C334.04998779296875,-327.4750061035156 346.5,-314.2749938964844 358.1600036621094,-300.3949890136719 C388.42999267578125,-264.364990234375 413.3500061035156,-223.6649932861328 431.70001220703125,-179.5749969482422 C441.1199951171875,-156.97500610351562 448.80999755859375,-133.48500061035156 454.6099853515625,-109.25499725341797 C454.6099853515625,-109.25499725341797 454.6099853515625,-109.25499725341797 454.6099853515625,-109.24500274658203 C463,-74.19499969482422 467.45001220703125,-37.6150016784668 467.45001220703125,0.004999999888241291z">
</path>
</g>
</g>
</g>
</svg>
</div>
</div>
</lottie-player>
as you can see I have an svg inside a shadow root, I need to change the stop inside the first radialGradient but I can't use the idbecause this would change on every render.
I try the following but can access the svg neither the first radialGradient.
I try the following:
function loadHead() {
const head = document
.getElementById('head')
.shadowRoot.getElementById('animation')
.getElementsByTagName('svg')[0];
console.log(head);
}
window.addEventListener('load', (event) => {
console.log('DOM fully loaded and parsed');
loadHead();
});
But head is always empty,
I also try:
function loadHead() {
const head = document
.getElementById('head')
.shadowRoot.getElementById('animation');
.getElementsByTagName('svg')[0];
.getElementsByTagName('defs')[0];
.getElementsByTagName('radialGradient').childNodes.length;
console.log(head);
}
But can't got anaythig. Any suggiestion or help would be appreciate
I got this simple SVG animation that is transforming the pattern from dots to circles on page load.
<svg width="596" height="255">
<pattern id="pattern-circles" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="6" cy="6" r="3" stroke="red" stroke-width="2" fill="transparent">
<animate attributeName="r" values="0; 5" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
</circle>
</pattern>
<!-- The canvas with our applied pattern -->
<rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-circles)" />
</svg>
I am pretty new to SVG animation and have a hard time figure out how to achieve my goal, in addition to what I already got (dots to circles), to have this animation start/fade-in from the top left dot and end in the bottom right dot - is this even possible to achieve with this SVG pattern setup? Is there a way to isolate the dots, and stagger them in one-by-one?
Here is one idea where I will generate the circles using JS. On each iteration I increment the delay using i/j to create the to top-left to bottom-right animation. The position is trivial, the cx is based on i and cy on j
var d = 20;
var nx = 596/d; /* number of circles in a row */
var ny = 255/d; /* number of circles in a columns */
let svg = document.querySelector("svg");
for(var i=0;i<nx;i++) {
for(var j=0;j<ny;j++) {
svg.insertAdjacentHTML( 'beforeend','<circle cx="'+(6 + d*i)+'" cy="'+(6 + d*j)+'" r="0" stroke="red" stroke-width="2" fill="transparent"><animate attributeName="r" values="0; 5" dur="1s" begin="'+((i+j)/10)+'s" repeatCount="0" fill="freeze" /></circle>');
}
}
<svg width="596" height="255">
</svg>
To have a to-right animation keep only the i (same logic if you want a to-bottom one by keeping only the j)
var d = 20;
var nx = 596/d; /* number of circles in a row */
var ny = 255/d; /* number of circles in a columns */
let svg = document.querySelector("svg");
for(var i=0;i<nx;i++) {
for(var j=0;j<ny;j++) {
svg.insertAdjacentHTML( 'beforeend','<circle cx="'+(6 + d*i)+'" cy="'+(6 + d*j)+'" r="0" stroke="red" stroke-width="2" fill="transparent"><animate attributeName="r" values="0; 5" dur="1s" begin="'+(i/10)+'s" repeatCount="0" fill="freeze" /></circle>');
}
}
<svg width="596" height="255">
</svg>
An infinite animation:
var d = 20;
var nx = 596/d; /* number of circles in a row */
var ny = 255/d; /* number of circles in a columns */
let svg = document.querySelector("svg");
for(var i=0;i<nx;i++) {
for(var j=0;j<ny;j++) {
svg.insertAdjacentHTML( 'beforeend','<circle cx="'+(6 + d*i)+'" cy="'+(6 + d*j)+'" r="0" stroke="red" stroke-width="2" fill="transparent"><animate attributeName="r" values="0; 5;0" dur="2s" begin="'+((i+j)/20)+'s" repeatCount="indefinite" /></circle>');
}
}
<svg width="596" height="255">
</svg>
And why not from the center:
var d = 20;
var nx = 596/d; /* number of circles in a row */
var ny = 255/d; /* number of circles in a columns */
var ic = nx/2;
var jc = ny/2;
let svg = document.querySelector("svg");
for(var i=0;i<nx;i++) {
for(var j=0;j<ny;j++) {
svg.insertAdjacentHTML( 'beforeend','<circle cx="'+(6 + d*i)+'" cy="'+(6 + d*j)+'" r="0" stroke="red" stroke-width="2" fill="transparent"><animate attributeName="r" values="0; 5;0" dur="2s" begin="'
+( Math.sqrt((ic - i)*(ic - i)+(jc - j)*(jc - j))/20)+'s" repeatCount="indefinite" /></circle>');
}
}
<svg width="596" height="255">
</svg>
Add an animated mask with a linearGradient.
<svg width="596" height="255">
<linearGradient id="prog-mask" x1=0% x2="100%" y1="0%" y2="100%">
<stop offset="0%" stop-color="white" stop-opacity="1" />
<stop offset="5%" stop-color="white" stop-opacity="0">
<animate attributeName="offset" values="0; 1" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
<animate attributeName="stop-opacity" values="0; 1" dur="2s" begin="2s" repeatCount="0" fill="freeze" />
</stop>
<stop offset="100%" stop-color="white" stop-opacity="0" />
</linearGradient>
<mask id="prog-render">
<rect x="0" y="0" width="100%" height="100%" fill="url(#prog-mask)"/>
</mask>
<pattern id="pattern-circles" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="6" cy="6" r="3" stroke="red" stroke-width="2" fill="transparent">
<animate attributeName="r" values="0; 5" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
</circle>
</pattern>
<!-- The canvas with our applied pattern -->
<rect x="0" y="0" width="100%" height="100%" fill="url(#pattern-circles)" mask="url(#prog-render)"/>
</svg>
You can fade things in with linearGradients. Here, the linearGradients disappear revealing the pattern below them.
Because we have two linearGradients the animation would look faster in the middle than at the start and end (we're multiplying two opacity numbers) so I'm using keySplines to make the animation faster in the middle and slower at the start and end to counteract that.
<svg width="596" height="255">
<defs>
<pattern id="pattern-circles" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
<circle cx="6" cy="6" r="3" stroke="red" stroke-width="2" fill="none">
</circle>
</pattern>
<linearGradient id="g1" x1="100%" y1="0" x2="0" y2="0">
<stop offset="0%" stop-color="white">
<animate attributeName="stop-opacity" values="1; 0" calcMode="spline" keyTimes="0;1" keySplines="0.5 0 0.5 1" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
</stop>
<stop offset="100%" stop-color="white" stop-opacity="0" />
</linearGradient>
<linearGradient id="g2" x1="0" y1="100%" x2="0" y2="0">
<stop offset="0%" stop-color="white" stop-opacity="1">
<animate attributeName="stop-opacity" values="1; 0" calcMode="spline" keyTimes="0;1" keySplines="0.5 0 0.5 1" dur="2s" begin="0s" repeatCount="0" fill="freeze" />
</stop>
<stop offset="100%" stop-color="white" stop-opacity="0" />
</linearGradient>
</defs>
<rect width="100%" height="100%" fill="url(#pattern-circles)" />
<rect width="100%" height="100%" fill="url(#g1)"/>
<rect width="100%" height="100%" fill="url(#g2)"/>
</svg>
I would like to add text inside an element such that my intro is behind a rectangular, transparent element.
I tried adding text inside an SVG like this
<svg height="150" width="500">
<text x="100" y="30" fill="red">I love SVG!</text>
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
</svg>
However I can't Send the object backwards. Is this even possible?
Is there a better approach I can use to meet this objective rather than the solution I'm trying to use?
Are you just talking about whether the text is behind the oval, or on top of it?
If so, just changing the order of elements fixes that:
<svg height="150" width="500">
<defs>
<radialGradient id="grad1" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
<stop offset="0%" style="stop-color:rgb(255,255,255);
stop-opacity:0" />
<stop offset="100%" style="stop-color:rgb(0,0,255);stop-opacity:1" />
</radialGradient>
</defs>
<ellipse cx="200" cy="70" rx="85" ry="55" fill="url(#grad1)" />
<text x="100" y="30" fill="red">I love SVG!</text>
</svg>
Or is there something else you're trying to do? (Please note, even with the text on top of the oval, the contrast isn't that great, and it's still hard to read.)