说明

写这篇文章是因为某天看到这样一个公式 r=a(1-cosθ) ,我上网搜了下,原来是笛卡尔心形线的极坐标方程,这个方程里面的确有一个浪漫又悲情的爱情故事,感兴趣的朋友可以点这里看看,而至于这个故事是真是假,这 并不重要。

而这篇文章的目的是要用前端的方式,画出笛卡尔心形线。
本来我想,这么经典的公式,网上应该已经有人实现过了吧。
我搜了搜,不得不佩服网友们,有 Java 实现的,有 C# 实现的,也有 canvas 实现的,还能用 ECharts 画 ,可以学习学习。

好的,开始正文!
先来了解下心形线

心形线,是一个圆上的固定一点在它绕着与其相切且半径相同的另外一个圆周滚动时所形成的轨迹,因其形状像心形而得名。

因为 canvas 是直角坐标系的,所以先来看

平面直角坐标系 画法

先贴出网上搜来的 心形线的平面直角坐标系方程表达式
分别为 x^2+y^2+a*x=a*sqrt(x^2+y^2)x^2+y^2-a*x=a*sqrt(x^2+y^2

为什么会有两个方程表达式?
因为心形线的水平方向 和 垂直方向 对应的方程表达式不同,而用相同的方程表达式画的心形线,把每个点的 x 坐标和 y 坐标交换下,又会改变方向,所以会有两个方程表达式。

好了,开始画吧,看看这位朋友的做法
思路
根据方程表达式得到所有点的坐标,然后把每个点连接起来,然后填充,最后就行成一个心形了。

参数方程

x=a*(2*sin(t)+sin(2*t))
y=a*(2*cos(t)+cos(2*t))

x,y 分别表示一个点的 x 坐标 和 y 坐标,
a:是一个常数,用来控制心形的大小,
t :代表 弧度
t 的取值范围:-pi<=t<=pi 或 0<=t<=2*pi

代码

<!doctype html>
<html lang="en"><head><meta charset="UTF-8"></head><body><canvas width="400" height="400"></canvas><script>var canvas = document.querySelector('canvas');var context = canvas.getContext('2d');  context.lineWidth = 3;// 将画布的原点(0,0),移动到(200,200)// 移动原点是为了能让整个心形显示出来context.translate(200,200); // t 代表弧度var t=0;// maxt 代表 t 的最大值var maxt = 2*Math.PI;// vt 代表 t 的增量var vt = 0.01;// 需要循环的次数var maxi = Math.ceil(maxt/vt);// 保存所有点的坐标的数组var pointArr=[];// x 用来暂时保存每次循环得到的 x 坐标var x=0;// y 用来暂时保存每次循环得到的 y 坐标var y=0;// 根据方程得到所有点的坐标for(var i=0;i<=maxi;i++){// x=a*(2*sin(t)+sin(2*t))x=50*(2*Math.sin(t)+Math.sin(2*t));// y=a*(2*cos(t)+cos(2*t))y=50*(2*Math.cos(t)+Math.cos(2*t));t+=vt;pointArr.push([x,y]); }// 根据点的坐标,画出心形线context.moveTo(pointArr[0][0],pointArr[0][1]);draw();function draw(){context.fillStyle='#c00';// 把每个点连接起来for(var i=1;i<pointArr.length;i++){x = pointArr[i][0];y = pointArr[i][1];context.lineTo(x,y);}context.fill();}</script></body>
</html>

效果图

平面直角坐标系 画法 (空心心形)

上面的代码是画一个实心的心形,当然我们也可以画空心的,只需要做出一点点的修改就可以。
我们只需要改改 draw() 函数就好,把原来的 fill() 方法,改为 stroke() 方法,并且把 strokeStyle 设置了颜色就行了。

function draw(){//context.fillStyle='#c00';context.strokeStyle='#c00';// 把每个点连接起来for(var i=1;i<pointArr.length;i++){x = pointArr[i][0];y = pointArr[i][1];context.lineTo(x,y);}//context.fill();context.stroke();
}

极坐标系画法

极坐标系是这样的

极坐标系中确定一个点的位置,靠的是极点(图中点O),和 角度 来确定的。
更多关于极坐标系的知识,可以看看这里

看看这位朋友的做法
思路
根据极坐标方程 r=a(1+sinθ) ,得到 r ,以 r 作为半径,根据 r 连续的去画圆弧,画完一圈后,心形就出来了。

心形线 极坐标方程
r=a(1+sinθ)

代码

<!doctype html>
<html lang="en"><head><meta charset="UTF-8">
</head><body><canvas width="400" height="400"></canvas><script>var canvas = document.querySelector('canvas');var context = canvas.getContext('2d');// 将画布的原点(0,0),移动到(200,100)// 移动原点是为了能让整个心形显示出来context.translate(200, 100);// 画心形draw();function draw() {// 画圆弧时,圆的半径var r = 0;//  start 代表画弧线时的 起始角var start = 0;//  end 代表画弧线时的 结束角var end = 0;//  一个常数,用来控制心形的大小var a = 100;context.fillStyle = '#e21f27';//连续的画圆弧for (var q = 0; q < 500; q++) {start += Math.PI * 2 / 500;// 当 结束角 是 Math.PI * 2 时也就是已经画了一圈了,心形就出来了end = start + Math.PI * 2 / 500;// 根据极坐标方程 r=a(1+sinθ),得到 r(半径)r = a * (1 + Math.sin(start)); // 画弧线context.arc(0, 0, r, start, end, false);}context.fill();}</script>
</body>
</html>

效果图

极坐标系 画法 (空心心形)

用极坐标系 画法,画空心心形,也是一样的需要改改 draw() 函数,把原来的 fill() 方法,改为 stroke() 方法,并且把 strokeStyle 设置了颜色就行了。

function draw() {var r = 0;var start = 0;var end = 0;var a = 100;//context.fillStyle = '#e21f27';context.strokeStyle = '#e21f27';for (var i = 0; i < 500; i++) {start += Math.PI * 2 / 500;end = start + Math.PI * 2 / 500;r = a * (1 + Math.sin(start)); context.arc(0, 0, r, start, end, false);}//context.fill();// 改用 stroke() 方法context.stroke();
}

可能你会觉得这样的心形并不好看。
看看这个参数方程吧!

x=16 * (sin(t)) ^ 3;
y=13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t)。

