Is possible center <g> in <svg>? - svg

I searched on the web and I do not found a solution for my problem, is possible to do that, center my element depending of size of my parent content.
<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" stroke="#333">
<g fill="none" fill-rule="evenodd">
<g transform="translate(1 1)" stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18c0-9.94-8.06-18-18-18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</g>
</svg>

I would put the loader in a symbol. Also I would give the loader and the svg element a viewBox attribute.
svg{border:1px solid;}
<svg width="100%" viewBox="-250 -50 500 100" xmlns="http://www.w3.org/2000/svg" stroke="#333">
<symbol id="the_symbol" viewBox="-2 -2 40 40">
<g stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18A18,18 0 0 0 0,18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</symbol>
<use xlink:href="#the_symbol" x="-20" y="-20" width="36" height="36" fill="none" />
</svg>
UPDATE
The OP is commenting that they want the root svg to take various sizes, while the loader has to be always the same size.
//the size and position of the symbol
let o = {x:36,y:18}
function init(){
let p = getsize(o);
//reset the size and position of the use element
theUse.setAttributeNS(null,"width",p.x)
theUse.setAttributeNS(null,"height",p.x)
theUse.setAttributeNS(null,"x",250-p.y)
theUse.setAttributeNS(null,"y",50-p.y)
}
// a function to calculate the size and position of the use element
function getsize(o){
var p = svg.createSVGPoint();
p.x= o.x;
p.y= o.y;
p = p.matrixTransform(svg.getScreenCTM().inverse());
return p
}
setTimeout(function() {
init();
addEventListener('resize', init, false);
}, 15);
svg{border:1px solid;}
symbol{overflow:visible}
<svg id="svg" width="100%" height="100%" viewBox="0 0 500 100" xmlns="http://www.w3.org/2000/svg" stroke="#333">
<symbol id="the_symbol" viewBox="0 0 36 36">
<g stroke-width="2">
<circle stroke-opacity=".5" cx="18" cy="18" r="18"/>
<path d="M36 18A18,18 0 0 0 0,18">
<animateTransform
attributeName="transform"
type="rotate"
from="0 18 18"
to="360 18 18"
dur="1s"
repeatCount="indefinite"/>
</path>
</g>
</symbol>
<use id="theUse" xlink:href="#the_symbol" fill="none" />
</svg>

Related

How can I animate a <path> object in SVG

<g id = "doc">
/*Doc*/
<path d = "M 100 100 L 150 100 L 170 120 L 170 190 L 100 190 L 100 100 Z M 150 100 L 150 120
L 170 120 M 120 140 L 150 140 M 120 160 L 150 160" stroke = "black" stroke-width = "8px" fill = "white" transform = "translate(350, 110)">
</path>
</g>
<animate xlink:href = "#doc" attributeName = "x" from = "450" to = "1000" dur = "4" repeatCount = "indefinite" />
If I try to animate the with the id = "doc", which is located inside a tag, the animation is not working. Thanks for help!
Your SVG was a bloated file icon:
The only animation I can think of is:
<svg viewBox="0 0 90 110" style="background:pink;height:180px">
<path d="m10 10 50 0 20 20 0 70-70 0 0-90zm50 0 0 20 20 0m-50 20 30 0m-30 20 30 0"
stroke="black" stroke-width="8px" fill="white">
<animatemotion path="m0 0h100" dur="4s" repeatCount="indefinite"/>
</path>
</svg>
Update - animationMotion doesn't work in Chrome IMG and OBJECT tags
animationMotion does work inside an IMG tag in FireFox
To make it work in Chrome, change it to an animateTransform animation
Since my favorite pastime on a lazy Sunday is to clean SVGs, here is your code:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1320 520" style="background:pink" fill="black" stroke="black">
<g id="deviceleft">
<rect x="355" y="80" width="12" height="85" rx="5" />
<rect x="355" y="185" width="12" height="40" rx="5" />
<rect x="10" y="10" width="350" height="500" stroke-width="5" rx="10" fill="lightblue" />
<circle cx="335" cy="35" r="8" fill="grey" stroke-width="7" />
</g>
<g id="deviceright">
<rect x="1305" y="110" width="12" height="85" rx="5" />
<rect x="1305" y="210" width="12" height="40" rx="5" />
<rect x="1010" y="60" width="300" height="400" fill="grey" stroke-width="5" rx="10" />
<rect x="1105" y="60" width="110" height="25" rx="10" />
<circle cx="1185" cy="72" r="6" stroke="grey" stroke-width="4" />
<rect x="1135" y="68" width="35" height="8" fill="darkgrey" rx="5" />
</g>
<g transform="translate(0 175)">
<path d="m435 60 500 0m-1 0-19-10m19 10-19 10" stroke-width="6" />
<path d="m385 20 50 0 20 20 0 70-70 0 0-90zm50 0 0 20 20 0m-50 20 30 0m-30 20 30 0" stroke-width="8"
fill="white">
<animateTransform attributeName="transform" type="translate" dur="4s" values="50 0;450 0"
repeatCount="indefinite" />
</path>
</g>
</svg>

