John Smit
John Smit

Reputation: 11

SVG - how can I draw stroked circle with cuted element?

Here is (not)exactly what I want get:

https://i.sstatic.net/nMbtl.png

My code:

           <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
                <circle class="circle_shadow" cx="50%" cy="50%" r="6.6%" fill="#333333" />
                <circle class="circle_shadow" cx="50%" cy="50%" r="11%" fill="none" stroke="#333333" stroke-width="7%" />
                <circle class="circle_shadow" cx="50%" cy="50%" r="19%" fill="none" stroke="#333333" stroke-width="7%" />
                <circle class="circle_shadow" cx="50%" cy="50%" r="27%" fill="none" stroke="#333333" stroke-width="7%" />
                <circle class="circle_shadow" cx="50%" cy="50%" r="35%" fill="none" stroke="#333333" stroke-width="7%" />
            </svg>

Upvotes: 1

Views: 3453

Answers (2)

markE
markE

Reputation: 105015

Try drawing Path Arcs instead of Circles

enter image description here

You can use the starting and ending positions of the arc to accomplish the “cuts” that you need.

Here is a javascript helper function that generates the Path Data for concentric arcs.

function regularArcData(cx,cy,radius,startDegrees,endDegrees,isCounterClockwise){

    var offsetRadians=0;  // -Math.PI/2 for 12 o'clock
    var sweepFlag=(isCounterClockwise)?0:1;
    var startRadians=offsetRadians+startDegrees*Math.PI/180;
    var endRadians=offsetRadians+endDegrees*Math.PI/180;
    var largeArc=( (endRadians-startRadians) % (2*Math.PI) ) > Math.PI ? 1 : 0;
    var startX=parseInt(cx+radius*Math.cos(startRadians));
    var startY=parseInt(cy+radius*Math.sin(startRadians));
    var endX=  parseInt(cx+radius*Math.cos(endRadians));
    var endY=  parseInt(cy+radius*Math.sin(endRadians));
    var space=" ";
    var arcData="";

    arcData+="M"+space+startX         +space
                      +startY         +space;
    arcData+="A"+space+radius         +space
                      +radius         +space
                      +offsetRadians  +space
                      +largeArc       +space
                      +sweepFlag      +space
                      +endX           +space
                      +endY;
    return(arcData);
}

Here is code and a Fiddle: http://jsfiddle.net/m1erickson/VbqnW/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
</style>

<script>
    $(function(){

        var svgns="http://www.w3.org/2000/svg";

        var svg=document.createElementNS(svgns,"svg");
        svg.setAttribute('width', '600px');
        svg.setAttribute('height', '600px');
        document.body.appendChild(svg);

        var cx=150;
        var cy=150;

        addPath(svg,"arc1","transparent","red",  15,regularArcData(cx,cy,50,0,135,false));
        addPath(svg,"arc2","transparent","green",15,regularArcData(cx,cy,65+2,0,180,false));
        addPath(svg,"arc3","transparent","blue", 15,regularArcData(cx,cy,80+4,0,215,false));
        addPath(svg,"arc4","transparent","orange", 15,regularArcData(cx,cy,95+6,0,250,false));
        addPath(svg,"arc5","transparent","purple", 15,regularArcData(cx,cy,110+8,0,270,false));


        function addPath(theSvg,id,fill,stroke,strokeWidth,data){
            var path=document.createElementNS(svgns,"path");
            path.setAttribute("id",id);
            path.setAttribute("fill",fill);
            path.setAttribute("stroke",stroke);
            path.setAttribute("stroke-width",strokeWidth);
            path.setAttribute("d",data);
            theSvg.appendChild(path);

            var pathSvg=""
            pathSvg+="\n"
                      +"<path id='"+id
                      +"' fill='"+fill
                      +"' stroke='"+stroke
                      +"' stroke-width='"+strokeWidth
                      +"' d='"+data+"'/>";
             $("#paths").text($("#paths").text()+pathSvg);
        }


        function regularArcData(cx,cy,radius,startDegrees,endDegrees,isCounterClockwise){

            var offsetRadians=0;  // -Math.PI/2 for 12 o'clock
            var sweepFlag=(isCounterClockwise)?0:1;
            var startRadians=offsetRadians+startDegrees*Math.PI/180;
            var endRadians=offsetRadians+endDegrees*Math.PI/180;
            var largeArc=( (endRadians-startRadians) % (2*Math.PI) ) > Math.PI ? 1 : 0;
            var startX=parseInt(cx+radius*Math.cos(startRadians));
            var startY=parseInt(cy+radius*Math.sin(startRadians));
            var endX=  parseInt(cx+radius*Math.cos(endRadians));
            var endY=  parseInt(cy+radius*Math.sin(endRadians));
            var space=" ";
            var arcData="";

            arcData+="M"+space+startX         +space
                              +startY         +space;
            arcData+="A"+space+radius         +space
                              +radius         +space
                              +offsetRadians  +space
                              +largeArc       +space
                              +sweepFlag      +space
                              +endX           +space
                              +endY;
            return(arcData);
        }


    }); // end $(function(){});
</script>

</head>

<body>
    <textarea id="paths" cols=130 rows=7>Paths</textarea><br/>
</body>
</html>

Upvotes: 5

Sanoob
Sanoob

Reputation: 2474

I am not expert with svg but I think you can do this using clipping. Semi-Circle http://jsfiddle.net/XpJEQ/7/

<?xml version="1.0" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <svg viewBox = "0 0 1100 400" version = "1.1">
        <defs>
            <circle id = "r2" cx = "200" cy = "50" r = "100" stroke = "black" stroke-width = "5"/>
            <circle id = "r3" cx = "-30" cy = "130" r = "100" stroke = "black" stroke-width = "5"/>

            <clipPath id = "clip1">
                <path d = "M 0 0 L 550 200 L 1100 0"/>
            </clipPath>
        </defs>
        <g clip-path = "url(#clip1)">
            <use x = "250" y = "0" xlink:href = "#r1" fill = "url(#g1)"/>
            <use x = "350" y = "150" xlink:href = "#r2" fill = "url(#g1)"/>
            <use x = "580" y = "50" xlink:href = "#r3" fill = "url(#g1)"/>
        </g>
    </svg>

For more clipping details check this too clipping and masking

Upvotes: 0

Related Questions