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".
Related
Is it possible to round a rectangle in SVG while ensuring the stroke obeys the roundedness of corners? The code below isn't working.
No Stroke:
stroke-width="0px"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="0px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
With Stroke:
stroke-width="10px"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
The stroke seems to follow the original sharp corners instead of the rounded corners.
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
A wide string extends beyond the svg border of the canvas SVG. Therefore, the string is partially cropped.
You must reduce the size of the rectangle so that the line is visible and shift the upper left corner of the rectangle right and down x="5" and y="5"
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect x="5" y="5" width="90" height="90" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
Update
ViewBox added. The coordinates of the rectangle x andy of the are increased, SVG wrapped in a container and can be embedded in an HTML page as a separate block. Adaptive application
.container {
width:30%;
height:30%
}
<div class="container">
<svg viewBox="0 0 110 110" xmlns="http://www.w3.org/2000/svg">
<rect x="10" y="10" width="90" height="90" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
</div>
As you can see from the picture, a square with a wide stroke is completely inside the SVG canvas
The first trivial solution is to make the overflow visible and add some margin to rectify this
svg {
overflow:visible;
margin:5px; /*half the stroke*/
}
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="150" height="80" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="100" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
Or you use calc() like below:
svg rect{
height:calc(100% - 10px);
width:calc(100% - 10px);
x:5px;
y:5px;
}
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="150" height="80" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
<svg width="100" height="200" xmlns="http://www.w3.org/2000/svg">
<rect width="100%" height="100%" stroke="red" stroke-width="10px" rx="10px" ry="10px" stroke-linejoin="round" />
</svg>
That can be used as background too:
.box {
background:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" ><rect x="5" y="5" width="100%" height="100%" style="height:calc(100% - 10px);width:calc(100% - 10px)" stroke="red" stroke-width="10" rx="10" ry="10" stroke-linejoin="round" /></svg>');
color: #fff;
padding:25px;
display:inline-block;
margin: 75px 0;
}
<div class="box"> Some text here</div>
<div class="box"> text very loooooooooooong here</div>
<div class="box"> a text <br> two line here</div>
<svg width="400" height="180">
<rect x="50" y="20" rx="20" ry="20" width="150" height="150"
style="fill:red;stroke:black;stroke-width:5;opacity:0.5" />
</svg>
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>
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;
}
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>
I would like to display, in SVG, a lot of circles. Each of us would contain an image.
I've found a way for doing that. I define a pattern :
<defs>
<pattern preserveAspectRatio="true" patternContentUnits="objectBoundingBox" height="1" width="1" y="0" x="0" id="imageExample">
<image height="1" width="1" y="0" x="0" xlink:href="img/imageExample.png"/>
</pattern>
</defs>
And then I display the circle :
<circle cx=x cy=y r=r stroke="white" stroke-width="2" fill="url(#imageExample)"/>
My question is : is it necessary to define 1000 patterns if I want to display 1000 circles ?
[edit] I want that each circle has a different background image, sorry.
of course, i isn't. see the demo below, also avaliable online:
<?xml version="1.0" encoding="utf-8"?>
<!-- SO: http://stackoverflow.com/questions/16174765/display-a-lot-of-images-in-background-svg -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="20cm" height="20cm"
viewBox="0 0 1000 1000"
preserveAspectRatio="xMinYMin"
style="background-color:white; border: solid 1px black;"
>
<defs>
<pattern preserveAspectRatio="true" patternContentUnits="objectBoundingBox" height="1" width="1" y="0" x="0" id="imageExample">
<image height="1" width="1" y="0" x="0" xlink:href="img/imageExample.png"/>
</pattern>
</defs>
<circle cx="123" cy="109" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="456" cy="332" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="12" cy="444" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="77" cy="567" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="66" cy="712" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="47" cy="855" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="843" cy="30" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="112" cy="321" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="387" cy="543" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
<circle cx="444" cy="67" r="10" stroke="black" stroke-width="1" fill="url(#imageExample)"/>
</svg>