SVG: float a shape over another shape? - html

I have two circle shapes I'm working with in HTML markup. Is it possible to position one atop another, setting order w/ a z-index type property? Currently my shapes render next to each other:
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="red" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="25" cy="25" r="25" fill="yellow" />
</svg>
thanks

Just use standard CSS positioning, e.g.
svg {
position: absolute;
}
Adjust as you see fit.

using the above suggestions to use normal CSS positioning, this is what i did to obtain relative layer positioning:
#svgHolder {
position:relative
}
.svgCircle2 {
position:absolute;
top:15px;
left:15px;
}
<div id="svgHolder">
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="red" />
</svg>
<svg class="svgCircle2" xmlns="http://www.w3.org/2000/svg">
<circle cx="35" cy="35" r="35" fill="yellow" />
</svg>
</div>

USE this FIDDLE
http://jsfiddle.net/4wpw6add/8/
<svg class="bottom" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" fill="red" />
</svg>
<svg class="top" xmlns="http://www.w3.org/2000/svg">
<circle cx="25" cy="25" r="25" fill="yellow" />
</svg>
.bottom{
margin:0;
}
.top{
margin: 0 auto;
position: absolute;
top: 34px;
left: 30px;
text-align:center;
}

Related

Fontawesome 5 SVG with JS: How does svg scale with font-size css property?

how does FA5 scale SVG icons via font-size css property? How can I scale this example svg like Fontawesome does? Thank you very much.
svg{
}
<svg height="100" width="100">
<circle cx="50" cy="50" r="50"/>
</svg>
It can be scaled via font-size like this:
svg {width: 3em; height:3em}
#svg1 {font-size:10px}
#svg2 {font-size:20px}
<svg id="svg1" viewBox="0 0 100 100"><circle cx="50" cy="50" r="49"/></svg>
<svg id="svg2" viewBox="0 0 100 100"><circle cx="50" cy="50" r="49"/></svg>
With FA5 SVG icons it will append a class to the svg element as default, so you are able to hook into it by using the below
<div class="myIcon">
<svg height="100" width="100">
<circle cx="50" cy="50" r="50"/>
</svg>
</div>
.myIcon .svg-inline--fa{
font-size: 20px;
}

Transparent overlapping circles without border in background

Is it possible to implement transparent overlapping svg circle elements without circles border in transparent area?
You can clip the bits you don't want to draw...
<svg height="100" width="150">
<defs>
<clipPath id="clip" clipPathUnits="objectBoundingBox">
<rect width="0.79" height="1.2" x="-0.1" y="-0.1"/>
</clipPath>
</defs>
<rect width="100%" height="100%" fill="blue" opacity="0.2" />
<circle cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="none" />
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="none" clip-path="url(#clip)"/>
</svg>
Check this link to view information about position absolute css code. I think this is what you are looking for. You might also want to view information about z-index. If you have any questions or want me to write some sample code for your problem let me know
svg{
position: absolute;
}
#svg-1{
top: 80px;
left: 20px;
}
#svg-2{
top: 80px;
left: 60px;
}
<svg id="svg-1" height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg>
<svg id="svg-2" height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" /></svg>
You can also use a <mask>.
I've used the same elements as #RobertLongson's answer so you can compare the approaches.
<svg height="100" width="150">
<defs>
<mask id="mask">
<!-- white rectangle to keep the area outside the circle -->
<rect width="100%" height="100%" fill="white"/>
<!-- black circle creates a "hole" to hide the part inside -->
<circle cx="50" cy="50" r="40" fill="black"/>
</mask>
</defs>
<rect width="100%" height="100%" fill="blue" opacity="0.2" />
<circle cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="none"
mask="url(#mask)"/>
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="none"/>
</svg>

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.

SVG viewBox scaling and cropping

