SVG, ellipse with pattern does not show up - svg

The code below should generate a circle filled with a diagonal pattern. The code is taken from this question, I just adapted the unit to get the following pattern: line thickness 0.2mm and line distance 1mm.
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="3.2cm" version="1.1"
viewBox="0 0 5 3.2" width="5.0cm"
xmlns="http://www.w3.org/2000/svg"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs />
<pattern height="0.14142135623730953" id="#1"
patternUnits="userSpaceOnUse" width="0.14142135623730953">
<path d="M-0.07071067811865477,0.07071067811865477
l0.14142135623730953,-0.14142135623730953
M-0.07071067811865477,0.21213203435596428
l0.28284271247461906,-0.28284271247461906
M0.07071067811865477,0.21213203435596428
l0.14142135623730953,-0.14142135623730953"
style="stroke:black; stroke-width:0.02" />
</pattern>
<ellipse cx="2" cy="1.6" fill="url(#1)" id="#2" rx="1.5"
ry="1.5" stroke="black" stroke-width="0.01" />
<ellipse cx="3" cy="1.6" fill="none" id="#3" rx="1.5" ry="1.5"
stroke="none" stroke-width="0.01" />
<text dominant-baseline="hanging" stroke="black"
text-anchor="end" x="0.5" y="0.7000000000000002">$A$</text>
<text dominant-baseline="hanging" stroke="black"
text-anchor="start" x="4.5" y="0.7000000000000002">$B$</text>
</svg>
Ignore the ellipse #3 (it's transparent) and the two texts. Why does the ellipse #2 not show up?

Try this;
Your mistake is in naming id="#1"
if you select something by id you write #elementId
if you define element id you write id="elementId"
<?xml version="1.0" encoding="utf-8" ?>
<svg baseProfile="full" height="3.2cm" version="1.1"
viewBox="0 0 5 3.2" width="5.0cm"
xmlns="http://www.w3.org/2000/svg"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs />
<pattern height="0.14142135623730953" id="1"
patternUnits="userSpaceOnUse" width="0.14142135623730953">
<path d="M-0.07071067811865477,0.07071067811865477
l0.14142135623730953,-0.14142135623730953
M-0.07071067811865477,0.21213203435596428
l0.28284271247461906,-0.28284271247461906
M0.07071067811865477,0.21213203435596428
l0.14142135623730953,-0.14142135623730953"
style="stroke:black; stroke-width:0.02" />
</pattern>
<ellipse cx="2" cy="1.6" fill="url(#1)" id="#2" rx="1.5"
ry="1.5" stroke="black" stroke-width="0.01" />
<ellipse cx="3" cy="1.6" fill="none" id="#3" rx="1.5" ry="1.5"
stroke="none" stroke-width="0.01" />
<text dominant-baseline="hanging" stroke="black"
text-anchor="end" x="0.5" y="0.7000000000000002">$A$</text>
<text dominant-baseline="hanging" stroke="black"
text-anchor="start" x="4.5" y="0.7000000000000002">$B$</text>
</svg>

Related

How to change the color of one or more element that is part of a SVG pattern?

I have the following SVG code which draws many squares:
<svg width="100%" height="100%" viewBox="0,0,100%,100%" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="smallGrid" width="1.388888888888889%" height="5%" patternUnits="userSpaceOnUse">
<path fill="#2e99e5" d="M0 0h960v960H0z" stroke="gray" stroke-width="0.5"/>
</pattern>
<pattern id="grid" width="8.333333333333333%" height="50%" patternUnits="userSpaceOnUse">
<rect width="100%" height="100%" fill="url(#smallGrid)"/>
<path fill="none" d="M0 0h960v960H0z" stroke="gray" stroke-width="2" />
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#grid)" />
</svg>
Is there a way to select the first 3 <path fill="#2e99e5" d="M0 0h960v960H0z" stroke="gray" stroke-width="0.5"/>
and change the color?

Why is my shape not rotating along its apparent bounding box?

