В холсте вы можете легко нарисовать круг, используя метод дуги. Первоначально круг также можно рассматривать как эллипс с равной шириной и высотой, но нет способа нарисовать эллипс на холсте. Нам нужно использовать другие методы для моделирования.
Прежде всего, нам нужно прояснить параметры, необходимые для рисования эллипса. Основные геометрические знания говорят нам, что эллипсу нужны центральные координаты, ширину, высоту или угол вращения, но его можно избежать в настоящее время, вращение относительно просто.
1. Используйте Lineto, чтобы нарисовать эллипс Вы читаете это правильно, Lineto, метод, который используется чисто для рисования прямых линий, может быть фактически использоваться для рисования эллипсов! ? Но он существует, но стиль письма действительно невероятен:Функция Transelpse (Canvas, O, Oa, Ob) {
// нарисовать эллипс, пример: var b = новый массив (150150); Drawellipse (HB, B, 50,30);
с (Canvas) {
var x = o [0]+oa;
var y = o [1];
Moveto (x, y);
for (var i = 0; i <= 360; i ++) {
var ii = i*math.pi/180;
var x = o [0]+oa*math.cos (ii);
var y = o [1] -ob*math.sin (ii);
Lineto (x, y);
}
}
}
Принцип этого метода состоит в том, что круг имеет 360 градусов, поэтому используйте Lineto для цикла 360 раз, нарисуйте сегменты линии каждой степени и, наконец, подключите их к эллипсу. Среди них тригонометрическая функция необходимо использовать для расчета.
Обратите внимание, что вторым параметром этого метода является массив, то есть центральные координаты эллипса.
Идея очень странная, а нарисованный эллипс относительно гладкий. Но это не стоит использовать - этот метод требует 360 циклов для каждого нарисованного эллипса. Только когда нарисован эллипс, является малейшим испытанием производительности браузера.
Нам просто нужно понять его идеи
2. Используйте дугу, чтобы нарисовать круг и масштабировать его в эллипс Исходный текст этого метода здесь, и основная функция заключается в следующем:var canvas = document.getElementbyId ('myCanvas');
var context = canvas.getContext ('2d');
var centerx = 0;
var centery = 0;
var radius = 50;
// Сохранить состояние
context.save ();
// Перевести контекст
context.translate (canvas.width / 2, canvas.height / 2);
// масштабировать контекст горизонтально
context.scale (2, 1);
// нарисовать круг, который будет растянут в овальный
context.beginpath ();
Context.arc (CenterX, Centery, Radius, 0, 2 * Math.pi, false);
// восстановиться в исходном состоянии
context.restore ()
Этот метод использует функцию холста, о которой я не упоминал ранее, то есть масштаб, которая может реализовать масштабирование холста. Масштабирование имеет два направления: горизонтальный и вертикальный. Код увеличивает горизонтальное направление холста, в то время как вертикальное направление остается неизменным. Таким образом, круг, нарисованный дугой, превращается в эллипс.
Этот метод очень замечательный на первый взгляд, с небольшим количеством кодов, а принципы просты и легко понять. Но после того, как вы его анализируете, вы найдете его очевидные недостатки, то есть это неточно! Например, мне нужен эллипс, который имеет ширину 171 и 56. Если мы установим радиус дуги на 28, то последующее число 171/28/2 будет подавлено.
Тем не менее, существует компромисный метод, который всегда устанавливает радиус дуги на 100, а затем, если этого недостаточно, он будет увеличен, и если он превысит его, он будет уменьшен. Тем не менее, это все еще неточно.
3. Используйте Curveto Bezier Поскольку я чувствовал, что приведенный выше метод масштабирования является неточным, я действительно хочу найти точный метод для рисования эллипсов и, наконец, нашел его на Stackoverflow:Функция Drallyplipse (CTX, X, Y, W, H) {
var kappa = 0,5522848;
ox = (w / 2) * kappa, // Смещение контрольной точки горизонтальное
oy = (h / 2) * kappa, // Смещение контрольной точки вертикально
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // x-middle
ym = y + h / 2; // y-middle
ctx.beginpath ();
ctx.moveto (x, ym);
ctx.beziercurveto (x, ym - oy, xm - ox, y, xm, y);
ctx.beziercurveto (xm + ox, y, xe, ym - oy, xe, ym);
ctx.beziercurveto (xe, ym + oy, xm + ox, ye, xm, ye);
ctx.beziercurveto (xm - ox, ye, x, ym + oy, x, ym);
ctx.closepath ();
ctx.stroke ();
}
Этот метод можно считать идеальным. Он разделил эллипс на 4 изгиба Безера и соединил их с эллипсом. Последняя ширина и высота также относительно точны, а накладные расходы меньше.
Но этот метод все еще имеет свои недостатки. Все смотрят на параметр каппа, и есть очень странное значение. Я считаю, что многие люди не понимают, почему они должны взять эту ценность, прежде чем эксперт по геометрии сообщит вам, почему они хотят взять эту ценность - я все еще не знаю ее. И у меня было сильное желание изменить его и посмотреть, каковы были последствия.
Конечно, нельзя сказать, что мой импульс, похожий на обсессивно-компульсивного расстройства, является недостатком этого метода. Его настоящий недостаток - зачем вам использовать 4 кривых Безера? Я лично думаю, что эллипс, очевидно, состоит из двух кривых Безера, а не четырех. Эта идея в конечном итоге заставила меня найти самый идеальный способ нарисовать эллипс.
4. Используйте две кривые Besel, чтобы нарисовать эллипс
Чтобы понять, может ли предыдущий метод быть упорядоченным, я специально зарегистрировал учетную запись StackOverflow, чтобы задать вопросы. Поскольку в вопросе есть фотографии, точки не могут быть переданы. Мне пришлось использовать свой едва ли знания английского, чтобы ответить на вопросы иностранцев, чтобы заработать очки. Но, в конце концов, пришла удача, и ответил на вопрос, решил мою проблему.
Я поднял проблему взаимосвязи между кривой Бесэля и Эллипсом.
Честно говоря, я не понимал большинство ответов иностранцев ниже, но, к счастью, он предоставил образец кода, что заставило меня понять принцип, и я хотел бы снова поблагодарить его. Согласно его ответу, метод, который я нашел для рисования эллипсов, заключается в следующем:
// овальный
CanvasRenderingContext2d.prototype.oval = function (x, y, width, height) {
var k = (ширина/0,75)/2,
W = ширина/2,
h = высота/2;
this.beginpath ();
this.moveto (x, yh);
this.beziercurveto (x+k, yh, x+k, y+h, x, y+h);
this.beziercurveto (xk, y+h, xk, yh, x, yh);
this.closepath ();
вернуть это;
}
Этот метод является точным и имеет мало кода, и нет странного и трудности для понимания. Просто помните об этом, координатное соотношение ширины эллипса к контрольной точке кривой BESEL, которая рисует эллипс, выглядит следующим образом:
Контрольная точка Бесселя x = (ширина эллипса/0,75)/2 уже отражена в коде.
Вы можете проверить вышеупомянутые четыре метода, чтобы нарисовать эллипс.
Если вы найдете более простой способ, пожалуйста, поделитесь им и обсудите.