根据这个参数方程,用上面说的平面直角坐标系的画法,把代码里的方程换一下,就可以画出这样的心形。

代码

<!doctype html>
<html lang="en"><head><meta charset="UTF-8"></head><body><canvas width="400" height="400"></canvas><script>var canvas = document.querySelector('canvas');var context = canvas.getContext('2d');  context.lineWidth = 3;// 将画布的原点(0,0),移动到(200,200)// 移动原点是为了能让整个心形显示出来context.translate(200,200); // t 代表弧度var t=0;// vt 代表 t 的增量var vt = 0.01;// maxt 代表 t 的最大值var maxt = 2*Math.PI;// 需要循环的次数var maxi = Math.ceil(maxt/vt);// 保存所有点的坐标的数组var pointArr=[];// 控制心形大小var size = 10;// x 用来暂时保存每次循环得到的 x 坐标var x=0;// y 用来暂时保存每次循环得到的 y 坐标var y=0;// 根据方程得到所有点的坐标for(var i=0;i<=maxi;i++){// x=16 * (sin(t)) ^ 3;var x = 16 * Math.pow(Math.sin(t),3);// y=13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t)var y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) -2 * Math.cos(3 * t)- Math.cos(4 * t);t+=vt;pointArr.push([x*size,-y*size]); }// 根据点的坐标,画出心形线context.moveTo(pointArr[0][0],pointArr[0][1]);draw();function draw(){context.fillStyle='#c00';// 把每个点连接起来for(var i=1;i<pointArr.length;i++){x = pointArr[i][0];y = pointArr[i][1];context.lineTo(x,y);}context.fill();}</script></body>
</html>

也许我们还可以再做点什么,比如加点动画,看看下面这个吧。

点这里下载源码,里面已经加了很详细的注释了。

总结

这篇文章主要是说用笛卡尔心形线方程画心形,但是想要画出心形的方式绝对是多种多样的,单纯的用CSS也可以,复杂点 用贝塞尔曲线也能画出来,大家不妨去试试,说不定又有什么新发现呢。

