viewbox and icon positioning in SVG - html

I just have this very simple svg below;
<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">
<g stroke="#ccc">
<line x1="133" y1="50" x2="140" y2="40" stroke-width="2"></line>
</g>
<g stroke="#ccc">
<line x1="140" y1="40" x2="200" y2="40" stroke-width="2"></line>
</g>
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)"></circle>
<circle class="circle" cx="100" cy="100" r="57" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="180, 20000" transform="rotate(-90,100,100)"></circle>
<text text-anchor="middle" x="100" y="110" class="icon" style="font-size: 40px" fill="#3498DB"></text>
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">50%</text>
</svg>
</div>
FIDDLE HERE
The viewbox of the svg element is viewBox="0 0 194 300" and the y attribute on the icon is y="110" , my question is , is the Y attibute intentionally 110 ??
I.E. if i wanted to center the icon i would do the following:
(186/2)+ (height of icon/2) // 186 is the height of the viewbox
Am i right in assuming that the value of 110 is added in respect to the height of the viewbox ?

The y value of 110 will have been chosen by the author in order to vertically centre the text in the circle. It is not directly related to the viewBox. It is related to the centre of the circle, the size of the text (22) and to some extent the shape of the glyphs in whatever font is being used. For instance, the height of capital letters may vary for different fonts given the same font size.
SVG does not provide any way to automatically centre text vertically. So you have to position text manually.

Nope
dominant-baseline="central"
x="100"
100 is the vertical center of the circle (ry in the circle element) and dominant-baseline sets the text Y coordinate to the vertical center of the text.

Related

text-anchor="start" not moving text element to the start of the svg element.

I have the following really simple SVG code
<div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">
<g stroke="#ccc">
<line x1="133" y1="50" x2="140" y2="40" stroke-width="2"></line>
</g>
<g stroke="#ccc">
<line x1="140" y1="40" x2="200" y2="40" stroke-width="2"></line>
</g>
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)"></circle>
<circle class="circle" cx="100" cy="100" r="57" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="180, 20000" transform="rotate(-90,100,100)"></circle>
<text text-anchor="middle" x="100" y="110" class="icon" style="font-size: 40px" fill="#3498DB"></text>
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">50%</text>
</svg>
</div>
FIDDLE HERE, My difficulty is regarding the following svg element and how the text-anchor attribute works with it:
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">50%</text>
Now if i change text-anchor="start" , the text element does't really move to the start of the svg element, it rather moves to the start of the line below it , why ? can anybody explain why text-anchor="start" , is not working as expected ?
text-anchor is used to decide whether the X position of the text should be at the start, the end or in the middle of the text. To move the text position change it's X and Y coordinates.
To put the text at the start of the svg:
x="0"
text-anchor="start"
To put the text at the end of the svg:
x="194" //Width of the svg
text-anchor="end"
To put the text in the middle of the svg:
x="97" //Half of the width of the svg
text-anchor="middle"

What are the points in a SVG relative to?

I have the following simple SVG:
<div class="svg-wrapper">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">
<g stroke="#ccc">
<line x1="133" y1="50" x2="140" y2="40" stroke-width="2" />
</g>
<g stroke="#ccc">
<line x1="140" y1="40" x2="200" y2="40" stroke-width="2" />
</g>
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)" />
<circle class="circle" cx="100" cy="100" r="57" class="border" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="0,20000" transform="rotate(-90,100,100)" />
<text text-anchor="middle" x="100" y="110" class="icon" style="font-size: 40px" fill="#3498DB">&#xf206</text>
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">0%</text>
</div>
Now if you notice the SVG carefully, you will see that there are attibutes like the following:
x1="133" y1="50" x2="140" y2="40"
And the following for the circle:
cx="100" cy="100" r="57" ,
I just have one question about this, are these points relative to the document? Now I tried the following:
.svg-wrapper {
position: relative;
top: 200px;
left: 200px;
max-width: 200px;
}
I.E. Moved the container a bit by using position:relative, and the circle moved too, now I beleive if those points where relative to the document the circle should't have moved, but it clearly did and so it means that the following points are not relative to the document:
cx="100" cy="100" r="57"
And
x1="133" y1="50" x2="140" y2="40"
If not the document, then what are these points relative to? Can anybody explain?
The coordinate values are relative to the origin of the SVG, which is the top left of the SVG viewport.
The viewPort is defined by the <svg> element's width and height attributes. If you move the SVG by moving the container it is in, you move the SVG. Just the same as if it was an <img>, <canvas> etc.
It looks like the points are relative to the container, which would be in line with normal HTML in the sense that if you place an element within a container it's position then becomes relative to the container rather than the entire document.

Centering an icon in SVG

