changing the start point in svg circle - svg

I want to use the below SVG but the the fill starts from 3 O clock.
I want the fill to start from 12 O clock.
Please give suggestions on how to achieve that.
<svg id="svg" width="200" height="200" viewPort="0 0 100 100" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<circle r="90" cx="100" cy="100" fill="transparent" stroke-dasharray="565.48"
stroke-dashoffset="0"></circle>
<text id="percentile" x="50%" y="50%" text-anchor="middle" stroke="#191919"
stroke-width="1px" font-size="35" dy="0.3em">{{pct}}</text>
<!--<text id="percentile" x="50%" y="50%" text-anchor="middle" stroke="#191919"
stroke-width="1px" font-size="20" dy="-0.3em">Percentile</text>-->
<circle id="bar" r="90" cx="100" cy="100" fill="transparent"
stroke-dasharray="565.48" stroke-dashoffset="0"></circle>
</svg>

I presume you are using the image to show some kind of progress, i.e. it starts at completely gray, then gradually fills up with yellow starting from 3 o'clock as the proportion goes from 0 to 1 (or 0% to 100%), and the image shows what it looks like at 50%. You want to shift the start from 3 o'clock to 12 o'clock.
Update: The original solution I posted here suggested that you could solve this problem by using stroke-dashoffset. However, that solution was incorrect: it only works for small percentages of the circle, and breaks down once you try to fill larger proportions of the circle. The updated solution below shows an implementation of the suggestion in the comments below the original question. It involves rotating the circle. The demo code below also addresses one of the concerns you expressed for this solution in your comments, i.e. the demo code shows that if the rotation is applied only to the circle, it should not affect text that is placed within the circle.
<svg id="svg" width="500" height="200">
<g transform="">
<circle r="90" cx="100" cy="100" fill="none" stroke="gray" stroke-width="20"></circle>
<circle id="bar" r="90" cx="100" cy="100" fill="none" stroke="orange" stroke-width="20" stroke-dasharray="70.69 494.80" transform="rotate(0, 100, 100)"></circle>
<text x="35" y="100" font-family="Verdana" font-size="15">Text inside circle</text>
</g>
<g transform="translate(250)">
<circle r="90" cx="100" cy="100" fill="none" stroke="gray" stroke-width="20"></circle>
<circle id="bar" r="90" cx="100" cy="100" fill="none" stroke="orange" stroke-width="20" stroke-dasharray="70.69 494.80" transform="rotate(-90, 100, 100)"></circle>
<text x="35" y="100" font-family="Verdana" font-size="15">Text inside circle</text>
</g>
</svg>

Related

SVG Chrome Rendering Bug with Dominant Baseling inside Group Transform

The second X in the circle below is aligned vertical centrally on Firefox but not on Chrome, is this a bug?
The first X is aligned correctly on both.
<svg height="200">
<circle cx="100" cy="100" r="100" fill="red"></circle>
<text x="100" y="100" dominant-baseline="central" text-anchor="middle" font-size="50">X</text>
</svg>
<svg width="340px" height="100px" viewBox="0 0 100 29.41"><g transform="translate(8.333333333333334 7.500000000000001) scale(15.000000000000002 15.000000000000002)"><circle cx="0" cy="0" r="0.5" fill="red"></circle><text x="0" y="0" dominant-baseline="central" text-anchor="middle" font-size="0.4">X</text></g></svg>

How to color a region i.e the intersection of two object?

I want to color an intersection of two object, let's say a circle and a rectangle.
What I have tried so far is to defined a path bounding that region then add the fill attribute, but it seems too complicated.
Is there any other ways to do so?
Let me elabotare more one the problem:
<svg width="352" height="57" xmlns="http://www.w3.org/2000/svg">
<line y2="0.75" x2="103.95" y1="43.15" x1="42.35" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="50.35" x2="201.55" y1="0.75" x1="103.95" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="19.15" x2="239.95" y1="49.55" x1="201.55" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="55.95" x2="282.35" y1="18.35" x1="240.75" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
<line y2="37.55" x2="351.15" y1="31.95" x1="0.75" fill-opacity="null" stroke-opacity="null" stroke-width="1.5" stroke="#000" fill="none"/>
</svg>
I have a set of lines which the end of one is another end of the other.
I have another line intersecing these line.
How could I color the region i.e the triangles formed by these line?
You can use <clipPath> to clip the rect with the circle like so:
svg{width:100vh;}
<svg viewBox="50 50 200 100">
<clipPath id="clip">
<use xlink:href="#c" />
</clipPath>
<g fill="none" stroke="black" >
<circle id="c" cx="100" cy="100" r="30" />
<rect id="r" x="90" y="80" width="80" height="60" />
</g>
<use xlink:href="#r" clip-path="url(#clip)" fill="gold" />
</svg>
You could work with opacity to let the color of an overlapped element shine through like shown here:
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg">
<g style="stroke:#000; stroke-width:1">
<circle cx="50" cy="50" r="50" opacity="0.5" style="fill:red" />
<circle cx="100" cy="50" r="50" opacity="0.5" style="fill:yellow" />
<rect x="0" y="70" width="150" height="50" fill-opacity="0.5" style="fill:blue" />
</g>
</svg>
You can also specify the opacity levels separately for stroke and fill by using stroke-opacity and fill-opacity.
Edit:
Looking at your edited question again: when you are dealing with a succession of lines (and curves) you should use <path> elements instead of individual <line> elements. One of its advantages is that it comes with a fill behaviour that is almost exactly as you want it to be. However, to suit the requirements of your example you would need to find the positions where the straight line enters and leaves the zig-zag shape. These positions then define the points used for your filled path. The "original" (non-filled) path is then plotted over the filled path:
<svg width="352" height="57" xmlns="http://www.w3.org/2000/svg">
<path d="M56,33 103.95,0.75 201.55,50.35 239.95,19.15 260,36z
M0.75,31.95 351.15,37.55" style="fill:yellow" />
<path d="M42.35,43.15 103.95,0.75 201.55,50.35 239.95,19.15 282.35,55.95
M0.75,31.95 351.15,37.55" style="stroke:black;fill:none"/>
</svg>

