Как нарисовать овал в холсте html5? - PullRequest
73 голосов
/ 31 января 2010

Кажется, не существует встроенной функции для рисования овальной формы. Также я не ищу форму яйца.

Можно ли нарисовать овал с двумя кривыми Безье? Кто-нибудь испытал это?

Моя цель - нарисовать глаза, и я просто использую дуги. Заранее спасибо.

Решение

Таким образом, scale () изменяет масштабирование для всех следующих фигур. Save () сохраняет настройки до, а восстановление используется для восстановления настроек для рисования новых фигур без масштабирования.

Благодаря Яни

ctx.save();
ctx.scale(0.75, 1);
ctx.beginPath();
ctx.arc(20, 21, 10, 0, Math.PI*2, false);
ctx.stroke();
ctx.closePath();
ctx.restore();

Ответы [ 16 ]

2 голосов
/ 28 марта 2011

Да, это возможно с двумя кривыми Безье - вот краткий учебник / пример: http://www.williammalone.com/briefs/how-to-draw-ellipse-html5-canvas/

1 голос
/ 04 августа 2013

При этом вы можете даже нарисовать отрезки эллипса:

function ellipse(color, lineWidth, x, y, stretchX, stretchY, startAngle, endAngle) {
    for (var angle = startAngle; angle < endAngle; angle += Math.PI / 180) {
        ctx.beginPath()
        ctx.moveTo(x, y)
        ctx.lineTo(x + Math.cos(angle) * stretchX, y + Math.sin(angle) * stretchY)
        ctx.lineWidth = lineWidth
        ctx.strokeStyle = color
        ctx.stroke()
        ctx.closePath()
    }
}

http://jsfiddle.net/FazAe/1/

1 голос
/ 26 мая 2013

Это еще один способ создания формы, подобной эллипсу, хотя он использует функцию "fillRect ()", которую можно использовать для изменения аргументов в функции fillRect ().

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Sine and cosine functions</title>
</head>
<body>
<canvas id="trigCan" width="400" height="400"></canvas>

<script type="text/javascript">
var canvas = document.getElementById("trigCan"), ctx = canvas.getContext('2d');
for (var i = 0; i < 360; i++) {
    var x = Math.sin(i), y = Math.cos(i);
    ctx.stroke();
    ctx.fillRect(50 * 2 * x * 2 / 5 + 200, 40 * 2 * y / 4 + 200, 10, 10, true);
}
</script>
</body>
</html>
1 голос
/ 01 марта 2013

Поскольку никто не придумал подход, использующий более простое quadraticCurveTo, я добавляю решение для этого. Просто замените bezierCurveTo звонки в ответе @ Steve's на:

  ctx.quadraticCurveTo(x,y,xm,y);
  ctx.quadraticCurveTo(xe,y,xe,ym);
  ctx.quadraticCurveTo(xe,ye,xm,ye);
  ctx.quadraticCurveTo(x,ye,x,ym);

Вы также можете удалить closePath. Хотя овал выглядит немного иначе.

0 голосов
/ 13 сентября 2016

Если вы хотите, чтобы эллипс полностью поместился внутри прямоугольника, это действительно так:

function ellipse(canvasContext, x, y, width, height){
  var z = canvasContext, X = Math.round(x), Y = Math.round(y), wd = Math.round(width), ht = Math.round(height), h6 = Math.round(ht/6);
  var y2 = Math.round(Y+ht/2), xw = X+wd, ym = Y-h6, yp = Y+ht+h6, cs = cards, c = this.card;
  z.beginPath(); z.moveTo(X, y2); z.bezierCurveTo(X, ym, xw, ym, xw, y2); z.bezierCurveTo(xw, yp, X, yp, X, y2); z.fill(); z.stroke();
  return z;
}

Убедитесь, что ваш canvasContext.fillStyle = 'rgba(0,0,0,0)'; не заполнен этим дизайном.

0 голосов
/ 15 марта 2013

Вот функция, которую я написал, которая использует те же значения, что и дуга эллипса в SVG. X1 и Y1 - последние координаты, X2 и Y2 - конечные координаты, радиус - числовое значение, а по часовой стрелке - логическое значение. Также предполагается, что ваш контекст холста уже определен.

function ellipse(x1, y1, x2, y2, radius, clockwise) {

var cBx = (x1 + x2) / 2;    //get point between xy1 and xy2
var cBy = (y1 + y2) / 2;
var aB = Math.atan2(y1 - y2, x1 - x2);  //get angle to bulge point in radians
if (clockwise) { aB += (90 * (Math.PI / 180)); }
else { aB -= (90 * (Math.PI / 180)); }
var op_side = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)) / 2;
var adj_side = Math.sqrt(Math.pow(radius, 2) - Math.pow(op_side, 2));

if (isNaN(adj_side)) {
    adj_side = Math.sqrt(Math.pow(op_side, 2) - Math.pow(radius, 2));
}

var Cx = cBx + (adj_side * Math.cos(aB));            
var Cy = cBy + (adj_side * Math.sin(aB));
var startA = Math.atan2(y1 - Cy, x1 - Cx);       //get start/end angles in radians
var endA = Math.atan2(y2 - Cy, x2 - Cx);
var mid = (startA + endA) / 2;
var Mx = Cx + (radius * Math.cos(mid));
var My = Cy + (radius * Math.sin(mid));
context.arc(Cx, Cy, radius, startA, endA, clockwise);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...