I have the following very simple SVG:
<div id="circli" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">
<g stroke="#ccc">
<line x1="133" y1="50" x2="140" y2="40" stroke-width="2"></line>
</g>
<g stroke="#ccc">
<line x1="140" y1="40" x2="200" y2="40" stroke-width="2"></line>
</g>
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)"></circle>
<circle class="circle" cx="100" cy="100" r="57" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="180, 20000" transform="rotate(-90,100,100)"></circle>
<text text-anchor="middle" x="100" y="110" class="icon" style="font-size: 40px" fill="#3498DB"></text>
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">50%</text>
</svg>
</div>
My question is pertaining to the icon and how it is being centered, I am not quite understanding the logic behind how exactly the author of this code has centered the icon. The code for the icon and the circle looks like below:
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)"></circle>
<circle class="circle" cx="100" cy="100" r="57" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="180, 20000" transform="rotate(-90,100,100)"></circle>
<text text-anchor="middle" x="100" y="110" class="icon" style="font-size: 40px" fill="#3498DB"></text>
Notice the x, y attributes on the <text> element like so:
x="100" y="110"
Now if you play around in the console, you'll notice that any value apart from that will make the icon no longer centered.
I am not quite understanding the logic for centering the icon here. Can anybody explain please?
P.S. I believe the y value is 110 to counter the size of the icon, something like negative margin when vertically aligning a absolutely positioned element.
FIDDLE HERE Can somebody please explain this to me?
The icon is centered due to two attribute-value pairs:
It is horizontally centered because of the text-anchor = 'middle' attribute. When text anchor is set to middle, the text is positioned such that the center of the text is placed at the x coord that was given as attribute for the text tag. Below is what MDN says about this property-value pair.
middle
The rendered characters are aligned such that the middle of the text string is at the current text position. (For text on a path, conceptually the text string is first laid out in a straight line. The midpoint between the start of the text string and the end of the text string is determined. Then, the text string is mapped onto the path with this midpoint placed at the current text position.)
Here the circle is created such that its center is at (100,100) and hence setting the text x='100' and setting text-anchor = 'middle' positions the text at the horizontal center of the circle.
It is vertically centered because of the y attribute's value. This involves trial and error based on the font-size and the font of the text. In this particular case, the font-size: 40px means that the height of the box is roughly 26 units. This means that setting y = '113' will actually be setting the text at vertical middle (to be precise). The value of y = '100' doesn't put it at exact center.
In the below snippet we can see how the font-size impacts the value of y attribute. Basically the value for y should be set in such a way that half the text will be above the center the rest will be below the center. So, y is roughly center point + (height of text / 2).
As explained by Lea Verou in this article, there is a property called dominant-baseline: middle; which will center text vertically without the need for such calculations but the browser support is poor.
.svg-container {
max-width:200px;
}
<div id="circli" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">
<g stroke="#ccc">
<line x1="133" y1="50" x2="140" y2="40" stroke-width="2"></line>
</g>
<g stroke="#ccc">
<line x1="140" y1="40" x2="200" y2="40" stroke-width="2"></line>
</g>
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)"></circle>
<circle class="circle" cx="100" cy="100" r="57" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="180, 20000" transform="rotate(-90,100,100)"></circle>
<text text-anchor="middle" x="100" y="113" class="icon" style="font-size: 40px" fill="#3498DB"></text>
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">50%</text>
</svg>
</div>
<div id="circlj" class="svg-container">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186" class="circliful">
<g stroke="#ccc">
<line x1="133" y1="50" x2="140" y2="40" stroke-width="2"></line>
</g>
<g stroke="#ccc">
<line x1="140" y1="40" x2="200" y2="40" stroke-width="2"></line>
</g>
<circle cx="100" cy="100" r="57" class="border" fill="#eee" stroke="none" stroke-width="15" stroke-dasharray="360" transform="rotate(-90,100,100)"></circle>
<circle class="circle" cx="100" cy="100" r="57" fill="none" stroke="#3498DB" stroke-width="5" stroke-dasharray="180, 20000" transform="rotate(-90,100,100)"></circle>
<text text-anchor="middle" x="100" y="109.5" class="icon" style="font-size: 30px;" fill="#3498DB"></text>
<text class="timer" text-anchor="middle" x="175" y="35" style="font-size: 22px; undefined;" fill="#aaa">50%</text>
</svg>
</div>

What is the default width/margin/padding of SVG <g> and <text> elements?

