Suppose I have a SVG circle with a radius r. Now suppose I have an SVG line which starts at the center of the SVG circle. How can I determine the x2 and y2 coordinates of where it crosses the radius of the circle.
<line x1="500" y1="500" x2="300" y2="75" style="stroke:#156217;stroke-width:4" />
<circle cx="500" cy="500" r="100" stroke="black" stroke-width="3" fill="transparent" />
You can clip the line with a clipPath. The use element allows us to point to the circle element we want to reuse for clipping.
<svg viewBox="0 0 1000 1000">
<defs>
<clipPath id="cp">
<use xlink:href="#c"/>
</clipPath>
</defs>
<line x1="500" y1="500" x2="300" y2="75" style="stroke:#156217;stroke-width:4" clip-path="url(#cp)" />
<circle id="c" cx="500" cy="500" r="100" stroke="black" stroke-width="3" fill="none" />
</svg>
I have a pin that needs to be shown inside a circle in Svg.
My current code is the following:
<svg viewBox="0 0 20 20" preserveAspectRatio="xMinYMin meet">
<circle cx="50%" cy="1.5" r="1.5" style="fill: green;"></circle>
<svg x="47.5%" y="5%" viewBox="0 0 10000 10000" fill="#fff" preserveAspectRatio="none">
<g>
<path d="M250,124.3c-35,0-63.4,28.8-63.4,64.1c0,35.3,28.5,64,63.4,64s63.4-28.8,63.4-64.1C313.4,153,285,124.3,250,124.3z
M250,222c-18.3,0-33.2-15.1-33.2-33.7s14.9-33.7,33.2-33.7s33.2,15.1,33.2,33.7S268.3,222,250,222z">
</path>
<path d="M250,50.9c-74.9,0-135.8,61.6-135.8,137.4c0,31.3,22.5,84.4,66.9,157.7c32.9,54.4,66.2,100.3,66.6,100.7l2.4,3.3l2.4-3.3
c0.3-0.5,33.7-46.3,66.6-100.7c44.4-73.3,66.9-126.4,66.9-157.7C385.8,112.5,324.9,50.9,250,50.9z M250,397.6
c-16.5-24.3-45.5-68.4-69.9-114c-23.5-44-35.9-77-35.9-95.4c0-59,47.4-107,105.8-107s105.8,48,105.8,107
c0,18.4-12.4,51.4-35.9,95.4C295.4,329.3,266.5,373.4,250,397.6z">
</path>
</g>
</svg>
</svg>
which works somewhat but seems inelegant, and perhaps also buggy. What I would like is a better way to center the group 'inside' the circle without using JavaScript
It would be nice if I could get rid of the extra SVG element in the middle with its really big viewBox that I'm using to place the pin. So if you can show me how to do it with just a g and make a scaling function that would be good.
If you want to use coordinates that contain percentage values, you need an element that has x and y attributes. <use> is such an element, <g> is not.
Your live will be easier if you draw your pin centered on the origin of the coordinate system: translate(-250 -230).
After that, you can easily scale it to the size you need: scale(0.0025) (remember: multiple transform commands are processed right-to-left.)
Finally, you use the pin template with the same x and y coordinates as your circle.
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 20 20" preserveAspectRatio="xMinYMin meet">
<defs>
<!--center the pin around the origin and scale it to final size-->
<g id="pin" transform="scale(0.0025) translate(-250 -230)">
<path d="M250,124.3c-35,0-63.4,28.8-63.4,64.1c0,35.3,28.5,64,63.4,64s63.4-28.8,63.4-64.1C313.4,153,285,124.3,250,124.3z
M250,222c-18.3,0-33.2-15.1-33.2-33.7s14.9-33.7,33.2-33.7s33.2,15.1,33.2,33.7S268.3,222,250,222z" />
<path d="M250,50.9c-74.9,0-135.8,61.6-135.8,137.4c0,31.3,22.5,84.4,66.9,157.7c32.9,54.4,66.2,100.3,66.6,100.7l2.4,3.3l2.4-3.3
c0.3-0.5,33.7-46.3,66.6-100.7c44.4-73.3,66.9-126.4,66.9-157.7C385.8,112.5,324.9,50.9,250,50.9z M250,397.6
c-16.5-24.3-45.5-68.4-69.9-114c-23.5-44-35.9-77-35.9-95.4c0-59,47.4-107,105.8-107s105.8,48,105.8,107
c0,18.4-12.4,51.4-35.9,95.4C295.4,329.3,266.5,373.4,250,397.6z" />
</g>
</defs>
<!--use the same coordinates for the center of the circle and the pin-->
<circle cx="50%" cy="1.5" r="1.5" fill="green" />
<use xlink:href="#pin" x="50%" y="1.5" fill="white" />
</svg>
I was just going through THIS fiddle and the code looks like below:
<svg width=200 height=200 viewbox="0 0 225 225" >
<path d="M220, 220
A200, 200, 0, 0, 0, 20, 20
L 20, 220
Z"
fill = "lightskyblue">
</path>
</svg>
Now when i play around with the viewbox and change the value to viewbox="100 100 225 225" it has the effect of doing something like:
transform:translate(-100px, -100px);
Well i believe when i specify 100 as the min-x, min-y the values of viewbox the effect should have been something like
transform:translate(100px, 100px);
But instead the effect is something similar to:
transform:translate(-100px, -100px);
Why so ? can somebody explain ?
By setting minX and minY to 100, what you are doing is telling the SVG renderer that the top left of your SVG starts at (100,100). And that point should be at the top left of the SVG viewport.
It is the same as if you decided your ruler started at the 10cm mark. The 12cm mark would appear to be at 2cm instead of 12cm. In other words 10cm further left (lower).
Have a look at the following sample SVG. I've marked out an area which we will make set the viewport and viewBox to in a later example.
<svg width="600" height="600">
<!-- mark the area that will become the viewport -->
<rect x="100" y="100" width="300" height="200" fill="linen"/>
<!-- add some other content -->
<circle cx="120" cy="120" r="20" fill="red"/>
<circle cx="200" cy="200" r="50" fill="red"/>
<circle cx="380" cy="270" r="50" fill="red" fill-opacity="0.3"/>
</svg>
If we now set the viewBox to the cream coloured area and set the viewport (SVG width and height) correspondingly, you will see what happens.
<svg width="300" height="200" viewBox="100 100 300 200">
<!-- mark the area that will become the viewport -->
<rect x="100" y="100" width="300" height="200" fill="linen"/>
<!-- add some other content -->
<circle cx="120" cy="120" r="20" fill="red"/>
<circle cx="200" cy="200" r="50" fill="red"/>
<circle cx="380" cy="270" r="50" fill="red" fill-opacity="0.3"/>
</svg>
You can see that the small red circle which is roughly at 100,100, is now at the top left of the viewport.
Hope this makes it clearer for you.
Imagine you have a sheet of paper with your drawing on it and you overlay a piece of cellulite (or anything transparent) on top.
Draw a box on the cellulite and colour in everything outside the box.
Move the cellulite to the right.
Your drawing (the part you can still see within the cellulite box) appears to have moved to the left.
the viewBox is the cellulite box in this example.
I have the following path
<svg class="svg" height="100%" width="100%">
<polygon points="0,0 200,0 100,100" style="fill:lime;stroke:purple;stroke-width:1" />
</svg>
The 0,0 refers to the top left corner of the SVG. How do I make it refer to the bottom right so that the triangle is always in the bottom right corner of the SVG (and it's parent div)?
This following question asked a similar question but no one answered it Svg path position
Happy Holidays
So the answer is to edit the perserve aspect ration to make it aligned to the xmax (right side) and ymin (bottom side) to make the bottom right corner positioning.
Below is the code
<svg viewBox="0 0 100 100" width="100%" height="100%" preserveAspectRatio="xMaxYMin meet">
<g>
<polygon points="0,100 0,90 100,100" style="fill:yellow;" />
</g>
</svg>
First, your SVG will need to have a viewBox if you want consistent rendering.
For example:
<svg class="svg" height="100%" width="100%" viewBox="0 0 600 600">
<polygon points="0,0 200,0 100,100" style="fill:lime;stroke:purple;stroke-width:1" />
</svg>
You don't precisely describe how you want the document to behave when the origin is shifted.
If you just want to shift the origin to the bottom right, you can just surround your content with a group element that shifts the coordinate space to 600,600.
<svg class="svg" height="100%" width="100%" viewBox="0 0 600 600">
<g transform="translate(600 600)">
<polygon points="0,0 200,0 100,100" style="fill:lime;stroke:purple;stroke-width:1" />
</g>
</svg>
But that will mean that your triangle is off the bottom right of the screen, so you would need to adjust all your triangle coords accordingly.
<svg class="svg" height="100%" width="100%" viewBox="0 0 600 600">
<g transform="translate(600 600)">
<polygon points="-200,-200 0,-200 -100,-100" style="fill:lime;stroke:purple;stroke-width:1" />
</g>
</svg>
Fiddle here
However if you actually wanted to invert the whole coordinate space so that the origin is at the bottom right and positive coordinate space is up and to the left - which is really just rotating the document 180deg - you can use:
<svg class="svg" height="100%" width="100%" viewBox="0 0 600 600">
<g transform="rotate(180 300 300)">
<polygon points="0,0 200,0 100,100" style="fill:lime;stroke:purple;stroke-width:1" />
</g>
</svg>
Fiddle here
Aside from using javascript, this seems like the best option available.
Right aligned coordinates in SVG
Is it possible to use one SVG shape as the fill of another shape?
You want to use an SVG Pattern. See this example:
<svg viewBox="0 0 800 400" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="TrianglePattern" patternUnits="userSpaceOnUse"
x="0" y="0" width="100" height="100"
viewBox="0 0 10 10" >
<path d="M0,0 L7,0 L3.5,7 z" fill="red" stroke="blue" />
</pattern>
</defs>
<!-- The ellipse is filled using a triangle pattern paint server
and stroked with black -->
<ellipse fill="url(#TrianglePattern)" stroke="black" stroke-width="5"
cx="400" cy="200" rx="350" ry="150" />
</svg>
Note that:
The viewBox of the <pattern> will clip what is drawn. (As seen in the example, the top stroke and top-left corner each triangle is slightly hidden.)
When the viewBox is a different size from the width and height you are effectively scaling the size of the graphic(s) in your pattern. (The example scales the 7-unit-wide triangle in the pattern up by a factor of 10, such that only 7 of them—plus padding—are visible across the width of a 700-unit-wide ellipse.)