skip to Main Content

I am working with a dataset that has all the points required to build a circle. I need to utilize the dataset to build a svg path (and not svg circle) element that is circular.

I tried as following which did not work.
What path commands can I use to make the path appear like a full circle.

const svgns = 'http://www.w3.org/2000/svg';
const data = [{
    "x": 384,
    "y": 552
}, {
    "x": 440.4273842,
    "y": 533.6656315
}, {
    "x": 475.3014256,
    "y": 485.6656315
}, {
    "x": 475.3014256,
    "y": 426.3343685
}, {
    "x": 440.4273842,
    "y": 378.3343685
}, {
    "x": 384,
    "y": 360
}, {
    "x": 327.5726158,
    "y": 378.3343685
}, {
    "x": 292.6985744,
    "y": 426.3343685
}, {
    "x": 292.6985744,
    "y": 485.6656315
}, {
    "x": 327.5726158,
    "y": 533.6656315
}, {
    "x": 384,
    "y": 552
}];

const svg = d3.select('#viz')
    .append('svg')
    .attr('xmlns', svgns)
    .attr('viewBox', '0 0 600, 600');

svg.append('path')
    .attr('d', () => {
        return d3.line().x(d => d.x).y(d => d.y)(data)
    })
    .attr('fill', 'none')
    .attr('stroke', 'red');
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<body>   
    <div id="viz"></div>   
</body>
</html>

3

Answers


  1. You can use the D3 curve method to create a smooth transition between points.

    const svgns = 'http://www.w3.org/2000/svg';
    const data=[{x:384,y:552},{x:440.4273842,y:533.6656315},{x:475.3014256,y:485.6656315},{x:475.3014256,y:426.3343685},{x:440.4273842,y:378.3343685},{x:384,y:360},{x:327.5726158,y:378.3343685},{x:292.6985744,y:426.3343685},{x:292.6985744,y:485.6656315},{x:327.5726158,y:533.6656315},{x:384,y:552}];
    
    const svg = d3.select('#viz')
        .append('svg')
        .attr('xmlns', svgns)
        .attr('viewBox', '0 0 600, 600');
        
    const curve = d3.line().curve(d3.curveNatural);
    const points = data.map(Object.values); // [[384, 552], [440.4273842, 533.6656315] ...]
    
    svg.append('path')
        .attr('d', curve(points))
        .attr('fill', 'none')
        .attr('stroke', 'red');
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
    <body>   
        <div id="viz"></div>   
    </body>
    </html>
    Login or Signup to reply.
  2. Answering your specific question – you want to change those "L" commands which are straight line commands, to "A" commands which are arc draw commands. The format of "A" commands is: A|a]rx,ry, x-axis-rotation, large-arc-flag, sweep-flag, x,y

    That gives you the following in your case:

    <svg width="600px" height="400px" viewBox="0 200 1200 800">
      
        <path d="M384,552
            A 100,100,0, 0, 0, 440.427,533.666 
            A 100,100,0, 0, 0, 475.301,485.666 
            A 100,100,0, 0, 0, 475.301,426.334 
            A 100,100,0, 0, 0, 440.427,378.334 
            A 100,100,0, 0, 0, 384,360
            A 100,100,0, 0, 0, 327.573,378.334
            A 100,100,0, 0, 0, 292.699,426.334 
            A 100,100,0, 0, 0, 292.699,485.666
            A 100,100,0, 0, 0, 327.573,533.666
            A 100,100,0, 0, 0, 384,552  "/>
    </svg>
    Login or Signup to reply.
  3. d3 is not really helpfull when it comes to writing the SVG arc command. Both path.arc and path.arcTo use parameters that demand recomputing your data, only so that internally the computation can be reversed. It is easier just to write the attribute string directly.

    This requires the knowledge of three values in advance:

    • the radius of your circle,
    • the largeArc flag: 0 for arcs less than half a circle, 1 for arcs that are longer
    • the sweep flag: 0 for counterclockwise arcs, 1 for clockwise arcs.
    const svgns = 'http://www.w3.org/2000/svg';
    const data = [{
        "x": 384,
        "y": 552
    }, {
        "x": 440.4273842,
        "y": 533.6656315
    }, {
        "x": 475.3014256,
        "y": 485.6656315
    }, {
        "x": 475.3014256,
        "y": 426.3343685
    }, {
        "x": 440.4273842,
        "y": 378.3343685
    }, {
        "x": 384,
        "y": 360
    }, {
        "x": 327.5726158,
        "y": 378.3343685
    }, {
        "x": 292.6985744,
        "y": 426.3343685
    }, {
        "x": 292.6985744,
        "y": 485.6656315
    }, {
        "x": 327.5726158,
        "y": 533.6656315
    }, {
        "x": 384,
        "y": 552
    }];
    
    const r = 96;
    const largeArc = 0;
    const sweep = 0;
    
    const svg = d3.select('#viz')
        .append('svg')
        .attr('xmlns', svgns)
        .attr('viewBox', '0 0 600, 600');
    
    svg.append('path')
        .attr('d', () => {
            return data.reduce((path, d, i) => {
                if (i) {
                    path += `A${r} ${r} 0 ${largeArc}${sweep}${d.x},${d.y}`;
                } else {
                    path += `M${d.x},${d.y}`;
                }
                return path;
            }, "");
        })
        .attr('fill', 'none')
        .attr('stroke', 'red');
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
    <body>   
        <div id="viz"></div>   
    </body>
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search