I have the following SVG file I am working on.
http://jsfiddle.net/slayerofgiants/9y3qc/8/
If you notice from the fiddle file, the horizontal scrollbar extends to about twice the width of the SVG drawing. There is nothing but white space beyond the edge of the SVG. If I remove the <g> and <text> elements, then horizontal scrollbar goes away and is the size of the width of the screen.
You can see this on this 2nd jsfiddle
http://jsfiddle.net/slayerofgiants/m5zPv/
The code below is the SVG with no g elements containing the paired text elements.
<svg version="1.1" width="90%" id="ex1-3rds-quarter-s" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 323.333 55.333" enable-background="new 0 0 323.333 55.333"
xml:space="preserve" preserveAspectRatio="xMinYMid meet">
<font horiz-adv-x="1000">
<g id="fullTAB" transform="scale(1.1,1)" >
<g id="tablines" display="block">
<line fill="none" id="lowE" stroke="#000000" stroke-width="0.1" stroke-linecap="round" stroke-linejoin="round" x1="6" y1="45" x2="262" y2="45"/>
<line fill="none" id="Astring" stroke="#000000" stroke-width="0.1" stroke-linecap="round" stroke-linejoin="round" x1="6" y1="38.5" x2="262" y2="38.5"/>
<line fill="none" id="Dstring" stroke="#000000" stroke-width="0.1" stroke-linecap="round" stroke-linejoin="round" x1="6" y1="32" x2="262" y2="32"/>
<line fill="none" id="Gstring" stroke="#000000" stroke-width="0.1" stroke-linecap="round" stroke-linejoin="round" x1="6" y1="25.5" x2="262" y2="25.5"/>
<line fill="none" id="Bstring" stroke="#000000" stroke-width="0.1" stroke-linecap="round" stroke-linejoin="round" x1="6" y1="19" x2="262" y2="19"/>
<line fill="none" id="highE" stroke="#000000" stroke-width="0.1" stroke-linecap="round" stroke-linejoin="round" x1="6" y1="12.5" x2="262" y2="12.5"/>
</g>
<rect x="258" y="12" display="inline" width="0.829" height="32.73"/>
<rect x="260" y="12" display="inline" width="2.618" height="32.73"/>
<rect x="78" y="12" display="inline" width="0.829" height="32.73"/>
<rect x="6" y="12" display="inline" width="1" height="32.73"/>
<rect x="204" y="12" display="inline" width="0.829" height="32.73"/>
<rect x="142" y="12" display="inline" width="0.829" height="32.73"/>
<text x="13" y="21" style="text-anchor: middle" display="inline" font-family="'MyriadPro-Bold'" font-size="8.3685">T</text>
<text x="13" y="31" style="text-anchor: middle" display="inline" font-family="'MyriadPro-Bold'" font-size="8.3685">A</text>
<text x="13" y="41" style="text-anchor: middle" display="inline" font-family="'MyriadPro-Bold'" font-size="8.3685">B</text>
<g id="fretinformation">
</g><!--Fret Information -->
</g><!--Full Tab -->
</svg>
The code below is the g element with the paired text elements I am using which when inserted into the document causes the scrollbar to extend to about twice the width of the drawing size. I have a number of these with different x values. They are in the #fretinformation g element which is empty in the code above.
<g display="inline">
<text x="248" y="35" style="text-anchor: middle" fill="#324DCE" font-family="'MyriadPro-Bold'" font-size="8.3685">2</text>
<text x="248" y="41.5" style="text-anchor: middle" fill="#324DCE" font-family="'MyriadPro-Bold'" font-size="8.3685">3</text>
</g>
I had thought the g element had no width value and the text element width would collapse to only the width of the text it contained. What are the default widths/margin/padding of the g and text elements? And how can I change this behavior so there is no horizontal scrollbar?
Thanks--Christopher
EDIT
What appears to be happening is the text element is getting a width of 90% of the window size and as the text element is transformed along the x axis, it increases the overall width of the SVG file to be almost twice what it should be. As I remove text elements from right to left, the amount of whitespace to the right of the SVG file decreases.
SVG does not use a box layout model like HTML/CSS.
Putting display="inline" on an SVG element is basically meaningless. SVG elements are placed and drawn where you explicitly tell them.
The thing that determines the width and height of an SVG document is the width and height attributes (and sometimes the viewBox) of the root <svg> element.
However there are some differences (ie. bugs) in the way browsers lay out SVG elements. The fact that you are getting a scrollbar is an IE bug. You can use GCyrillus' overflow hidden trick to fix that.
It is render as an inline-boxe without any extra padding or margins.
I noticed a bug in chrome and another in IE11. wich one bothers you ?
It is somehow a bug that you can fix with : height:1%;(chrome) and overflow:hidden(IE) in your case : DEMO
svg {
display:block;
border:solid;
width:90%;
height:1%; /* fix webkit */
overflow:hidden;/* fix IE */
}
jsfiddle re-edited from IE11 : http://jsfiddle.net/9y3qc/13/ to check once again your comment

How to center a circle in an svg

I'm lost as to how I can put a circle element at the center of an svg without it moving around or getting bigger and smaller as I resize the page.
I've tried viewBox but it doesn't do what I expected.
An alternative to the viewBox variant:
<svg width="100" height="100">
<circle cx="50%" cy="50%" r="10"/>
</svg>
The circle would however get bigger if you zoom the whole page.
Another way is to use a zero-length path with rounded linecaps, like this:
<svg viewBox="0 0 100 100">
<path d="M50 50" stroke-linecap="round" stroke="black"
fill="none" vector-effects="non-scaling-stroke"
stroke-width="20"/>
</svg>
http://jsfiddle.net/dAEB9/
<svg viewBox="-1 -1 2 2"> <!-- viewBox defines the coordinate system.-->
<circle cx="0" cy="0" r="1" />
</svg>
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/viewBox
http://jsfiddle.net/QrNnN/
Put your circle in group <g> and use transform="translate(x, y)".
<svg viewBox="0 0 400 400">
<g transform="translate(200, 200)">
<circle cx="0" cy="0" r="200" style="" fill="darkOrange"></circle>
</g>
</svg>
Result:
Simple example on JSFiddle:
https://jsfiddle.net/mattez/0p2pstrf/