I'm trying to rotate this image (#small) so that it's upside down, but the shape isn't rotating as I'd expect. It seems to me that the bounding box would be much smaller than its apparent axis of rotation.
What's actually going on here and how can I fix it?
MWE
<?xml version="1.0" encoding="utf-8"?>
<svg id="test-image"
viewBox="0 0 816 1110"
width="816" height="1110"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
<g id="base">
<svg viewBox="-8 -10 16 20" >
<path d="M 7.989,3.103 C 7.747,-0.954 0.242,-8.59 0,-10.5 c -0.242,1.909 -7.747,9.545 -7.989,13.603 -0.169,2.868 1.695,4.057 3.39,4.057 1.8351685,-0.021581 3.3508701,-2.8006944 3.873,-3.341 0.242,0.716 -1.603,6.682 -2.179,6.682 l 5.811,0 C 2.33,10.501 0.485,4.535 0.727,3.819 1.1841472,4.3152961 2.5241276,7.0768295 4.601,7.16 6.295,7.159 8.158,5.971 7.989,3.103 z"
style="fill:#000000" />
</svg>
</g>
<g id="small">
<use xlink:href="#base" transform="scale(0.1,0.1)" />
</g>
</defs>
<!-- debugging grid -->
<rect width="100%" height="100%" stroke="black" fill="white"/>
<rect width="80%" height="80%" stroke="lightgrey" fill="white" x="10%" y="10%" />
<rect width="60%" height="60%" stroke="lightgrey" fill="white" x="20%" y="20%" />
<rect width="40%" height="40%" stroke="lightgrey" fill="white" x="30%" y="30%" />
<rect width="20%" height="20%" stroke="lightgrey" fill="white" x="40%" y="40%" />
<line x1="0%" x2="100%" y1="50%" y2="50%" stroke="lightgrey" />
<line y1="0%" y2="100%" x1="50%" x2="50%" stroke="lightgrey" />
<!-- rotation test -->
<use xlink:href="#small" x="50%" y="50%" />
<use xlink:href="#small" x="50%" y="50%" transform="rotate(10)" />
<use xlink:href="#small" x="50%" y="50%" transform="rotate(20)" />
<use xlink:href="#small" x="50%" y="50%" transform="rotate(30)" />
</svg>

How can I construct an SVG scene with user coordinates to fill the screen