How can I output a certain place from SVG and zoom it?
E. g., I have the following HTML with SVG (the copy of the code and its render are located at http://jsfiddle.net/5e0pas9m/ ).
<div style="border: 1px solid black;">1
<svg width="100" height="100" viewBox="0 0 200 200" style="border: 1px solid red; transform: scale(1);" preserveAspectRatio="xMidYMid none">
<rect width="100%" height="100%" style="fill:rgb(200,200,255);stroke-width:4;stroke:rgb(100,100,255)" />
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
<circle cx="150" cy="150" r="40" stroke="red" stroke-width="4" fill="yellow" />
</svg>
</div>
<div style="border: 1px solid black;">2
<svg width="100" height="100" viewBox="0 0 100 100" style="border: 1px solid red; transform: scale(1);" preserveAspectRatio="xMidYMid none">
<rect width="100%" height="100%" style="fill:rgb(200,200,255);stroke-width:4;stroke:rgb(100,100,255)" />
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
<circle cx="150" cy="150" r="40" stroke="red" stroke-width="4" fill="yellow" />
</svg>
</div>
<div style="border: 1px solid black;">3
<svg width="100" height="100" viewBox="100 100 200 200" style="border: 1px solid red; transform: scale(1);" preserveAspectRatio="xMidYMid none">
<rect width="100%" height="100%" style="fill:rgb(200,200,255);stroke-width:4;stroke:rgb(100,100,255)" />
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
<circle cx="150" cy="150" r="40" stroke="red" stroke-width="4" fill="yellow" />
</svg>
</div>
<div style="border: 1px solid black;">4
<svg width="100" height="100" style="border: 1px solid red; transform: scale(1);" preserveAspectRatio="xMidYMid none">
<g transform="scale(1), translate(-100 -100)">
<rect width="100%" height="100%" style="fill:rgb(200,200,255);stroke-width:4;stroke:rgb(100,100,255)" />
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
<circle cx="150" cy="150" r="40" stroke="red" stroke-width="4" fill="yellow" />
</g>
</svg>
</div>
The div-1 shows my full image.
If I like to show only the top-left corner in the same window I make viewBox="0 0 100 100" (div-2) and it gives approximately what I want: the part of the image fitted to the window.
But when I do the same thing with the right-bottom corner (div-3 represents viewBox="100 100 200 200") the image is only translated but is not fitted/zoomed/scaled.
The div-4 nealry shows an example of my target achieved via another technique.
The third and fourth arguments of the viewBox are width and height, not maxX and maxY. So the viewBox for your bottom-right example should be "100 100 100 100".

How can I preserve the aspect ratio of internal elements of an SVG while allowing the SVG itself to scale?

I'm very new to SVG, so I apologize if this is an obvious question. I've tinkered for a few hours and seem to have hit a wall.
I am attempting to create an SVG element in an HTML document which:
has a firm boundary on the outer viewport
preserves the aspect ratio of internal elements
does not preserve the aspect ratio of the outer SVG element
can be resized arbitrarily while maintaining these contraints
This JSFiddle illustrates what I mean and what I have attempted:
http://jsfiddle.net/a8q6S/
And here's the same code since I can't post this otherwise:
<div>
<h2>correct placement and aspect ratio, but cannot be resized without losing relative placement</h2>
<svg viewBox="0 0 100 100" style="width: 100px; height: 100px; border: 1px solid red;">
<circle cx="0" cy="0" r="10"></circle>
<circle cx="50" cy="50" r="10"></circle>
<circle cx="100" cy="100" r="10"></circle>
</svg>
</div>
<div>
<h2>correct aspect ratio of circle, incorrect relative placement</h2>
<svg viewBox="0 0 100 100" preserveAspectRatio="xMinYMin" style="width: 200px; height: 100px; border: 1px solid red;">
<circle cx="0" cy="0" r="10"></circle>
<circle cx="50%" cy="50%" r="10"></circle>
<circle cx="100%" cy="100%" r="10"></circle>
</svg>
</div>
<div>
<h2>correct relative placement, can be resized, but loses internal aspect ratio</h2>
<svg viewBox="0 0 100 100" preserveAspectRatio="none" style="width: 200px; height: 100px; border: 1px solid red;">
<circle cx="0" cy="0" r="10"></circle>
<circle cx="50" cy="50" r="10"></circle>
<circle cx="100" cy="100" r="10"></circle>
</svg>
</div>
Is this possible? Am I going about this the wrong way?
You cannot achieve what you want using pure SVG. You will need to use some javascript to tweak the SVG a bit on load and resize.
If you use something like your second example, you will only need to tweak the viewBox, width and height. The contents can stay constant.
For example,
<svg viewBox="0 0 100 100" style="width: 100px; height: 100px; border: 1px solid red;">
<circle cx="0" cy="0" r="10"></circle>
<circle cx="50%" cy="50%" r="10"></circle>
<circle cx="100%" cy="100%" r="10"></circle>
</svg>
would become
<svg viewBox="0 0 200 100" style="width: 200px; height: 100px; border: 1px solid red;">
<circle cx="0" cy="0" r="10"></circle>
<circle cx="50%" cy="50%" r="10"></circle>
<circle cx="100%" cy="100%" r="10"></circle>
</svg>
when the width doubled.
http://jsfiddle.net/a8q6S/3/
It is possible to use 2 svg, one with preserveAspectRatio="none" and the other one without. The last one will be the upper one.
In my example, I draw an arrow with 100% height, and then I draw circles on it.
<body style="height: 100%; width: 100%; margin: 0; background-color: grey">
<svg style="height: 100%; width: 10%; left: 10%; position: absolute; overflow: hidden;"
viewBox="0 0 100 100" preserveAspectRatio="none">
<rect x="40" y="0" r="40" width="20" height="95%" style="fill:blue;"/>
<polygon points="40,95 50,100 60,95" style="fill:blue;" />
</svg>
<svg style="height: 100%; width: 10%; left: 10%; position: absolute; overflow: hidden;">
<circle cx="50%" cy="16.6%" r="25" style="fill:white;" />
<circle cx="50%" cy="50%" r="50" style="fill:white;" />
<circle cx="50%" cy="83.3%" r="25" style="fill:white;" />
</svg>
</body>
Thank you. I was having a similar issue. This is my solution.
<svg viewBox="0 0 100% 100%" preserveAspectRatio="xMinYMin" style="width: 200px; height: 100px; border: 1px solid red;">
<circle cx="0%" cy="0%" r="10"></circle>
<circle cx="50%" cy="50%" r="10"></circle>
<circle cx="100%" cy="100%" r="10"></circle>
</svg>
Sorry I'm also new with svgs, thanks for the corrections.
This doesn't directly solve the problem presented, but I found that I couldn't preserve the aspect ratio of a viewbox inside a viewbox that does not preserve aspect ratio.
The caveat to this solution is that you must establish the width and height for each inner svg unless doesn't preserve relative placement.
If you want to preserve both relative placement and aspect ratio, do not use a viewbox.
<svg viewbox="0 0 100 100" preserveAspectRatio="xMinYMin" width=200 height=100 style="border: 1px solid red;">
<svg>
<circle cx="0" cy="0" r="10"></circle>
<circle cx="50" cy="50" r="10"></circle>
<circle cx="100" cy="100" r="10"></circle>
</svg>
<svg viewbox="0 0 100 100" preserveAspectRatio="none" fill=blue width=200 height=100>
<circle cx="0" cy="0" r="7"></circle>
<circle cx="50" cy="50" r="7"></circle>
<circle cx="100" cy="100" r="7"></circle>
</svg>
<svg fill=red width=200 height=100>
<circle cx="0%" cy="0%" r="4"></circle>
<circle cx="50%" cy="50%" r="4"></circle>
<circle cx="100%" cy="100%" r="4"></circle>
</svg>
</svg>