SVG pathLength on circle not defining circle's circumference?

According to https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle, the pathLength attribute is supposed to define the "total length for the circle's circumference", however, when I use stroke-dasharray, it doesn't seem to line up?
<svg width="100" height="100" viewBox="0 0 1 1">
<circle
cx="0.5"
cy="0.5"
stroke-width="0.5"
r="0.25"
pathLength="360"
stroke-dasharray="180 360"
stroke-dashoffset="0"
stroke="black"
fill="none"
/>
</svg>
According to https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/pathLength as well, this should be half-filled, thus a semi-circle, however it's slightly less than a semi-circle. If I have stroke-dasharray set to 360 360 instead, it doesn't fully close when, if I understand how the pathLength attribute is supposed to work, it should.
Am I misunderstanding pathLength or stroke-dasharray?
Edit: it seems to work differently across browsers...?
Chromium:
Firefox:
Safari:
Edit 2:
When I get their total lengths, it's different across browsers! Is this intended? Is it possible to solve this issue?
As #enxaneta commented. The smaller the viewBox, the bigger the problem is. In this example it is only the last one (viewBox="0 0 100 100") that looks OK in Chrome.
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 1 1">
<path d="M0 .5 L1 .5" stroke-width=".01" stroke="gray"/>
<circle cx=".5" cy=".5" r=".4" stroke="black" stroke-width=".2" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 10 10">
<path d="M0 5 L10 5" stroke-width=".1" stroke="gray"/>
<circle cx="5" cy="5" r="4" stroke="black" stroke-width="2" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 50 50">
<path d="M0 25 L50 25" stroke-width=".5" stroke="gray"/>
<circle cx="25" cy="25" r="20" stroke="black" stroke-width="10" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>
<svg xmlns="http//www.w3.org/2000/svg" width="130" viewBox="0 0 100 100">
<path d="M0 50 L100 50" stroke-width="1" stroke="gray"/>
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="20" fill="none" stroke-dasharray="180 360" pathLength="360" />
</svg>

svg circle color change at certain point

