【问题标题】:d3.js - draw ellipse shape with 4 points by svg pathd3.js - 通过 svg 路径绘制 4 个点的椭圆形
【发布时间】:2022-01-26 17:46:32
【问题描述】:

我想通过 svg 路径绘制一个椭圆形。我使用下面的代码,但形状看起来像一个圆角矩形。 如何调整参数以获得eclipse路径!

demo()
function demo() {
    var width = 400
    var height = 200

    var margin = {left:20,top:20,right:20,bottom:20}
    var svg = d3.select('body').append("svg")
    .attr('width',width + margin.left + margin.right)
    .attr('height',height + margin.top + margin.bottom)
    .style('border','2px solid red')
    
    var g = svg.append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)

    var data = [[0,0,400,100]]
    g.selectAll('node')
    .data(data)
    .enter()
    .append('path')
    .attr('class','node')
    .attr('stroke','black')
    .attr('stroke-width',2)
    .attr('fill','none')
    .attr('d',function(d) {
        var w = d[2]
        var h = d[3]
        
        var ax = d[0]
        var ay = d[1] + h/2
        var bx = ax + w/2
        var by = ay + h/2
        var cx = ax + w
        var cy = ay
        var dx = bx
        var dy = d[1]
        add_dot(g,[[ax,ay],[bx,by],[cx,cy],[dx,dy]])
        
        var path = ['M',ax,ay,'C',ax,by,ax,by,bx,by,
            cx,by,cx,by,cx,cy,
            cx,dy,cx,dy,dx,dy,
            ax,dy,ax,dy,ax,ay]
        
        return path.join(' ')
    })
    function add_dot(g,data) {
        g.selectAll('dots')
        .data(data)
        .join('circle')
        .attr('class','dots')
        .attr('cx',d => d[0])
        .attr('cy',d => d[1])
        .attr('r',5)
        .attr('fill','red')

    }
  }
<script src="https://d3js.org/d3.v6.min.js"></script>

【问题讨论】:

  • 应该是“椭圆”吗?
  • 您试图用四条cubic bezier 曲线逼近一个椭圆,但是对于每条曲线(四分之一椭圆),您将两个控制点放在同一个“角”中。必须更加小心地放置这些控制点。参见例如stackoverflow.com/questions/1734745/…

标签: svg d3.js


【解决方案1】:

路径C command 绘制三次贝塞尔线段,可以近似椭圆,但不精确。 A command 绘制一个弧段,一个椭圆的扇形。

demo()
function demo() {
    var width = 400
    var height = 200

    var margin = {left:20,top:20,right:20,bottom:20}
    var svg = d3.select('body').append("svg")
    .attr('width',width + margin.left + margin.right)
    .attr('height',height + margin.top + margin.bottom)
    .style('border','2px solid red')
    
    var g = svg.append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)

    var data = [[0,0,400,100]]
    g.selectAll('node')
    .data(data)
    .enter()
    .append('path')
    .attr('class','node')
    .attr('stroke','black')
    .attr('stroke-width',2)
    .attr('fill','none')
    .attr('d',function(d) {
        var w = d[2]/2
        var h = d[3]/2
        
        var ax = d[0]
        var ay = d[1] + h
        var bx = ax + w
        var by = ay + h
        var cx = ax + w*2
        var cy = ay
        var dx = bx
        var dy = d[1]
        add_dot(g,[[ax,ay],[bx,by],[cx,cy],[dx,dy]])
        
    var path = ['M',ax,ay,'A',w,h,0,0,0,bx,by,
        w,h,0,0,0,cx,cy,
        w,h,0,0,0,dx,dy,
        w,h,0,0,0,ax,ay]
        
        return path.join(' ')
    })
    function add_dot(g,data) {
        g.selectAll('dots')
        .data(data)
        .join('circle')
        .attr('class','dots')
        .attr('cx',d => d[0])
        .attr('cy',d => d[1])
        .attr('r',5)
        .attr('fill','red')

    }
  }
<script src="https://d3js.org/d3.v6.min.js"></script>

【讨论】:

  • 很高兴知道,如果画圆,我应该使用贝塞尔曲线还是A命令?
  • 圆是一种特殊的椭圆,所以使用 A 命令。对于小于整圆 1/4 的线段,三次贝塞尔曲线可以近似为误差小于 0.1% 的弧。讨论here
【解决方案2】:

demo()
function demo() {
    var width = 400
    var height = 200

    var margin = {left:20,top:20,right:20,bottom:20}
    var svg = d3.select('body').append("svg")
    .attr('width',width + margin.left + margin.right)
    .attr('height',height + margin.top + margin.bottom)
    .style('border','2px solid red')
    
    var g = svg.append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)

    var data = [[0,0,400,100]]
    g.selectAll('node')
    .data(data)
    .enter()
    .append('path')
    .attr('class','node')
    .attr('stroke','black')
    .attr('stroke-width',2)
    .attr('fill','none')
    .attr('d',function(d) {
        var w = d[2]
        var h = d[3]
        
        var ax = d[0]
        var ay = d[1] + h/2
        var bx = ax + w/2
        var by = ay + h/2
        var cx = ax + w
        var cy = ay
        var dx = bx
        var dy = d[1]
        add_dot(g,[[ax,ay],[bx,by],[cx,cy],[dx,dy]])
        
    var path = ['M',ax,ay,'C',ax,(ay+by)/2,(ax+bx)/2,by,bx,by,
        (bx+cx)/2,by,cx,(by+cy)/2,cx,cy,
        cx,(cy+dy)/2,(cx+dx)/2,dy,dx,dy,
        (dx+ax)/2,dy,ax,(dy+ay)/2,ax,ay]
        
        return path.join(' ')
    })
    function add_dot(g,data) {
        g.selectAll('dots')
        .data(data)
        .join('circle')
        .attr('class','dots')
        .attr('cx',d => d[0])
        .attr('cy',d => d[1])
        .attr('r',5)
        .attr('fill','red')

    }
  }
<script src="https://d3js.org/d3.v6.min.js"></script>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 2021-02-08
    • 1970-01-01
    相关资源
    最近更新 更多