一个浪漫又悲情的爱情故事——笛卡尔心形线相关推荐

  1. python turtle笛卡尔心形线_一个浪漫又悲情的爱情故事——笛卡尔心形线

    说明 写这篇文章是因为某天看到这样一个公式 r=a(1-cosθ) ,我上网搜了下,原来是笛卡尔心形线的极坐标方程,这个方程里面的确有一个浪漫又悲情的爱情故事,感兴趣的朋友可以点这里看看,而至于这个故 ...

  2. 一个浪漫又悲情的爱情故事...

    一键关注

  3. 德芙巧克力诞生的背后,有一个悲情的爱情故事。

    德芙巧克力诞生的背后,有一个悲情的爱情故事.  . 大家都吃过德芙(Dove)巧克力吧.但你知道德芙巧克力的含义吗 就让我们一起体会德芙巧克力背后的悲情故事吧. 1919年的春天,卢森堡王室迎来了夏洛 ...

  4. 笛卡尔心形线——一个凄美的爱情故事(附MATLAB三维心形线和HTML二维心形线代码)

    1650年,斯德哥尔摩的街头,52岁的笛卡尔邂逅了18岁的瑞典公主克里斯汀. 那时,落魄.一文不名的笛卡尔过着乞讨的生活,全部的财产只有身上穿的破破烂烂的衣服和随身所带的几本数学书籍.生性清高的笛卡尔 ...

  5. 【Python】笛卡尔心形线——数学家的浪漫(花式哄小女友第一天)

    文章目录 简介 演示 安装 方程 参数方程 极坐标方程 源码 拓展 仓库 其它 参考 简介 用python的matplotlib库绘制心形线. 演示 心-直角坐标 心-极坐标系 扁点的心 动态绘制 安 ...

  6. Matlab爱心方程式的解析式,数学,才是一切浪漫的开始;看数学大佬笛卡尔玩转数学!...

    提到数学你会想到什么?复杂的计算...无尽的逻辑推演...如魔鬼般的公式和符号...许多学生对数学充满了畏惧小学.中学.高中,等到大学很多人走向专业化之路,与数学分道扬镳,如果你觉得数学的出现只是为了 ...

  7. 分享一个程序猿的真实的爱情故事

    分享一个程序猿的真实的爱情故事 在今天(农历四月十九日)这个特别的日子里,就不分享技术干货了.因为今天是我老婆的生日,所以我改成记录一下关于我这个"老"程序猿跟我老婆之间的故事.也 ...

  8. 无聊使用python画一个笛卡尔心

    无聊使用python画一个笛卡尔心 �� import numpy as np import matplotlib.pyplot as plta = 1 t = np.linspace(0, 2*np ...

  9. python绘制笛卡尔心形曲线_走近解析几何学之父笛卡尔:笛卡尔坐标系与浪漫的心形曲线...

    解析几何是进行科学研究的重要的数学工具.比如说,要确定船只在大海中航行的位置,就要确立经纬度,这就需要精确的掌握夭体运行的规律;要改善枪炮的性能,就要精确地掌握抛射物体的运行规律.解决这些问题必须采用 ...

最新文章

  1. 从事嵌入式开发需要掌握哪些知识?从事嵌入式软件开发的前景如何?
  2. Linux下gcc中各种文件后缀说明
  3. # HDU - 6185 Covering
  4. hihoCoder1678 版本号排序
  5. 160. 相交链表 golang
  6. 用python实现一个按需生成用于vim跳转的tags文件的小程序
  7. 移动项目工作笔记0001---使用uni-app开发移动端应用
  8. 布林通道参数用20还是26_布林通道(BOLL)策略的投资效果如何?
  9. init()函数何时运行?
  10. php如何打开格式_php的文件格式是什么?如何打开php文件[graphic]
  11. bochs运行xp_bochs模拟器xp系统镜像安装教程及注意事项
  12. 学会局域网的锐捷破解共享
  13. 计算机c语言实验心得与小结,C语言实验心得体会
  14. 基于微信小程序办公用品采购系统的设计与实现.rar(毕业论文+程序源码+后端源码)
  15. 2.1用户界面设计的八项黄金法则
  16. python自动登录qq邮箱_python实现自动登录qq邮箱,写邮件并发送
  17. VS2012中的R6002 - floating point support not loaded错误
  18. 写一个GAMEBOY的模拟器
  19. 哪一个属于计算机外存储器,下边哪一个属于计算机的外存储器()
  20. For循环语句及使用

热门文章

  1. 字体样式字体分类字体样式二
  2. 使用图形编辑框架GEF创建基于Eclipse的应用程序
  3. 【小程序云开发转uniCloud阿里云】
  4. android字体加横线
  5. Launcher布局加载流程
  6. 南大通用GBase8s 常用SQL语句(150)
  7. OpenCV实践之路——方形图片对角线切割
  8. R以及RStudio的获取和使用
  9. 时序分析 43 -- 时序数据转为空间数据 (二) 马尔可夫转换场
  10. 高仿QQ源码 界面(3)