I have a svg that circle is moving around through path. I want the circles' color are changed at some points (ex. mid of the path)
https://codepen.io/lzwdct/pen/poRYVXZ
<circle r="20" fill="blue" mask="url(#myMask)">
<animateMotion dur="5s" repeatCount="indefinite"
path="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13 M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
c-48.89-48.89-128.09-48.95-176.91-0.13" />
</circle>
Please guide me how to update the color. The color eventually will be changed multiple times with long paths.
I'm not sure if there's anything in SVG that would enable you to do that directly.
But you can check currentTime vs the duration of the animateMotion element and set a color via javascript based on that.
const color = (n) => {
const R = Math.round((255 * n) / 100);
const G = Math.round((255 * (100 - n)) / 100);
const B = 0;
return `rgb(${R}, ${G}, ${B})`;
};
const circles = document.querySelectorAll("circle");
window.setInterval(() => {
circles.forEach(circle => {
const ani = circle.querySelector('animateMotion');
const duration = ani.getSimpleDuration();
const currentTime = ani.getCurrentTime() % duration;
const colorValue = color((currentTime / duration) * 100);
circle.parentNode.style.fill = colorValue;
});
}, 500);
circle {
transition: 500ms;
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 2549.62 3338.72" style="enable-background:new 0 0 2549.62 3338.72;" xml:space="preserve">
<style type="text/css">
.st0{fill:none;stroke:#8EA5AE;stroke-width:50;stroke-miterlimit:10;}
.st1{fill:none;stroke:#8EA5AE;stroke-width:50;stroke-linecap:round;stroke-miterlimit:10;}
.st2{fill:none;stroke:#758992;stroke-width:50;stroke-miterlimit:10;}
.st3{fill:none;stroke:#758992;stroke-width:50;stroke-linecap:round;stroke-miterlimit:10;}
.st4{fill:none;stroke:#4E5F65;stroke-width:50;stroke-miterlimit:10;}
.st5{fill:none;stroke:#4E5F65;stroke-width:50;stroke-linecap:round;stroke-miterlimit:10;}
</style>
<g>
<mask id="myMask">
<!-- Pixels under white are rendered -->
<rect x="0" y="0" width="1015" height="855" fill="white" />
<!-- Pixels under black are hidden -->
<rect class="moveme" x="315" y="335" height="150" width="150" transform="rotate(45 395 395)">
<animateTransform attributeName="transform"
attributeType="XML"
type="scale"
keyTimes="0; 0.25999; 0.26; 1"
values="1; 1; 0; 0"
dur="5s"
additive="sum"
repeatCount="indefinite"/>
</rect>
</mask>
<g>
<path class="st0" d="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13" />
<path class="st1" d="M683.19,30.7L258.92,454.97c-29.29,29.29-76.78,29.29-106.07,0c-29.29-29.29-29.29-76.78,0-106.07
c29.29-29.29,76.78-29.29,106.07,0"/>
<path class="st2" d="M753.9,101.42c0,0-424.26,424.26-424.26,424.26c-68.34,68.34-179.15,68.34-247.49,0s-68.34-179.15,0-247.49
s179.15-68.34,247.49,0"/>
</g>
<g>
<path class="st0" d="M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
c-48.89-48.89-128.09-48.95-176.91-0.13"/>
<path class="st2" d="M329.63,278.19L753.9,702.46c29.29,29.29,76.78,29.29,106.07,0c29.29-29.29,29.29-76.78,0-106.07
s-76.78-29.29-106.07,0"/>
<path class="st1" d="M258.92,348.9c0,0,424.26,424.26,424.26,424.26c68.34,68.34,179.15,68.34,247.49,0s68.34-179.15,0-247.49
s-179.15-68.34-247.49,0"/>
</g>
</g>
<g mask="url(#myMask)">
<circle r="20" mask="url(#myMask)">
<animateMotion dur="5s" repeatCount="indefinite"
path="M718.54,66.06L294.41,490.19c-48.89,48.89-128.09,48.95-176.91,0.13c-48.82-48.82-48.76-128.02,0.13-176.91
s128.09-48.95,176.91-0.13 M294.28,313.55l424.13,424.13c48.89,48.89,128.09,48.95,176.91,0.13c48.82-48.82,48.76-128.02-0.13-176.91
c-48.89-48.89-128.09-48.95-176.91-0.13" />
</circle>
<circle r="20">
<animateMotion dur="5s" repeatCount="indefinite"
path="M753.9,101.42c0,0-424.26,424.26-424.26,424.26c-68.34,68.34-179.15,68.34-247.49,0s-68.34-179.15,0-247.49
s179.15-68.34,247.49,0 M329.63,278.19L753.9,702.46c29.29,29.29,76.78,29.29,106.07,0c29.29-29.29,29.29-76.78,0-106.07 s-76.78-29.29-106.07,0" />
</circle>
<circle r="20">
<animateMotion id="circle1" dur="5s" repeatCount="indefinite"
path="M683.19,30.7L258.92,454.97c-29.29,29.29-76.78,29.29-106.07,0c-29.29-29.29-29.29-76.78,0-106.07 c29.29-29.29,76.78-29.29,106.07,0 M258.92,348.9c0,0,424.26,424.26,424.26,424.26c68.34,68.34,179.15,68.34,247.49,0s68.34-179.15,0-247.49 s-179.15-68.34-247.49,0" /></circle></g>
</svg>
You need to tweak it for your paths, basic concept is to add an animate on the element you want to change and use values and keyTimes (the whole animation is 0 to 1)
As you will notice, you get a color-gradient for free.
If you don't want that, add more keyTimes so the color fades occur faster
<svg width="450" height="180">
<path id="PATH" d="M 50 90 H400" stroke="black"/>
<g>
<circle class="circle" r="30" fill="black"></circle>
<circle class="circle" r=25 fill="red" >
<animate
attributeName="fill"
attributeType="XML"
values="red;green;yellow;hotpink;blue"
keyTimes= "0;0.4;0.6;0.8;1"
dur="3s"
repeatCount="indefinite"/>
</circle>
<animateMotion dur="3s" repeatCount="indefinite">
<mpath href="#PATH" />
</animateMotion>
</g>
</svg>
svga

How to start svg pattern from begin for two elements separately and how to setup right coordinate system?

I have two thick lines and I want to apply pattern for this lines. Lines should have the same pattern, but start of drawing pattern should start from (0, 0) for each line separately. In my experiment http://jsfiddle.net/69t09wey/ patterns apply like mask. I.e pattern apply for whole svg canvas as invisible layer and where line is visible, pattern also visible.
<svg viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern-1" width="20" height="20" x="0" y="0" patternUnits = "userSpaceOnUse" >
<path d="M 0 0 L 20 20" fill="none" stroke="#0000ff" stroke-width="1"></path>
</pattern>
<g transform="scale(5)">
<rect x="1" y="1" width="1000" height="1000"
fill="none" stroke="blue" />
<path d="M 1 9 L 200 9"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
<path d="M 1 53 L 200 53"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
</g>
</svg>
If you make your lines the same. Then move the second one by applying a transform. That will shift the coordinate space of the pattern.
<svg viewBox="0 0 1000 1000"
xmlns="http://www.w3.org/2000/svg" version="1.1">
<pattern id="pattern-1" width="20" height="20" x="0" y="0" patternUnits = "userSpaceOnUse" >
<path d="M 0 0 L 20 20" fill="none" stroke="#0000ff" stroke-width="1"></path>
</pattern>
<g transform="scale(5)">
<rect x="1" y="1" width="1000" height="1000"
fill="none" stroke="none" />
<path d="M 1 9 L 200 9"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
<path d="M 1 9 L 200 9" transform="translate(0,44)"
fill="red" stroke="url(#pattern-1)" stroke-width="20" />
</g>
</svg>

svg mouseover doesn't work in zurb foundation nav topbar

I'm working with zurb foudation and have a roll over on an svg that is within the header. If the svg is under
then the roll over effect on the svg doesn't work. but if I remove either the section tag or the data-topbar attribute then it works fine. you can see an example of all three variations here:
http://firefields.com/foundation-5.5.0/icon-issue.html
and this is the svg code
<svg version="1.1" id="headTest" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 42 42" enable-background="new 0 0 42 42" xml:space="preserve" >
<defs>
<mask id="Mask">
<path fill="#ffffff" d="M25.4,12.7L15.3,28.6c0.2,0.2,0.4,0.4,0.6,0.5c0.4,0.2,0.7,0.4,1.2,0.5L27,13.9c-0.3-0.4-0.6-0.7-0.8-0.8
C25.9,12.9,25.7,12.8,25.4,12.7z"/>
<path fill="#ffffff" d="M14.3,25.9c0.3-0.2,0.6-0.3,0.8-0.4l1.5-2.3c-1,0.1-2.1,0.4-3.3,0.9c-2.1,1.1-4.2,3-5.8,5.4
c-0.5,0.7-0.8,1.4-1.1,2.1c0.5,0.7,0.9,1.2,1.5,1.8c0.4-0.9,0.8-1.9,1.4-2.8C10.6,28.5,12.4,26.8,14.3,25.9z"/>
<path fill="#ffffff" d="M20.3,37.6c1.6-2.5,2.5-5.3,2.5-7.8c0-1.7-0.4-3.2-1-4.3l-1.2,2.1c0.2,0.7,0.4,1.4,0.3,2.2
c0,2.1-0.8,4.6-2.2,6.7c-0.5,0.7-1,1.4-1.5,2c-2.8-0.7-5.3-1.9-7.6-3.6C9.2,35.6,9.1,36.3,9,37c2.6,2,5.6,3.2,8.8,3.7
c0.6-0.6,1.1-1.1,1.6-1.8l0,0c0,0,0,0,0.1,0C19.7,38.5,20,38.1,20.3,37.6z"/>
<path fill="#ffffff" d="M38.7,12c-0.8-1.7-2-3.3-3.3-4.6c-0.1,0.7-0.4,1.5-0.7,2.2c0,0,0,0.1,0.1,0.1l-0.1-0.1c-0.4,1-0.8,2-1.5,3
c-1.4,2.1-3.2,3.8-5,4.8c-0.7,0.3-1.3,0.6-1.9,0.7l-1.2,2.1c1.3,0.1,2.7-0.3,4.1-0.9c2.1-1.1,4.2-3.1,5.8-5.5
c0.5-0.7,0.8-1.4,1.1-2.1c0.3,0.5,0.6,0.8,0.7,1.3c4.5,8.9,0.9,19.7-7.9,24.2c-2.4,1.2-4.9,1.9-7.5,1.9c-0.5,0.7-0.9,1.4-1.5,2
c3.3,0.2,6.7-0.6,9.9-2.1C39.9,33.9,43.8,21.8,38.7,12z"/>
<path fill="#ffffff" d="M12.9,5c2.9-1.5,6-2.1,9.1-1.9c0.6-0.7,1.1-1.3,1.7-1.9c-3.8-0.5-7.8,0.1-11.6,2c-9.9,4.9-13.9,17-8.9,26.8
c1,2.1,2.4,3.9,4.1,5.5c0.1-0.7,0.4-1.5,0.7-2.1c-1.1-1.2-2.1-2.6-3-4.2C0.5,20.3,4,9.5,12.9,5z"/>
<path fill="#ffffff" d="M22.4,5.6c-1.6,2.5-2.5,5.3-2.5,7.8c0,1.4,0.2,2.6,0.7,3.5l1.4-2.2c-0.1-0.4-0.1-0.8-0.1-1.3
c0-2.1,0.8-4.6,2.2-6.7c0.7-1.1,1.4-2.1,2.1-2.8c2.6,0.8,5,2.1,7.1,4.1c0.3-0.8,0.5-1.6,0.5-2.2c-2.3-2-5-3.3-7.9-4
c-0.7,0.5-1.2,1-1.8,1.7c0.3,0.1,0.2,0-0.1,0C23.4,4,22.9,4.8,22.4,5.6z"/>
</mask>
</defs>
<g mask="url(#Mask)">
<circle fill="#222222" class="icon-background-circle" cx="21" cy="21" r="21"/>
<circle fill="#73e8eb" class="icon-foreground-circle" cx="21" cy="21" r="0">
<animate attributeType="xml" attributeName="r" begin="hoverZone.mouseover" to="21" dur="0.15s" fill="freeze" />
<animate attributeType="xml" attributeName="r" begin="hoverZone.mouseout" to="0" dur="0.15s" fill="freeze" />
</circle>
</g>
<rect id="hoverZone" x="0" y="0" width="42" height="42" fill-opacity="0" />
</svg>
hope you can help.
It has nothing to do with the <section> element.
When an an SVG is embedded via the <img> element, animations are allowed, but interaction (such as mouse events) are not. This is for privacy reasons.
Use <object> or <embed> instead.

Resources