用d3.js+svg绘制圆内接正多边形

试想一下,如果要我们用尺规在纸上绘制圆内接正n边形,这并不是一件很容易做到的事情。但如果要我们在浏览器上完成这个任务,只要掌握了技巧,这会是一件很容易的事。

先看一下已经绘制出来的效果
在这里插入图片描述
从图形上我们可以看出来,先是绘制了一个圆,然后在圆内依次画出了圆的内接正6边形,正5边形,正4边形,正3角形。形成了覆盖效果。

再看一下对应的javascript代码

<!DOCTYPE html>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<head>
<title>绘制圆内接正多边形</title>
<script src="d3.v3.min.js" charset="utf-8"></script>
</head>

<body>
<h2>绘制圆内接正多边形</h2>

<div  id="stage" width="800" height="800"></div>  

<script type="text/javascript">

// 设置svg
var svg = d3.select("#stage").append("svg")
    .attr("width", 800)
    .attr("height", 800); 

// 画圆
var myCircle = svg.selectAll(".cycle")  
    .data([1])
    .enter()  
    .append("circle")   
    .attr("cx", 400)
    .attr("cy", 400)
    .attr("r", 200)
    .style("fill", "#219E3E")
    .style("stroke", "#17301D")
    .style("stroke-width", "2");  

//画多边形
var myPolygon = svg.selectAll(".polygon")
    //.data([16,15,14,13,12,11,10,9,8,7,6,5,4,3])
    .data([6,5,4,3])
    .enter()
    .append("polygon")   
    .attr("points", function (d, i) { return polygonPoints(400,400,200,d); } )    
    .style("fill", "lime")
    .style("stroke", "purple")
    .style("stroke-width", "2");   



/*
*求圆内接正多边形的顶点串,形如x1,y1,x2,y2,...xn,yn
*cx,cy为圆心,r为半径,n为边数,正多边形底边与X轴平行
*/
function polygonPoints(cx,cy,r,n){
    var alpha=2*Math.PI/n;
    var a=Math.PI/2+alpha/2;
    var points="";
    for(var i=0;i<n;i++){
        x=cx+r*Math.cos(a);
        y=cy+r*Math.sin(a);
        points+=x+","+y+",";
        a+=alpha;
    }    
    return points.substring(0,points.length-1);
}

</script>


</body>
</html>

从源码中可以看出,引入了一个js组件:d3.v3.min.js。

我们将代码稍做一点改动,就可以依次画出圆的内接正8边形,正7边形,正6边形,正5边形,正4边形,正3角形.
效果如下:
在这里插入图片描述
如果我不说明,恐怕你很难猜出来这到底画的是什么。
能够实现复杂的绘图效果,但是源代码却非常简单。这是为什么?

因为d3.js+svg的结合,极大地简化我们的绘图工作量。就拿本文的例子来说。svg本就是一种描述性的绘图语言(或者说标准)。只要我们给出了图形的基本要素,具体的绘制工作就不用我们操心了。

而d3.js的作用是什么呢?它可以非常方便地将数据转换为dom中的元素。所以称之为数据驱动文档的工具。

下面简单地说明一下绘图的原理。
要绘制一个圆
svg的基本语法是:

<svg width="800" height="800"><circle cx="400" cy="400" r="200" style="fill: rgb(33, 158, 62); stroke: rgb(23, 48, 29); stroke-width: 2px;"></circle></svg>

也就是说在svg标签中加入一个circel标签就可以画出一个圆,而一个圆的基本要素是圆心与半径。svg中用cx,xy属性指明圆心的x坐标与y坐标。r指明圆的半径。

再对照一下d3.js代码

// 画圆
var myCircle = svg.selectAll(".cycle")  
    .data([1])
    .enter()  
    .append("circle")   
    .attr("cx", 400)
    .attr("cy", 400)
    .attr("r", 200)
    .style("fill", "#219E3E")
    .style("stroke", "#17301D")
    .style("stroke-width", "2");  

就会发现d3.js将用svg绘图的工作进一步简化,并且可以用对象化操作的方式来设置对象的各种属性,除了前面提到的圆心,半径,颜色,线型都可以方便地设置。

要绘制一个多边型,以最简单的三边形为例,svg的语法是:

<svg width="800" height="800"><polygon points="226.7949192431123,500.00000000000006,399.99999999999994,200,573.2050807568878,499.9999999999999" style="fill: lime; stroke: purple; stroke-width: 2px;"></polygon></svg>

也就是说在svg标签中加入一个polygon标签就可以画出一个多边形,而polygon标签的points属性指明的多边形的各个顶点的坐标。

