SVG marker - can I set length and angle?

后端 未结 2 2067
被撕碎了的回忆
被撕碎了的回忆 2021-01-17 09:35

I\'m trying to draw 6 sticks starting from the centre of the circle with an angle (60 degrees)

\"Desired

相关标签:
2条回答
  • 2021-01-17 10:14

    After wrapping my head around this for a while I came up with a solution which does not require any scripting at all, thus being SVG-only. There are some ideas involved in this:

    1. Your marker is left unchanged.

    2. To simplify matters the elements are placed referring to the SVG's origin in the top left corner. All visible elements are then grouped into one <g> which will be translated to the desired offset, thus tranlating the elements all at once. This frees you from taking into account the position of the circle's center for every calculation of coordinates.

    3. There is a <line> in the <defs> section which acts as a template for the sticks which will be arranged around the big circle. Setting only the y1 attribute will set x1, y1 and x2 to their default values of 0. The value of y1, however, determines the length of the sticks. This line has to be translated by the circle radius (97.5) to be correctly positioned.

    4. When putting everything together inside of the group, the sticks are included by the <use> element referencing the line template from the <defs> section. You are then able to set the desired rotation for each indiviual stick by specifying transform="rotate(..)".

    #markerCircle > circle {
        stroke: none;
        fill: #ef4b22;
    }
    
    #stick {
        stroke: #ef4b22;
        stroke-width: 2px;
        fill: none;
        marker-start: url(#markerCircle);
    }
    
    circle {
        stroke: #ef4b22;
        stroke-width: 10px;
        fill: none;
    }
    <svg width="400" height="400" 
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink">
      
        <defs>
            <marker id="markerCircle" markerwidth="13" markerheight="13" refx="5" refy="7" orient="auto">
                <circle cx="7" cy="7" r="3"/>
            </marker>
            <line id="stick" y1="50" transform="translate(0,97.5)"/>
        </defs>
        
        <g transform="translate(150,152.5)">
            <circle r="97.5" />
            <use xlink:href="#stick" transform="rotate(0)" />
            <use xlink:href="#stick" transform="rotate(60)" />
            <use xlink:href="#stick" transform="rotate(120)" />
            <use xlink:href="#stick" transform="rotate(180)" />
            <use xlink:href="#stick" transform="rotate(240)" />
            <use xlink:href="#stick" transform="rotate(300)" />
        </g>
      
    </svg>

    Note, that for brevity and to emphasize the important aspects I stripped the SVG down as far as possible:

    1. The styling was moved to an external CSS.

    2. Because many attributes have default values in case they are omitted, I got rid of them.

    Any of these changes can easily be reverted by putting the missing information back into the SVG without jeopardizing the overall appearance. If you prefer to have everything contained within a standalone SVG without an external CSS you might as well put the styling back in:

    <svg width="400" height="400" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    
        <defs>
            <marker id="markerCircle" markerwidth="13" markerheight="13" refx="5" refy="7" orient="auto">
                <circle cx="7" cy="7" r="3" style="stroke:none; fill:#ef4b22;" />
            </marker>
            <line id="stick" y1="50" transform="translate(0,97.5)" style="stroke:#ef4b22; stroke-width:2px; fill:none;marker-start: url(#markerCircle);"/>
        </defs>
    
        <g transform="translate(150,152.5)">
            <circle r="97.5" style="stroke:#ef4b22; stroke-width:10px; fill:none;" />
            <use xlink:href="#stick" transform="rotate(0)" />
            <use xlink:href="#stick" transform="rotate(60)" />
            <use xlink:href="#stick" transform="rotate(120)" />
            <use xlink:href="#stick" transform="rotate(180)" />
            <use xlink:href="#stick" transform="rotate(240)" />
            <use xlink:href="#stick" transform="rotate(300)" />
        </g>
    
    </svg>
    
    0 讨论(0)
  • 2021-01-17 10:21

    Here's a demo I made for you.

    The main function used is to find a point on a circle, as below:

    function findPoint(cx, cy, rad, cornerGrad){
      var cornerRad = cornerGrad * Math.PI / 180;
      var nx = Math.cos(cornerRad)*rad + cx;
      var ny = Math.sin(cornerRad)*rad + cy;
      return { x: nx, y: ny };
    }
    
    0 讨论(0)
提交回复
热议问题