I want to set a faint yellow color lighting effect (car head lights) to my svg element. It is possible to do this on mouse hovering?
Here is my car's svg element:
<path d="M-286.912,486.288c-5.668,11.518-10.595,21.793-15.771,31.941c-2.707,5.307-7.279,7.822-13.323,7.754
c-8.107-0.09-16.215-0.022-24.236-0.022c-2.128-14.509,10.613-32.582,25.01-35.839c7.575-1.714,15.223-3.119,22.869-4.498
C-291.004,485.378-289.497,485.944-286.912,486.288z M-289.368,487.823c-0.416-0.483-0.833-0.966-1.249-1.449
c-7.414,1.581-14.821,3.191-22.242,4.736c-16.099,3.351-22.808,14.912-26.056,29.591c-0.493,2.228-0.81,4.176,2.248,4.142
c7.625-0.084,15.336,0.294,22.832-0.779c3.441-0.492,7.727-3.229,9.433-6.206C-298.845,508.159-294.301,497.879-289.368,487.823z"/>
The SVG data you posted doesn't seem to do anything. However, you can use SVG filters to add glare effects. Here's an example:
svg:hover .headlight {
fill: yellow;
filter: url(#f1);
}
<svg width="600" height="300" viewBox="0 0 600 300">
<defs>
<filter id="f1" x="-25%" y="-25%" width="150%" height="150%">
<feGaussianBlur in="SourceGraphic" stdDeviation="15" result="glare" />
<feMerge>
<feMergeNode in="glare" />
<feMergeNode in="SourceGraphic" />
</feMerge>
</filter>
</defs>
<path fill="black" stroke="none" d="M0 0 600 0 600 300 0 300z" />
<circle cx="150" cy="150" r="50" fill="darkslategray" class="headlight" />
<circle cx="450" cy="150" r="50" fill="darkslategray" class="headlight" />
</svg>
Related
I need your help with the implementation of svg animation.
https://youtu.be/lrWjkARl8Zg
(sorry for the poor video quality)
And I have such a structure of svg
I need the arrow (class = "arrow") itself to move along long lines and draw it.
<svg class="vector" width="1193" height="329" viewBox="0 0 1193 329" fill="none" xmlns="http://www.w3.org/2000/svg">
<path class="long_line" d="M1436 327.98L84.7148 327.98C73.8082 328.219 62.9639 326.275 52.818 322.262C42.6722 318.249 33.4293 312.249 25.6315 304.613C17.8337 296.977 11.6384 287.858 7.40866 277.793C3.17891 267.728 0.999997 256.919 0.999996 246C0.999996 235.081 3.17891 224.272 7.40866 214.207C11.6384 204.142 17.8337 195.023 25.6315 187.387C33.4292 179.751 42.6722 173.75 52.818 169.738C62.9638 165.725 73.8082 163.781 84.7147 164.02L589.173 164.02" stroke="black" stroke-width="2" stroke-miterlimit="10"/>
<path class="arrow" d="M544 204L589 164L548 124" stroke="black" stroke-width="2"/>
<path class="arrow" d="M504 1L459 41L500 81" stroke="black" stroke-width="2"/>
<path class="short_line" d="M1308 41L459 41" stroke="black" stroke-width="2" stroke-miterlimit="10"/>
</svg>
Advise which library I can use
You could do this using svg smil animations:
A Guide to SVG Animations (SMIL)
Your arrow animations could be achieved by
<animateMotion> for moving the arrow element and
animating the stroke-dashoffset property.
Animated example
svg {
border: 1px solid #ccc;
width: 33%;
overflow: visible;
display: block;
}
path {
stroke-width: 10;
stroke: #000;
}
<p>Click on animation for replay</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 500">
<defs>
<path id="arrow" fill="none" d="M-45,40L0,0l-41-40" />
</defs>
<use id="arrow1" href="#arrow" />
<use id="arrow2" href="#arrow" />
<g id="graphics">
<rect id="graphics" fill="#fff" fill-opacity="0" x="0" y="0" width="100%" height="100%" />
<path id="mpath-long" fill="none" pathLength="100" stroke-width="2" stroke-miterlimit="10" stroke-dashoffset="100" stroke-dasharray="100" d="M1571,413H219.7
c-10.9,0.2-21.8-1.7-31.9-5.7c-10.1-4-19.4-10-27.2-17.6c-7.8-7.6-14-16.8-18.2-26.8S136,341.9,136,331s2.2-21.7,6.4-31.8
s10.4-19.2,18.2-26.8c7.8-7.6,17-13.6,27.2-17.6c10.1-4,21-6,31.9-5.7h504.5" />
<path id="mpath-short" fill="none" pathLength="100" stroke-width="2" stroke-miterlimit="10" stroke-dashoffset="100" stroke-dasharray="100" d="M1443,126H594" />
</g>
<animateMotion href="#arrow1" dur="2" rotate="auto" repeatCount="1" begin="0;graphics.click" fill="freeze">
<mpath href="#mpath-long" />
</animateMotion>
<animate attributeType="XML" href="#mpath-long" id="strokeAni" attributeName="stroke-dashoffset" from="100" to="0" dur="2s" repeatCount="1" begin="0;graphics.click" fill="freeze" />
<animateMotion href="#arrow2" dur="2s" rotate="auto" repeatCount="1" begin="0;graphics.click" fill="freeze">
<mpath href="#mpath-short" />
</animateMotion>
<animate attributeType="XML" href="#mpath-short" attributeName="stroke-dashoffset" from="100" to="0" dur="2s" repeatCount="1" fill="freeze" begin="0;graphics.click" />
</svg>
Quite likely, you will have to tweak your svg viewBox to get the desired result.
A common trick is to position element that's supposed to move along the motion path to x/y = 0.
Static example
<style>
svg{
border: 1px solid #ccc;
width: 33%;
overflow:visible;
display:block;
}
path{
stroke-width:10;
stroke: #000;
}
</style>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 500">
<defs>
<path id="arrow" fill="none" d="M-45,40L0,0l-41-40" />
</defs>
<use id="arrow1" href="#arrow" />
<use id="arrow2" href="#arrow" />
<g id="graphics">
<rect id="graphics" fill="#fff" fill-opacity="0" x="0" y="0" width="100%" height="100%" />
<path id="mpath-long" fill="none" pathLength="100" stroke-width="2" stroke-miterlimit="10" stroke-dashoffset="0" stroke-dasharray="100" d="M1571,413H219.7
c-10.9,0.2-21.8-1.7-31.9-5.7c-10.1-4-19.4-10-27.2-17.6c-7.8-7.6-14-16.8-18.2-26.8S136,341.9,136,331s2.2-21.7,6.4-31.8
s10.4-19.2,18.2-26.8c7.8-7.6,17-13.6,27.2-17.6c10.1-4,21-6,31.9-5.7h504.5" />
<path id="mpath-short" fill="none" pathLength="100" stroke-width="2" stroke-miterlimit="10" stroke-dashoffset="0" stroke-dasharray="100" d="M1443,126H594" />
</g>
</svg>
I am a total newbie trying to make an interactive SVG - preferably without any external scripting. The effect that I am aiming for is to have one SVG element act as an interactive toggle to make another element appear and disappear.
Please find below a simple version where the text "Toggle" acts as the toggle. On click, this will animate the opacity attribute of the rectangle from 0 to 1 making it appear.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext.click" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
Any subsequent click will now just simply repeat that same animation. But I want any second (fourth, sixth, etc.) click to reverse the animation (i.e. make the rectangle disappear). In other words to truly act as a toggle.
Any advice on how to achieve this effect with as little code and/or invisible elements as possible would be greatly appreciated.
Thanks!
This is how I would do it: I'm using 2 overlapped text elements and I'm setting the pointer events to all or none on click: This way you'll click once on one text and next on the other.
The rect has 2 animate elements: one animation will start when you click on the first text, the second animation will start when clicking on the second text.
text{font-size:8.46667px;line-height:1.25;font-family:sans-serif;stroke-width:0.264583;}
<svg width="300" viewBox="0 0 47.652294 10.096307" id="svg8">
<g id="layer1" transform="translate(-29.085516,-61.315985)">
<rect fill="#ff0000" opacity="0" id="rect" width="9.8317242" height="9.8317242" x="66.773796" y="61.448277">
<animate attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="toggletext1.click" />
<animate attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="toggletext2.click" />
</rect>
<text x="29.085516" y="68.002762" id="toggletext2">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext1.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
<text x="29.085516" y="68.002762" id="toggletext1">
<tspan x="29.085516" y="68.002762">Toggle</tspan>
<set attributeName="pointer-events" from="none" to="all" begin="toggletext2.click" />
<set attributeName="pointer-events" from="all" to="none" begin=".click" />
</text>
</g>
</svg>
Add a second rectangle fade animation
<animate id="hide" attributeName="opacity" fill="freeze"
from="1" to="0" dur="2s" begin="indefinite" />
And add a JS trigger that toggles the animation of the appearance and disappearance of the rectangle
var svg_1 = document.getElementById("svg8"),
hide = document.getElementById("hide"),
visable = document.getElementById("visable");
let flag = true;
svg_1.addEventListener('click', function() {
if (flag == true) {
visable.beginElement();
flag = false;
} else {
hide.beginElement();
flag = true;
}
});
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
width="47.652294mm"
height="10.096307mm"
viewBox="0 0 47.652294 10.096307"
version="1.1"
id="svg8">
<style
id="style861"></style>
<defs
id="defs2" />
<g
id="layer1"
transform="translate(-29.085516,-61.315985)">
<rect
fill="#ff0000"
opacity="0"
id="rect"
width="9.8317242"
height="9.8317242"
x="66.773796"
y="61.448277">
<animate id="visable" attributeName="opacity" fill="freeze" from="0" to="1" dur="2s" begin="indefinite" />
<animate id="hide" attributeName="opacity" fill="freeze" from="1" to="0" dur="2s" begin="indefinite" />
</rect>
<text
xml:space="preserve"
style="font-size:8.46667px;line-height:1.25;font-family:sans-serif;-inkscape-font-specification:sans-serif;stroke-width:0.264583"
x="29.085516"
y="68.002762"
id="toggletext"><tspan
id="tspan857"
x="29.085516"
y="68.002762"
style="stroke-width:0.264583">Toggle</tspan></text>
</g>
</svg>
Although I like the No-JavaScript pointer-events method; this is how I would do it:
When OP says: preferably without any external scripting.
I presume he means no 3rd party libraries.
So I would use a Custom Element <svg-toggle> (supported in all modern browsers)
that creates the SVG for any number of toggles you want
To toggle animation:
switch the from and to parameters on every click
restart the animation
<style>
svg {
display: inline-block; width: 30%; vertical-align: top;
cursor: pointer; background: teal; color: white;
}
</style>
<svg-toggle></svg-toggle>
<svg-toggle color="yellow"></svg-toggle>
<svg-toggle color="blue" label="Blue" duration=".5"></svg-toggle>
<script>
customElements.define('svg-toggle', class extends HTMLElement {
connectedCallback() {
this.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">
${this.getAttribute("label")||'Toggle'}</text>
<rect fill="${this.getAttribute("color")||'red'}" x='33' y="3" width="12" height="12">
<animate attributeName="opacity" dur="${this.getAttribute("duration")||2}s" from="0" to="1" fill="freeze" begin="indefinite"/>
</rect></svg>`;
this.animate = this.querySelector("animate");
this.onclick = (evt) => this.toggle();
}
toggle( // method, so can be called from Javascript
from = this.animate.getAttribute("from"), // optional from/to parameters
to = this.animate.getAttribute("to"),
) {
this.animate.setAttribute( "from", to );
this.animate.setAttribute( "to" , from );
this.animate.beginElement();
}
});
</script>
I don't want modern W3C standard Web Components mumbo jumbo...
Then stick the JavaScript on every SVG:
<svg
onclick="{
let a = this.querySelector('animate');
let from = a.getAttribute('from');
a.setAttribute('from',a.getAttribute('to'));
a.setAttribute('to',from);
a.beginElement();
}"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 18">
<text x="2" y="12" font-size="10px" fill="currentColor">Gold</text>
<rect fill="gold" x="33" y="3" width="12" height="12">
<animate attributeName="opacity" dur=".3s" from="0" to="1"
fill="freeze" begin="indefinite"></animate>
</rect>
</svg>
I don't want JavaScript
See Enxaneta his pointer-events answer
Consider the following SVG code for moving a circle around the center of the screen, with hard-coded dimensions:
<svg xmlns="http://www.w3.org/2000/svg">
<g>
<ellipse id="circ" style="fill:#000000"
cx="60%" cy="50%"
rx="10" ry="10" />
<!--Assuming window size is 1000x1000-->
<animateTransform attributeName="transform"
type="rotate" dur="10s"
from="0,500,500"
to="360,500,500"
repeatCount="indefinite"/>
</g>
</svg>
If I try to provide the center of rotation in percent, the animation doesn't work at all:
<animateTransform attributeName="transform"
type="rotate" dur="10s"
from="0,50%,50%"
to="360,50%,50%"
repeatCount="indefinite"/>
How do I fix this?
Set a viewBox on your SVG, then whatever size you make it, the ellipse will rotate around the centre of it.
viewBox="0 0 1000 1000"
The value of 1000 for width and height here is chosen because it would make 500 be the centre.
svg:nth-child(1) {
width: 200px;
}
svg:nth-child(2) {
width: 500px;
}
svg {
border: solid 1px green;
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
<g>
<ellipse id="circ" style="fill:#000000"
cx="60%" cy="50%"
rx="10" ry="10" />
<!--Assuming window size is 1000x1000-->
<animateTransform attributeName="transform"
type="rotate" dur="10s"
from="0,500,500"
to="360,500,500"
repeatCount="indefinite"/>
</g>
</svg>
<!-- An exact duplicate of th first one -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000">
<g>
<ellipse id="circ" style="fill:#000000"
cx="60%" cy="50%"
rx="10" ry="10" />
<!--Assuming window size is 1000x1000-->
<animateTransform attributeName="transform"
type="rotate" dur="10s"
from="0,500,500"
to="360,500,500"
repeatCount="indefinite"/>
</g>
</svg>
I have a below code,
<div id="akbar">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="400" height="200" viewBox="0 0 400 200">
<g transform="scale(1,-1) translate(0,-200)">
<rect x="50" y="0" fill="#f00" width="100" height="100">
<animate attributeName="height"
from="0"
to="100"
dur="0.5s"
fill="freeze" />
</rect>
<rect x="150" y="0" fill="#f70" width="100" height="200">
<animate
attributeName="height"
from="0"
to="200"
dur="0.5s"
fill="freeze" />
</rect>
<rect x="250" y="0" fill="#ec0" width="100" height="150">
<animate
attributeName="height"
from="0"
to="150"
dur="0.5s"
fill="freeze" />
</rect>
</g>
</svg>
</div>
I would like to animate the svg rectangle to grow like music waves.
How can I achieve that?
I need this behavior
You can achieve it using
values,
keyTimes
and keySplines
attributes of an <animate> tag.
JSfiddle example.
I stripped your example to single column only:
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="400" height="200" viewBox="0 0 400 200">
<g transform="scale(1,-1) translate(0,-200)">
<rect x="50" y="0" fill="#f00" width="100" height="100">
<animate
attributeName="height"
from="0"
to="100"
dur="1s"
fill="freeze"
values="0; 200; 150; 160; 150; 160"
keyTimes="0; 0.2; 0.4; 0.6; 0.8; 1"
keySplines=".42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;
.42 0 1 1;
0 0 .59 1;"
/>
</rect>
</g>
</svg>
As it is not perfect yet, you can play around with the attributes to adjust the timing better (keySplines especially) and make it more music waves like.
As you can see on the provided example, single column steps of movements are:
All the way from bottom to top
Then, from top to ~83% of height
Then, from ~83% to ~88%,
Then, from ~88% to ~83%,
Then, from ~83% to ~88%
I guess that increasing the difference between those repeating percentage numbers (83 and 88) will give you slightly better effect than mine (which is based on 75% and 80%, easier to calculate on widht: 200px), but it is close.
Also take a look at CSS tricks article on SVG animation, it is very thorough and covers all the details about mentioned attributes - and much more.
I want to make an animation that looks like a google search box
I have a text path where the word appears in a 'bold' font.
I would like the word to animate so that the first letter appears 'regular', then the first and second, then the first second and third etc.
Is this possible to do with an svg animation?
<svg width="100%" height="100%" viewBox="30 -50 600 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<path id="path1">
<animate attributeName="d" from="m100,50 h0" to="m100,50 h1100" dur="5s" begin="0s" repeatCount="indefinite" />
</path>
// this text "types"
<text font-size="90" font-family="Montserrat" fill='black'>
<textPath xlink:href="#path1">Google is</textPath>
</text>
// I want this text to animate the "font-style"
<text font-size="90" font-family="Montserrat" fill='black' x="100" y="200">
Google is gold
<animate attributeType="CSS" .... />
</text>
You'd need to put the letters in separate tags within the textPath so you can target them individually with animations.
I've just done the first letter but you could extend this to all the letters if you wished.
<svg width="100%" height="100%" viewBox="30 -50 600 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<path id="path1">
<animate attributeName="d" from="m100,50 h0" to="m100,50 h1100" dur="5s" begin="0s" repeatCount="indefinite" />
</path>
// this text "types"
<text font-size="90" font-family="Montserrat" fill='black'>
<textPath xlink:href="#path1">Google is</textPath>
</text>
// I want this text to animate the "font-style"
<text font-size="90" font-family="Montserrat" fill='black' x="100" y="200">
<tspan>G<animate attributeType="CSS" attributeName="font-weight" from="700" to="100" dur="1s" begin="0s" repeatCount="indefinite"/></tspan>oogle is gold
</text>