再看一下对应的d3.js的代码

//画多边形
var myPolygon = svg.selectAll(".polygon")
    //.data([16,15,14,13,12,11,10,9,8,7,6,5,4,3])
    .data([3])
    .enter()
    .append("polygon")   
    .attr("points", function (d, i) { return polygonPoints(400,400,200,d); } )    
    .style("fill", "lime")
    .style("stroke", "purple")
    .style("stroke-width", "2");   

这里的代码稍稍有点费解,但正是d3.js强大性的体现。在画圆时,cx,cy属性是直接给出来的。而在这里画三角形的最关键的属性points的值是由一个匿名函数
function (d, i) { return polygonPoints(400,400,200,d); }决定的。

也就是说可以根据参数d来动态地返回points。而这里的d代表数据集中的当前数据,数据集只是一个简单的数组 [3],所以d就代表3.

如果将数据集换成[6,5,4,3],就可以一次指定要画6边形,5边形,4边形,3边形,points的值将会根的参数d的不同而调用函数计算出来。

这就是d3.js的强大之处,画一个多边形与画一百个多边形,一万个多边形,代码不用发生变化,只要把数据集从1个元素的数组替换成100个元素的数组,10000个元素的数组。确实是很方便。

再看一下画出4个正多边形的代码,就会明白我说的意思了。

//画多边形
var myPolygon = svg.selectAll(".polygon")
    //.data([16,15,14,13,12,11,10,9,8,7,6,5,4,3])
    .data([6,5,4,3])
    .enter()
    .append("polygon")   
    .attr("points", function (d, i) { return polygonPoints(400,400,200,d); } )    
    .style("fill", "lime")
    .style("stroke", "purple")
    .style("stroke-width", "2");   

如果想进一步了解d3.js强大而又有趣的功能,可以简单搜索一下d3.js的教程,上面有更多的例子。

补充说明,要画出内接正多边形,需要一点小小的解析几何的知识,这就是下面的函数中所蕴含的几何知识

/*
*求圆内接正多边形的顶点串,形如x1,y1,x2,y2,...xn,yn
*cx,cy为圆心,r为半径,n为边数,正多边形底边与X轴平行
*/
function polygonPoints(cx,cy,r,n){
    var alpha=2*Math.PI/n;
    var a=Math.PI/2+alpha/2;
    var points="";
    for(var i=0;i<n;i++){
        x=cx+r*Math.cos(a);
        y=cy+r*Math.sin(a);
        points+=x+","+y+",";
        a+=alpha;
    }    
    return points.substring(0,points.length-1);
}

如果对代码有疑惑,那么是时候复习一下中学的数学知识了。除了参加高考,原来中学的数学知识也是有那么一点用处的。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
d3.js是一个用于数据可视化的JavaScript库,它提供了丰富的功能和工具来创建交互式和动态的数据可视化图表。其中,svg的path标签在d3.js中被称为"可以组成任何形状的形状"。d3.js提供了多种path生成器,可以用来创建不同类型的路径。 以下是一些常用的d3.js svg path生成器: 1. d3.svg.line() - 线path生成器 2. d3.svg.line.radial() - 径向path生成器 3. d3.svg.area() - 区域path生成器 4. d3.svg.area.radial() - 径向区域path生成器 5. d3.svg.arc() - 圆与圆弧path生成器 6. d3.svg.symbol() - 符号path生成器 7. d3.svg.chord() - chord path生成器 8. d3.svg.diagonal() - diagonal path生成器 9. d3.svg.diagonal.radial() - diagonal radial path生成器 这些生成器可以通过调用相应的方法来生成路径,并且还可以使用其他方法来改变其属性。此外,这些生成器还支持链式调用,可以方便地进行多个操作。 范例: ```javascript // 创建一个svg元素 var svg = d3.select("body") .append("svg") .attr("width", 500) .attr("height", 500); // 创建一个线path生成器 var lineGenerator = d3.svg.line(); // 创建一个路径并设置其属性 var path = svg.append("path") .attr("d", lineGenerator([[0, 0], [100, 100], [200, 50]])) .attr("stroke", "black") .attr("fill", "none"); // 创建一个圆与圆弧path生成器 var arcGenerator = d3.svg.arc() .innerRadius(50) .outerRadius(100) .startAngle(0) .endAngle(Math.PI); // 创建一个路径并设置其属性 var path = svg.append("path") .attr("d", arcGenerator()) .attr("transform", "translate(250, 250)") .attr("fill", "red"); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值