En el lienzo, puede dibujar fácilmente un círculo usando el método ARC. Originalmente, el círculo también puede considerarse como una elipse con igual ancho y altura, pero no hay forma de dibujar una elipse en el lienzo. Necesitamos usar otros métodos para simularlo.
En primer lugar, necesitamos aclarar los parámetros necesarios para dibujar una elipse. El conocimiento geométrico básico nos dice que la elipse necesita las coordenadas del centro, el ancho, la altura o el ángulo de rotación, pero esto se puede evitar por el momento, la rotación es relativamente fácil.
1. Use Lineto para dibujar una elipse ¡Lees eso correcto, Lineto, un método que se usa puramente para dibujar líneas rectas, en realidad se puede usar para dibujar elipses! ? Pero él existe, pero el estilo de escritura es realmente increíble:función Drawellipse (Canvas, O, OA, OB) {
// dibujar una elipse, ejemplo: var b = nueva matriz (150,150); Drawellipse (Hb, B, 50,30);
con (lienzo) {
var x = o [0]+oa;
var y = o [1];
Moveto (x, y);
para (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);
}
}
}
El principio de este método es que un círculo tiene 360 grados, así que use Lineto para hacer bucle 360 veces, dibuje los segmentos de línea de cada grado y finalmente conéctelos en una elipse. Entre ellos, la función trigonométrica SINE Cosine debe usarse para el cálculo.
Tenga en cuenta que el segundo parámetro de este método es una matriz, es decir, las coordenadas del centro de la elipse.
La idea es muy extraña, y la elipse dibujada es relativamente suave. Pero no vale la pena usarlo: este método requiere 360 ciclos por cada elipse dibujada. Solo cuando se dibuja la elipse es una más mínima prueba del rendimiento del navegador.
Solo necesitamos entender sus ideas
2. Use arco para dibujar un círculo y escalarlo en una elipse El texto original de este método está aquí, y la función central es la siguiente:var lienvas = document.getElementById ('mycanvas');
var context = Canvas.getContext ('2d');
var CenterX = 0;
var centery = 0;
Radio var = 50;
// Guardar estado
context.save ();
// Traducir el contexto
context.translate (Canvas.Width / 2, Canvas.Height / 2);
// Escala del contexto horizontalmente
context.scale (2, 1);
// dibujar círculo que se estirará en un ovalado
context.beginPath ();
context.arc (CenterX, Centery, Radius, 0, 2 * Math.pi, falso);
// restaurar al estado original
context.restore ()
Este método utiliza una función de lienzo que no he mencionado antes, es decir, escala, que puede realizar la escala del lienzo. La escala tiene dos direcciones: horizontal y vertical. El código amplía la dirección horizontal del lienzo, mientras que la dirección vertical permanece sin cambios. Entonces, el círculo dibujado por arco se convierte en una elipse.
Este método es muy maravilloso a primera vista, con pocos códigos, y los principios son simples y fáciles de entender. Pero después de analizarlo, encontrará sus deficiencias obvias, es decir, es inexacta! Por ejemplo, necesito una elipse de 171 de ancho y 56 de alto. Si establecemos el radio de arco en 28, entonces el número posterior de 171/28/2 estará deprimido.
Sin embargo, existe un método de compromiso para establecer siempre el radio de arco en 100, y luego, si no es suficiente, se ampliará, y si lo excede, se reducirá. Sin embargo, todavía es inexacto.
3. Use Bezier Curveto Como sentí que el método de escala anterior es inexacto, realmente quiero encontrar un método exacto para dibujar elipses y finalmente lo encontré en StackOverflow:función Drawellipse (CTX, X, Y, W, H) {
var kappa = 0.5522848;
ox = (w / 2) * Kappa, // Punto de control Offset horizontal
oy = (h / 2) * kappa, // Punto de control Offset vertical
xe = x + w, // x-end
ye = y + h, // y-end
xm = x + w / 2, // X-Middle
ym = y + h / 2; // y medio
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 ();
}
Este método puede considerarse perfecto. Dividió una elipse en 4 curvas Bezier y las conectó a una elipse. El ancho y la altura finales también son relativamente precisos y la sobrecarga es menor.
Pero este método todavía tiene sus inconvenientes. Todos miran el parámetro Kappa, y hay un valor muy extraño. Creo que muchas personas no entienden por qué tienen que tomar este valor antes de que el experto en geometría le diga por qué quieren tomar este valor, todavía no lo sé. Y tenía un fuerte impulso de cambiarlo y ver cuáles eran las consecuencias.
Por supuesto, no se puede decir que mi impulso similar al desorden obsesivo compulsivo sea la desventaja de este método. Su verdadera desventaja es: ¿por qué necesitas usar 4 curvas Bezier? Personalmente, creo que una elipse obviamente está compuesta por dos curvas Bezier en lugar de cuatro. Esta idea finalmente me llevó a encontrar la manera más perfecta de dibujar una elipse.
4. Use dos curvas Besel para dibujar una elipse
Para comprender si el método anterior se puede simplificar, registré especialmente una cuenta de StackOverflow para hacer preguntas. Como hay imágenes en la pregunta, los puntos no pueden transmitirse. Tuve que usar mi dominio del inglés apenas para responder las preguntas de los extranjeros para ganar puntos. Pero al final, llegó la buena suerte, y responder una pregunta resolvió mi problema de puntos.
He planteado el problema de la relación entre Besel Curve y Ellipse.
Para ser honesto, no entendí la mayoría de las respuestas de los extranjeros a continuación, pero afortunadamente proporcionó una página de muestra de código, lo que me hizo entender el principio, y me gustaría agradecerle nuevamente. Según su respuesta, el método que encontré para dibujar elipses es el siguiente:
//oval
CanvasrenderingContext2d.prototype.oval = function (x, y, ancho, altura) {
var k = (ancho/0.75)/2,
w = ancho/2,
h = altura/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 ();
devolver esto;
}
Este método es preciso y tiene poco código, y no hay extraño y difícil de entender. Solo recuerde esto, la relación coordenada del ancho de la elipse hasta el punto de control de la curva Besel que dibuja la elipse es la siguiente:
El punto de control de Bessel x = (ancho de elipse/0.75)/2 ya se refleja en el código.
Puede probar los cuatro métodos anteriores para dibujar una elipse.
Si encuentra una manera más fácil, compártelo y discúblalo.