In Canvas können Sie einen Kreis mit der ARC -Methode problemlos zeichnen. Ursprünglich kann der Kreis auch als Ellipse mit gleicher Breite und Höhe angesehen werden, aber es gibt keine Möglichkeit, eine Ellipse in Leinwand zu zeichnen. Wir müssen andere Methoden verwenden, um es zu simulieren.
Zunächst müssen wir die Parameter klären, die zum Zeichnen einer Ellipse erforderlich sind. Grundlegende geometrische Kenntnisse zeigen, dass die Ellipse die Zentralkoordinaten, die Breite, die Höhe oder den Drehwinkel benötigt. Dies kann vorerst vermieden werden, die Rotation ist relativ einfach.
1. Zeichnen Sie Lineto, um eine Ellipse zu zeichnen Sie lesen, dass ein Lineto, eine Methode, die rein zum Zeichnen von geraden Linien verwendet wird, tatsächlich zum Zeichnen von Ellipsen verwendet werden kann! ? Aber er existiert, aber der Schreibstil ist wirklich unglaublich:Funktion Drawellipse (Leinwand, O, OA, OB) {
// eine Ellipse zeichnen, Beispiel: var b = Neuarray (150,150); Drawellipse (HB, B, 50,30);
mit (canvas) {
var x = o [0]+oa;
var y = o [1];
MoveTo (x, y);
für (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);
}
}
}
Das Prinzip dieser Methode ist, dass ein Kreis 360 Grad hat. Verwenden Sie also Lineto, um 360 -mal zu schleifen, die Liniensegmente jedes Grades zu zeichnen und sie schließlich zu einer Ellipse zu verbinden. Unter ihnen muss die trigonometrische Sinus -Kosinus zur Berechnung verwendet werden.
Beachten Sie, dass der zweite Parameter dieser Methode ein Array ist, dh die Zentralkoordinaten der Ellipse.
Die Idee ist sehr seltsam und die gezogene Ellipse ist relativ glatt. Es lohnt sich jedoch nicht zu verwenden - diese Methode erfordert 360 Zyklen für jede gezogene Ellipse. Nur wenn die Ellipse gezogen wird, ist eine geringste Prüfung der Leistung des Browsers.
Wir müssen nur seine Ideen verstehen
2. Verwenden Sie ARC, um einen Kreis zu zeichnen und ihn in eine Ellipse zu skalieren Der ursprüngliche Text dieser Methode ist hier, und die Kernfunktion lautet wie folgt:var canvas = document.getElementById ('mycanvas');
var context = canvas.getContext ('2d');
var centerx = 0;
var centery = 0;
var radius = 50;
// Status retten
context.save ();
// Kontext übersetzen
context.translate (canvas.width / 2, canvas.height / 2);
// Kontext horizontal skalieren
Context.Scale (2, 1);
// Kreis ziehen, der in ein Oval ausgestreckt wird
context.beginPath ();
context.arc (CenterX, Centery, Radius, 0, 2 * Math.pi, False);
// in den ursprünglichen Zustand wiederherstellen
context.restore ()
Diese Methode verwendet eine Canvas -Funktion, die ich zuvor nicht erwähnt habe, dh Skala, die die Skalierung von Leinwand realisieren kann. Skalierung hat zwei Richtungen: horizontal und vertikal. Der Code vergrößert die horizontale Richtung der Leinwand, während die vertikale Richtung unverändert bleibt. Der von Bogen gezogene Kreis verwandelt sich also in eine Ellipse.
Diese Methode ist auf den ersten Blick sehr wunderbar, mit wenigen Codes, und die Prinzipien sind einfach und leicht zu verstehen. Aber nachdem Sie es analysiert haben, werden Sie seine offensichtlichen Mängel finden, dh es ist ungenau! Zum Beispiel brauche ich eine Ellipse, die 171 breit und 56 hoch ist. Wenn wir den Radius von ARC auf 28 festlegen, wird die nachfolgende Anzahl von 171/28/2 depressiv.
Es gibt jedoch eine Kompromissmethode, die immer den Radius von Bogen auf 100 festlegen kann, und wenn es nicht ausreicht, wird er vergrößert, und wenn sie es überschreitet, wird es reduziert. Es ist jedoch noch ungenau.
3. Verwenden Sie Bezier Curveto Da ich das Gefühl hatte, dass die obige Skalierungsmethode ungenau ist, möchte ich wirklich eine genaue Methode finden, um Ellipsen zu zeichnen, und fand sie schließlich auf Stackoverflow:Funktion DRAGELLIPSE (CTX, X, Y, W, H) {
var kappa = 0,5522848;
OX = (w / 2) * Kappa, // Kontrollpunkt -Offset Horizontal
oy = (h / 2) * kappa, // Steuerpunktversetzt vertikal
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 ();
}
Diese Methode kann als perfekt angesehen werden. Er teilte eine Ellipse in 4 Bezier -Kurven und verband sie mit einer Ellipse. Die endgültige Breite und Höhe sind ebenfalls relativ genau und der Overhead ist geringer.
Diese Methode hat jedoch immer noch ihre Nachteile. Jeder schaut auf den Kappa -Parameter, und es gibt einen sehr seltsamen Wert. Ich glaube, dass viele Menschen nicht verstehen, warum sie diesen Wert nehmen müssen, bevor der Geometriexperte Ihnen sagt, warum sie diesen Wert nehmen wollen - ich weiß es immer noch nicht. Und ich hatte einen starken Drang, ihn zu verändern und zu sehen, was die Folgen waren.
Natürlich kann mein Impuls, ähnlich wie Patienten mit Zwangsstörungen, nicht als Nachteil dieser Methode bezeichnet werden. Sein wahrer Nachteil ist - warum müssen Sie 4 Bezier -Kurven verwenden? Ich persönlich denke, dass eine Ellipse offensichtlich eher aus zwei Bezier -Kurven als aus vier besteht. Diese Idee hat mich schließlich dazu veranlasst, die perfekte Möglichkeit zu finden, eine Ellipse zu zeichnen.
4. Verwenden Sie zwei Besel -Kurven, um eine Ellipse zu zeichnen
Um zu verstehen, ob die vorherige Methode optimiert werden kann, habe ich speziell ein Stackoverflow -Konto registriert, um Fragen zu stellen. Da die Frage Bilder enthält, können die Punkte nicht übertragen werden. Ich musste meine kaum Englischkenntnisse nutzen, um die Fragen der Ausländer zu beantworten, um Punkte zu sammeln. Aber am Ende kam viel Glück und die Beantwortung einer Frage löste mein Punktproblem.
Ich habe das Problem der Beziehung zwischen der BES -Kurve und Ellipse angehoben.
Um ehrlich zu sein, habe ich die meisten Antworten der Ausländer unten nicht verstanden, aber zum Glück hat er eine Code -Beispielseite bereitgestellt, die mich das Prinzip verstanden hat, und ich möchte ihm erneut danken. Nach seiner Antwort lautet die Methode, die ich zum Zeichnen von Ellipsen gefunden habe, wie folgt:
//Oval
CanvasrenderingContext2d.prototype.ovoval = Funktion (x, y, breite, Höhe) {
var k = (Breite/0,75)/2,
W = Breite/2,,
H = Höhe/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 ();
gib dies zurück;
}
Diese Methode ist sowohl genau als auch nur wenig Code, und es gibt kein seltsames und schwer zu verstehenes. Denken Sie daran, das Koordinatenverhältnis der Breite der Ellipse zum Kontrollpunkt der BESEL -Kurve, die die Ellipse zeichnet, lautet wie folgt:
Der Bessel -Steuerpunkt X = (Ellipse Breite/0,75)/2 spiegelt sich bereits im Code wider.
Sie können die oben genannten vier Methoden zum Zeichnen einer Ellipse testen.
Wenn Sie einen einfacheren Weg finden, teilen Sie es bitte mit und besprechen Sie es.