HTML5的CANVAS上绘制椭圆的几种方法
<div class="lato" id="ty" x="100" y="100" a="100" b="20" onClick="javascript:tty()">椭圆</div> <canvas id="myCanvas" style=" width:200px; height:200px">
第一种方法不是很椭圆。
function tty(){ var cc=document.getElementById('myCanvas'); var context=cc.getContext('2d'); var x=parseInt(document.getElementById("ty").getAttribute('x')); var y=parseInt(document.getElementById("ty").getAttribute('y')); var a=parseInt(document.getElementById("ty").getAttribute('a')); var b=parseInt(document.getElementById("ty").getAttribute('b')); console.log(a+"a"); console.log(b+"b"); var step = (a > b) ? 1 / a : 1 / b; console.log(step) context.beginPath(); context.moveTo(x + a, y); //从椭圆的左端点开始绘制 for (var i = 0; i < 2 * Math.PI; i += step) { //参数方程为x = a * cos(i), y = b * sin(i), //参数为i,表示度数(弧度) context.lineTo(x + a * Math.cos(i), y + b * Math.sin(i)); } context.closePath(); context.stroke(); }
第二种方法
这种方法利用了数学中的均匀压缩原理将圆进行均匀压缩为椭圆,理论上为能够得到标准的椭圆.
function tty(){ var cc=document.getElementById('myCanvas'); var context=cc.getContext('2d'); var x=parseInt(document.getElementById("ty").getAttribute('x')); var y=parseInt(document.getElementById("ty").getAttribute('y')); var a=parseInt(document.getElementById("ty").getAttribute('a')); var b=parseInt(document.getElementById("ty").getAttribute('b')); context.save(); //选择a、b中的较大者作为arc方法的半径参数 var r = (a > b) ? a : b; var ratioX = a / r; //横轴缩放比率 var ratioY = b / r; //纵轴缩放比率 context.scale(ratioX, ratioY); //进行缩放(均匀压缩) context.beginPath(); //从椭圆的左端点开始逆时针绘制 context.moveTo((x + a) / ratioX, y / ratioY); context.arc(x / ratioX, y / ratioY, r, 0, 2 * Math.PI); context.closePath(); context.stroke(); context.restore(); }
第三种方法:三次贝塞尔曲线法
function tty(){ var cc=document.getElementById('myCanvas'); var context=cc.getContext('2d'); var x=parseInt(document.getElementById("ty").getAttribute('x')); var y=parseInt(document.getElementById("ty").getAttribute('y')); var a=parseInt(document.getElementById("ty").getAttribute('a')); var b=parseInt(document.getElementById("ty").getAttribute('b')); //关键是bezierCurveTo中两个控制点的设置 //0.5和0.6是两个关键系数(在本函数中为试验而得) 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.stroke(); context.restore(); }
经过实验,第二,第三种方法比较靠谱。