SVG Path - render only a percent of the specified path

NOTE: I have a feeling that the answers to this question will rely on the dashed stroke trick often used to answer questions about animating svg path ( e.g. Animate svg path, and the countless other similar questions). If possible, I am looking for an answer that does not rely on dashed lines.
Suppose you have an SVG with a path between some number of objects. You know where the objects are centered and their width. In principal you could calculate a path that only goes from the the edges of each object. However, this can be tedious. So how can you specify a path form object 1 to object 2, but offset the drawn part so it is only shown from the edges?
In the code below, the first path between two points uses their center.
This is how I want to specify my path. The second path is how I would like the path to be rendered. e.g. I am looking for some attribute like offset-from-start=10 and offset-from-end=10 to do this. If the path is compound or if the object has an irregular shape, calculating the angle of the shorter path is tedious (but straightforward). In addition, using a shorter path, changes curves, where hopefully this offset does not.
<svg style="width:200px;height:200px">
<circle r="10" cx="10" cy="10" fill="red"></circle>
<circle r="10" cx="190" cy="10" fill="red" style="opacity:0.5"></circle>
<path d="M10 10 L 190 10" stroke-width="4" stroke="black"></path>
<circle r="10" cx="10" cy="50" fill="red"></circle>
<circle r="10" cx="190" cy="50" fill="red" style="opacity:0.5"></circle>
<path d="M20 50 L 180 50" stroke-width="4" stroke="black"></path>
</svg>
If you want to avoid using the stroke-dasharray property, how about simply hiding the part of the path that intersects your object? The straightforward way to do this is avoiding partial transparency and drawing the path below:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="width:200px;height:50px">
<path d="M10 10 L 190 10" stroke-width="4" stroke="black"></path>
<circle r="10" cx="10" cy="10" fill="red"></circle>
<circle r="10" cx="190" cy="10" fill="#ff8080"></circle>
</svg>
A bit more sophisticated would be to define a mask. For that, you need to first define any object inside the mask without styling (implicit black) on a white background, and then reuse them with the visual styles:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
style="width:200px;height:50px">
<mask id="mask" maskUnits="userSpaceOnUse">
<rect width="100%" height="100%" fill="white" />
<circle id="obj1" r="10" cx="10" cy="10" />
<circle id="obj2" r="10" cx="190" cy="10" />
</mask>
<use xlink:href="#obj1" fill="red" />
<use xlink:href="#obj2" fill="red" opacity="0.5" />
<path d="M10 10 L 190 10" stroke-width="4" stroke="black" mask="url(#mask)" />
</svg>

Make a path get cut off by a circle

Is there a way to cut off a path when it is outside of a circle?
<svg width="100" height="100">
<circle cx="50" cy="50" r="50" fill="red" />
<path d="M0 0 L100 100" stroke-width="1px" stroke="black" />
</svg>
Is it possible to make that line stay inside the circle (and not be visible off of the circle) without changing the d="M200 175 L696 880" in the path?
You can use a clipPath to prevent things drawing outside another shape.
<svg width="100" height="100">
<clipPath id="clip">
<circle cx="50" cy="50" r="50" fill="red" />
</clipPath>
<circle cx="50" cy="50" r="50" fill="red" />
<path d="M0 0 L100 100" stroke-width="1px" stroke="black" clip-path="url(#clip)"/>
</svg>

Add a stroke to a clipped path

I'd like to display a stroke around the intersection of two circles.
Here's my code:
<clipPath id="clip">
<circle cx="100" cy="100" r="50" />
</clipPath>
<circle cx="150" cy="100" r="50" fill="red" clip-path="url(#clip)" stroke="black" />
The stroke of the clipped circle is getting clipped by the clipPath as well, but I'd like it to wrap around the intersection of both circles.
Just add half the stroke width to the radius of the clipping circle.
For instance, we have circles of radius 50 and stroke width 10. So we make the clipping circle have a radius of (50 + 5) = 55.
<svg>
<clipPath id="clip1">
<circle cx="100" cy="100" r="55" stroke="black" fill="none" stroke-width="5"/>
</clipPath>
<clipPath id="clip2">
<circle cx="150" cy="100" r="55" stroke="black" fill="red" stroke-width="5"/>
</clipPath>
<circle cx="150" cy="100" r="50" stroke="black" fill="red" stroke-width="10" clip-path="url(#clip1)" />
<circle cx="100" cy="100" r="50" stroke="black" fill="none" stroke-width="10" clip-path="url(#clip2)" />
</svg>
One option would be to have both circles act both as clip paths and as stroked circles.
<clipPath id="clip1">
<circle cx="100" cy="100" r="50" id="circle1" stroke="black" fill="none"/>
</clipPath>
<clipPath id="clip2">
<circle cx="150" cy="100" r="50" id="circle2" stroke="black" fill="red"/>
</clipPath>
<use xlink:href="#circle2" clip-path="url(#clip1)"/>
<use xlink:href="#circle1" clip-path="url(#clip2)"/>
Make sure the second <use> element is not filled because it would cover half of the stroke of the first <use> element.

Resources