虽然标题是画椭圆,但是我们先来说说Canvas中的圆

相信大家对于Canvas画圆都不陌生

oGC.arc(400, 300, 100, 0, 2*Math.PI, false);

如上所示,直接调用API就可以了,但是计算机内部却是使用光栅学,利用bresenham算法画圆的,这个我们放到最后来说,先说说利用圆的参数方程画圆

circle(oGC, 400, 300, 100);
function circle(context, x, y, a) { // x,y是坐标;a是半径var r = 1/a; // ①注意:此处r可以写死,不过不同情况下写死的值不同context.beginPath();context.moveTo(x + a, y);for(var i = 0; i < 2 * Math.PI; i += r) {context.lineTo(x + a * Math.cos(i), y + a * Math.sin(i));}context.closePath();context.fill();
}

原理是什么,相信三角函数不错的童鞋理解起来很容易的,如果不知道的话,注意注释①,我变化一下r的值,相信就立竿见影了~

r和2*Math.PI配合就是圆的精细程度,在半径为100的时候,r取1/10就可以了,通用的话可以写死,写成r = 1 / a;这样无论半径取大或者小,圆都会很精细,但是性能会有很大影响

现在来看看文章的主角,针对圆来看椭圆的

function EllipseOne(context, x, y, a, b) {var step = (a > b) ? 1 / a : 1 / b;context.beginPath();context.moveTo(x + a, y);for(var i = 0; i < 2 * Math.PI; i += step) {context.lineTo(x + a * Math.cos(i), y + b * Math.sin(i));}context.closePath();context.fill();
}

和圆基本一样,不过圆只有一个半径,而椭圆分为长轴和短轴了。

看下效果~

好了,画椭圆成功,文章结束~

怎么可能!!

就这样结束也太没品了,刚刚是方法一,下面来看其他的

方法二,均匀压缩法

这是我最喜欢的方法,易理解,相比较方法一,性能也快了很多,先贴代码~

function EllipseTwo(context, x, y, a, b) {context.save();var r = (a > b) ? a : b;var ratioX = a / r;var ratioY = b / r;context.scale(ratioX, ratioY);context.beginPath();context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI, false);context.closePath();context.restore();context.fill();
}

原理是利用了scale来对一个标准的圆进行压缩,ratioX是横轴缩放比率,ratioY是纵轴缩放比率,就因为这两个值不同,使得将标准圆缩放成了一个椭圆

记得save()和restore()还原context环境,so easy理解的方法

下面两种方法很高大上,都是利用三次贝塞尔曲线法

方法三,四,贝塞尔法

function EllipseThree(context, x, y, a, b) {var ox = 0.5 * a,oy = 0.6 * b;context.save();context.translate(x, y);context.beginPath();context.moveTo(0, b);context.bezierCurveTo(ox, b, a, oy, a, 0);context.bezierCurveTo(a, -oy, ox, -b, 0, -b);context.bezierCurveTo(-ox, -b, -a, -oy, -a, 0);context.bezierCurveTo(-a, oy, -ox, b, 0, b);context.closePath();context.fill();context.restore();
}function EllipseFour(context, x, y, a, b) {var k = 0.5522848,ox = k * a,oy = k * b;context.translate(x, y);context.beginPath();context.moveTo(-a, 0);context.bezierCurveTo(-a, oy, -ox, -b, 0, -b);context.bezierCurveTo(ox, -b, a, -oy, a, 0);context.bezierCurveTo(a, oy, ox, b, 0, b);context.bezierCurveTo(-ox, b, -a, oy, -a, 0);context.closePath();context.fill();
}

贝塞尔法的核心在于两个控制点的选取,但是它有致命的问题,当lineWidth较宽的时候,椭圆较扁,长轴较尖锐,会出现不平滑的情况

如果不知道什么事贝塞尔的话就自行百度……这个不解释了……

后面还有最后一种光栅法画椭圆,光栅法画圆很简单,画椭圆挺麻烦的,下面是最简单的一种椭圆画法,等于是lineWidth为1px的情况下

function EllipseFive(context, x, y, a, b) {var data = context.getImageData(0, 0, 800, 600);var imageData = data.data;var tx = 0;var ty = b;var d = b*b + a*a*(-b + 0.25);var mx = a * a / Math.sqrt(a * a + b * b);while(tx <= mx) {if(d < 0) {d += b * b * (2 * tx + 3);} else {ty--;d += b * b * (2 * tx + 3) + 2 * a * a * (1 - ty);}tx++;setPix(x + tx, y + ty);setPix(x + tx, y - ty);setPix(x - tx, y + ty);setPix(x - tx, y - ty);}d = b * b * (tx + 0.5) * (tx + 0.5) + a * a * (ty - 1) * (ty - 1) - a * a * b * b;while (ty > 0) {if (d < 0) {tx++;d += b*b*(2 * tx + 2) + a*a*(-2 * ty + 3);}else {d += a*a*(-2 * ty + 3);}ty--;setPix(x + tx, y + ty);setPix(x - tx, y + ty);setPix(x + tx, y - ty);setPix(x - tx, y - ty);}context.putImageData(data, 0, 0);function setPix(x, y){console.log(x, y);var index = getStartIndex(x, y);for(var i = 0; i< 4; i++) {if(i == 3) {imageData[index + i] = 255;}else{imageData[index + i] = 128;}}}function getStartIndex(x, y) {return y * 800 * 4 + x * 4;}
}