I am displaying a diagrammatic map using SVG and it must be proportional (i.e., not skewed x/y).
The image fills the whole screen so the outer item is always 100%/100%. In other words I want the viewport to always fill the browser windows (within the constraints of aspect ratio), for example:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events" >
<defs>
<solidColor xml:id="solidBlack" solid-color="black" />
<solidColor xml:id="solidLightGray" solid-color="lightgrey" />
</defs>
<style>
.Border { fill:none; stroke:red; stroke-width="2px" }
.TitleBlock { fill:none; stroke:black; stroke-width="1px" }
</style>
<svg x="0" y="0" width="100%" height="100%" viewbox="0 0 1000 1000" >
<rect x="2" y="2" width="99%" height="99%" class="Border" />
<svg viewbox="500 500 500 500">
<circle cx="30" cy="20" r="10px" fill="red" />
<circle cx="450" cy="30" r="10px" fill="blue" />
<circle cx="40" cy="490" r="10px" fill="green" />
</svg>
</svg>
</svg>
When this renders, the values are being interpreted as pixels, not user coordinates. So, for example, the green dot should be near the bottom of the screen (since it is at the bottom of the viewbox) but in actuality it is in the middle of the screen because it is interpreting 490 as 490 pixels.
To further clarify, the 1000 x 1000 dimensions of the total map area are user coordinates. For example, suppose I am making a space game and the game area is 1000 parsecs x 1000 parsecs. Any particular view of this map area should fill the screen.
Update
Based on the answer one fundamental problem is that to fill the screen I need to use 100% in the outer svg element. However, even after doing this, the image is not zooming in and using user coordinates:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
width="100%" height="100%"
viewBox="0 0 100000 100000" >
<defs>
<solidColor xml:id="solidBlack" solid-color="black" />
<solidColor xml:id="solidLightGray" solid-color="lightgrey" />
</defs>
<style>
.Border { fill:none; stroke:red; stroke-width="2px"; }
.TitleBlock { fill:none; stroke:black; stroke-width="1px"; }
}
</style>
<rect y="2" width="100%" height="100%" class="Border" />
<svg viewBox="50000 50000 100000 100000" >
<circle cx="52000" cy="52000" r="10px" fill="red" />
<circle cx="95000" cy="53000" r="10px" fill="blue" />
<circle cx="54000" cy="99000" r="10px" fill="green" />
</svg>
</svg>
This does not even appear at all, indicating it is using PIXELS not user coordinates.
I think you might be confused about how viewBox works. It describes the bounds of the document that should be scaled to fit the viewport (width & height). It doesn't perform a transform.
Your viewBox of "500 500 500 500" describes the area (500,500) -> (1000,1000). So your coordinate of (10,490) will normally end up way outside the viewport.
Having said that, it is not at all clear what you are actually trying to achieve with your nested set of <svg> elements.
I'm going to assume you are wanting to display a portion of your 1000x1000 world map so it fills the screen? Lets' start by simplifying your original SVG.
.Border { fill:none; stroke:red; stroke-width="2px" }
.TitleBlock { fill:none; stroke:black; stroke-width="1px" }
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:ev="http://www.w3.org/2001/xml-events"
width="100%" height="100%"
viewBox="0 0 1000 1000">
<defs>
<solidColor xml:id="solidBlack" solid-color="black" />
<solidColor xml:id="solidLightGray" solid-color="lightgrey" />
</defs>
<rect x="2" y="2" width="99%" height="99%" class="Border" />
<circle cx="30" cy="20" r="10px" fill="red" />
<circle cx="450" cy="30" r="10px" fill="blue" />
<circle cx="40" cy="490" r="10px" fill="green" />
</svg>
Here we are displaying the whole world map in an SVG that is 100%x100%. Due to the way percentage width/height values are processed for SVGs and because the viewBox is square. This normally results in an SVG that is 100% width and whose height is equivalent to the width, resulting in an SVG that may end up off the bottom of the page.
If you want the SVG viewport to match the screen exactly you should use a width/height in pixels, not percents. For the sake of fitting in the snippet window, let's choose a tiny screen of 512x384 (1/2 of a 1024x768 screen).
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="512" height="384"
viewBox="0 0 1000 1000">
<rect x="-50%" y="-50" width="200%" height="200%" fill="#ffc"/>
<rect x="2" y="2" width="99%" height="99%" fill="none" stroke="red" stroke-width="2" />
<circle cx="30" cy="20" r="10px" fill="red" />
<circle cx="450" cy="30" r="10px" fill="blue" />
<circle cx="40" cy="490" r="10px" fill="green" />
</svg>
Here I've also added a light yellow rectangle to show the dimensions of the viewport (screen) and how the viewBox has resulted in the "world" being scaled to fit the screen.
If you want the world to fill the screen and not have the blank areas to the left and right you need to change the preserveAspectRatio attribute. By default it is set to xMidYMid meet which means scale the viewBox area up to neatly fit the viewport and centre it. If we change it to xMidYMid slice, it will scale it up to fill the widest part of the viewport. That results in the top and bottom of your "world" going off screen.
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="512" height="384"
viewBox="0 0 1000 1000"
preserveAspectRatio="xMidYMid slice">
<rect x="-50%" y="-50" width="200%" height="200%" fill="#ffc"/>
<rect x="2" y="2" width="99%" height="99%" fill="none" stroke="red" stroke-width="2" />
<circle cx="30" cy="20" r="10px" fill="red" />
<circle cx="450" cy="30" r="10px" fill="blue" />
<circle cx="40" cy="490" r="10px" fill="green" />
</svg>
Now, if you want to view a portion of your "world", for example the top left, you would set the viewBox to "0 0 500 500". If you want to see the whole of that area, use `preserveAspectRatio="xMidYMid meet":
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="512" height="384"
viewBox="0 0 500 500"
preserveAspectRatio="xMidYMid meet">
<rect x="-50%" y="-50" width="200%" height="200%" fill="#ffc"/>
<rect x="2" y="2" width="99%" height="99%" fill="none" stroke="red" stroke-width="2" />
<circle cx="30" cy="20" r="10px" fill="red" />
<circle cx="450" cy="30" r="10px" fill="blue" />
<circle cx="40" cy="490" r="10px" fill="green" />
</svg>
If you don't want to see parts of the world outside of that 500x500 area, and can live with part of it being offscreen, use xMidYMid slice.
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="512" height="384"
viewBox="0 0 500 500"
preserveAspectRatio="xMidYMid slice">
<rect x="-50%" y="-50" width="200%" height="200%" fill="#ffc"/>
<rect x="2" y="2" width="99%" height="99%" fill="none" stroke="red" stroke-width="2" />
<circle cx="30" cy="20" r="10px" fill="red" />
<circle cx="450" cy="30" r="10px" fill="blue" />
<circle cx="40" cy="490" r="10px" fill="green" />
</svg>
Here, your three circles end up just off screen.
Does this help?

SVG: set fill color for part of a shape

I have an ellipse shape, which I want to split into 4 sections. Is it possible to independently color these sections or is it necessary to create 4 separate custom shapes ?
(I'd post a picture but I don't have the rep yet). Hope its clear what I mean.
Edit you can see code here http://jsfiddle.net/KQ3eH/
<html>
<head>
<style>
.anellipse {
fill:rgb(255,255,255);
stroke-width:2;
stroke:rgb(0,0,0);
}
.aline {
stroke:rgb(0,0,0);
stroke-width:2;
}
</style>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="960"
height="640">
<ellipse class="anellipse" cx="480" cy="320" rx="478" ry="318"/>
<line class="aline" x1="2" y1="320" x2="958" y2="320" stroke-linecap="round" stroke-dasharray="1, 4"/>
<line class="aline" x1="480" y1="2" x2="480" y2="638" stroke-linecap="round" stroke-dasharray="1, 4"/>
</svg>
</body>
</html>
You can do multicolor fills using a pattern.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="960" height="640">
<defs>
<pattern id="pat" width="1" height="1" viewBox="0 0 1 1" preserveAspectRatio="none">
<rect width=".5" height=".5" fill="red" />
<rect x=".5" width=".5" height=".5" fill="green" />
<rect y=".5" width=".5" height=".5" fill="orange" />
<rect x=".5" y=".5" width=".5" height=".5" fill="blue" />
</pattern>
</defs>
<ellipse class="anellipse" cx="480" cy="320" rx="478" ry="318" fill="url(#pat)"/>
<line class="aline" x1="2" y1="320" x2="958" y2="320" stroke-linecap="round" stroke-dasharray="1, 4" />
<line class="aline" x1="480" y1="2" x2="480" y2="638" stroke-linecap="round" stroke-dasharray="1, 4" />
</svg>
See example.
You can't do multi-colour fills (well not more than two colours anyway). So you basically have to split it up into four sections.
Splitting up the ellipse shape itself is a bit tricky. A much easier way would be to draw four coloured rectangles and use the ellipse as a clipping path.
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="960" height="640">
<defs>
<clipPath id="myell">
<ellipse class="anellipse" cx="480" cy="320" rx="478" ry="318" />
</clipPath>
</defs>
<g clip-path="url(#myell)">
<rect x="2" y="2" width="478" height="318" fill="red"/>
<rect x="480" y="2" width="478" height="318" fill="green"/>
<rect x="2" y="320" width="478" height="318" fill="orange"/>
<rect x="480" y="320" width="478" height="318" fill="blue"/>
</g>
</svg>
Demo here

How can i scale a shape without scaling its pattern?

I have an svg shape which uses a pattern. I want the pattern to NOT scale when i scale the shape.
Here's a fiddle with a minimal example, the bigger circle should show the pattern like the smaller one:
http://jsfiddle.net/cTMrQ/6/
<svg style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
<defs>
<pattern id="checkerPattern" patternUnits="userSpaceOnUse" x="0" y="0" width="4" height="4">
<image x="0" y="0" xlink:href="http://inwonderland.at/new/lines.png" width="4" height="4" />
</pattern>
<circle fill="url(#checkerPattern)" id="c" cx="50" cy="50" r="50" />
</defs>
<use x="100" y="100" xlink:href="#c" />
<use x="200" y="100" xlink:href="#c" transform="scale(2)" />
</svg>
In the end the shape will be a complex path and the image in the pattern will be a scan of a piece of paper, so just drawing a bigger circle instead of scaling it won't work.
Update
To clarify what i want, here are two images:
this is what it looks like, no matter what i try, when i scale the shape:
http://inwonderland.at/new/ihave.png
this is what i want:
http://inwonderland.at/new/iwant.png
i want the background image (bitmap image) to always have its natural size.
You can't get what you want using a pattern, the transform always happens after the fill, and you can't just move the pattern fill into a wrapper either. My suggestion is to use a filter and apply the filter on a wrapper - like so:
<svg style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
<defs>
<circle fill="url(#checkerPattern)" id="c1" cx="50" cy="50" r="50" />
<filter id="linepattern" x="0%" y="0%" height="100%" width="100%">
<feImage xlink:href="http://inwonderland.at/new/lines.png" result="pattern" width="4" height="4"/>
<feTile/>
<feComposite operator="in" in2="SourceGraphic"/>
</filter>
</defs>
<use filter="url(#linepattern)" x="100" y="100" xlink:href="#c1" />
<use filter="url(#linepattern)" x="200" y="100" xlink:href="#c1" transform="scale(2)" />
<g filter="url(#linepattern)">
<use x="50" y="100" xlink:href="#c1" transform="scale(2)" />
</g>
</svg>
Using viewport
1:1 no zoom
<svg width="800" height="400" viewBox="0 0 800 400">
2:1 zoom double size
<svg width="800" height="400" viewBox="0 0 400 200">
The following elements can use the viewBox attribute
<svg>
<symbol>
<image>
<marker>
<pattern>
<view>
viewbox is fully animatable; and you can zoom into any center point.
<animate attributeName="viewBox" begin="1s" dur="1s"
values="0 0 600 400; 250 180 300 200" fill="freeze" />
Transform a parent tag
Yes an SVG can be a child element but more commonly shapes made with multible tags are placed inside a group tag.
Transform scale can be used with tags which are parents IE the group tag.
<g transform="scale(1.5)">
/* draw your shape inside the g tag */
<use x="100" y="100" xlink:href="#c" />
<use x="200" y="100" xlink:href="#c" />
</g>
So using your above example scale the shape in a parent tag.
Update
To scale image but not patterns in other words move patterns, or icons, on background image that scales.
<g transform="scale(2)">
/* draw your shape inside the g tag */
<use x="100" y="100" xlink:href="#c" transform="scale(.5)" />
<use x="200" y="100" xlink:href="#c" transform="scale(.5)"/>
</g>
Update full svg
I had to move things around a bit, One full size, (lets call it a map), with an overlay of 1 half size map in the upper left corner. setting the full screen to render between 0 and max of 600. Setting a viewport the same but with the width set to 300 scales it down. I do need to double the radius for this example of scaling.
<svg viewBox="0 0 600 600" style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
<defs>
<pattern id="checkerPattern" patternUnits="userSpaceOnUse" x="0" y="0" width="4" height="4">
<image x="0" y="0" xlink:href="http://inwonderland.at/new/lines.png" width="4" height="4" />
</pattern>
<circle fill="url(#checkerPattern)" id="c" cx="50" cy="50" r="50" />
<circle fill="url(#checkerPattern)" id="c2" cx="50" cy="50" r="100" />
</defs>
<use x="100" y="100" xlink:href="#c" transform="scale(.5)"/>
<use x="200" y="100" xlink:href="#c" transform="scale(1)"/>
<rect width="600" height="600" style="fill: none; stroke: black;" />
<svg viewBox="0 0 600 600" width="300" height="300" x="300">
<use x="100" y="100" xlink:href="#c2" transform="scale(.5)"/>
<use x="200" y="100" xlink:href="#c2" transform="scale(1)"/>
<rect width="600" height="600" style="fill: none; stroke: black;" />
</svg>
</svg>
This example is scaled using the same circle pattern. The radius does not need to be changed here because the location is not in the tag being scaled. I'm making use of svg tags here but other tags can be used.
<svg viewBox="0 0 600 600" style="position: absolute" width="100%" height="100%" version="1.1" baseProfile="full"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">
<defs>
<pattern id="checkerPattern" patternUnits="userSpaceOnUse" x="0" y="0" width="4" height="4">
<image x="0" y="0" xlink:href="http://inwonderland.at/new/lines.png" width="4" height="4" />
</pattern>
<circle fill="url(#checkerPattern)" id="c" r="50" cx="50" cy="50" />
</defs>
<svg x="100" y="100"><use xlink:href="#c" transform="scale(.5)"/></svg>
<svg x="200" y="100"><use xlink:href="#c" transform="scale(1)"/></svg>
<rect width="600" height="600" style="fill: none; stroke: black;" />
<svg viewBox="0 0 600 600" width="300" height="300" x="300">
<svg x="100" y="100"><use xlink:href="#c" transform="scale(1)"/></svg>
<svg x="200" y="100"><use xlink:href="#c" transform="scale(2)"/></svg>
<rect width="600" height="600" style="fill: none; stroke: black;" />
</svg>
</svg>

Resources