给个结果图~

光栅法的原理在这里就不说啦,那个说的话篇幅很大,在这里也不推荐用光栅法去画椭圆,针对不同线宽很麻烦

ok这篇文章就到这啦,Thanks~

原创文章转载请注明:

转载自AlloyTeam:http://www.alloyteam.com/2015/07/canvas-hua-tuo-yuan-di-fang-fa/

转载于:https://www.cnblogs.com/skylor/p/4755501.html

Canvas画椭圆的方法相关推荐

  1. php椭圆形制图,canvas如何来绘制一个椭圆形?canvas画椭圆的方法总结

    canvas元素在html5中是用于在浏览器中画图的,所以canvas可以实现绘制很多不同的图,那么,今天我们就来看一看canvas如何来绘制一个椭圆形,话不多说,让我们来直接看正文吧. 首先我们来看 ...

  2. Canvas 画椭圆的方法

    转自:AlloyTeam, www.alloyteam.com/2015/07/canvas-hua-tuo-yuan-di-fang-fa/ 虽然标题是画椭圆,但是我们先来说说Canvas中的圆 相 ...

  3. html5 canvas画椭圆形

    在canvas中可以很方便的用arc方法画出圆形,本来圆形也可以看作是一个宽高相等的椭圆,但canvas中根本没有画椭圆的方法,我们要用其他方法来模拟. 我们首先要明确画一个椭圆需要那些参数,基本的几 ...

  4. 如何用python画椭圆_怎么用python画椭圆?

    使用python画椭圆的方法: 首先使用两行代码引入Matplotlib扩展包:import matplotlib.pyplot as plt from matplotlib.patches impo ...

  5. opengl 画椭圆_椭圆围城与圆型观光步道

    触碰标题下面一行中"邵勇老师"查看所有文章:触碰"数学教学研究", 关注本微信公众号(sx100sy).本公众号内容均由邵勇本人独创,欢迎转发,但未经许可不能转 ...

  6. html5画椭圆的完整代码,HTML5 Canvas中绘制椭圆的4种方法

    概述 HTML5中的Canvas并没有直接提供绘制椭圆的方法,下面是对几种绘制方法的总结.各种方法各有优缺,视情况选用.各方法的参数相同: 1.context为Canvas的2D绘图环境对象, 2.x ...

  7. Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形)

    1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, ...

  8. canvas画旋转椭圆

    要求使用画布变换方法. 椭圆画法参照大神佳作:http://web.jobbole.com/82960/ 效果如下: 代码如下: <!DOCTYPE html> <html> ...

  9. [html] 请使用canvas画一个椭圆

    [html] 请使用canvas画一个椭圆 <script> var c=document.getElementById("myCanvas"); var ctx=c. ...

最新文章

  1. 算法题001 剑指Offer 面试题三:二维数组中的查找
  2. idea The origin server did not find a current representation for the target resource or is not willi
  3. The Linux device model
  4. 【资源共享】RockChip_LCD开发文档v1.6
  5. Spring BeanFactory 容器
  6. python为什么没有指针_Python中有指针吗?
  7. Java编程:按照指定的字段顺序,将 Bean 转换为 Json
  8. php设置input时间格式,input[type='date']自定义样式与日历校验功能
  9. java框架面试题及答案,年薪50W
  10. XMind中怎么导入图标?
  11. was mutated while being enumerated.
  12. 怎样黑进Microsoft:循序渐进指南 (转)
  13. 解决hbase报错Master exiting
  14. mac安装postgresql并启动
  15. 白光干涉仪如何获得高度信息丨科普篇
  16. qdbus模块_Qt6各大模块变更概览:旨在成为未来主要开发平台
  17. 印刻出版 盛可以 限量《死亡賦格》
  18. Opencv+Zbar二维码识别(标准条形码/二维码识别)
  19. Twitter实时搜索系统EarlyBird的总结
  20. java实现openoffice在线预览文档

热门文章

  1. 语音、图像和视频数据的格式
  2. 遗留系统:IT攻城狮永远的痛
  3. 第三章:密码学基本理论
  4. 安卓古筝软件_超详细自学软件测评|小提琴/吉他/电子琴/尤克里里/电子鼓
  5. css背景图重复怎们弄,CSS如何实现背景图像重复效果
  6. 腾讯云直播产品系列(一):标准直播POC实践
  7. uPDF:免费功能强大的 PDF 全能工具箱, PDF 文件处理利器
  8. ue4 改变枢轴位置_UE4实时渲染深入探究----学习总结【上篇】
  9. KSQL DB 学习笔记1
  10. linux环境下mysql主从数据库配置(maser-slave-replication)