A tela no HTML5 não fornece diretamente um método para desenhar elipses. A seguir, é apresentado um resumo de vários métodos de desenho. Vários métodos têm suas próprias vantagens e desvantagens e são selecionadas de acordo com a situação. Os parâmetros de cada método são os mesmos:
O contexto é o objeto de ambiente de desenho 2D da tela,
X é a coordenada horizontal do centro da elipse.
y é a coordenada vertical do centro da elipse.
A é o comprimento do meio eixo horizontal da elipse.
B é o comprimento do meio eixo vertical da elipse.
Método da equação do parâmetroEste método usa as equações paramétricas da elipse para desenhar uma elipse
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Os parâmetros x e y da função são o centro da elipse; A e B são o meio eixo horizontal da elipse, respectivamente
// A duração do meio-eixo vertical não pode ser 0 ao mesmo tempo
// A desvantagem desse método é que, quando a largura de lin é mais larga e a elipse é lisonjeira
// A extremidade principal do eixo da elipse interna é nítida, não suave e tem baixa eficiência
função paramellipse (contexto, x, y, a, b)
{
// max é o maior dos principais valores do eixo a e b
// Aumente 1/máximo para cada ciclo, indicando o aumento do grau
// Isso fará com que o caminho (arco) desenhe em cada loop próximo a 1 pixel
var step = (a> b)? 1 / a: 1 / b;
context.BeginPath ();
context.moveto (x + a, y); // extrair do ponto final esquerdo da elipse
for (var i = 0; i <2 * math.pi; i += step)
{
// a equação do parâmetro é x = a * cos (i), y = b * sin (i),
// O parâmetro é I, indicando o grau (Radian)
context.lineto (x + a * math.cos (i), y + b * math.sin (i));
}
context.ClosePath ();
context.stroke ();
};
Método de compressão uniformeEste método usa o princípio da compressão uniforme na matemática para comprimir uniformemente o círculo em uma elipse, que teoricamente pode obter uma elipse padrão. O código a seguir terá problemas com larguras de linha inconsistentes. A solução é ver os comentários de Simonleung no 5º andar.
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// O método é desenhar o círculo usando o método ARC e combinar escala para
// Escalando na direção horizontal ou vertical do eixo (até compressão)
// A borda da elipse desenhada neste método se torna mais espessa à medida que a borda está mais próxima do final do eixo principal, e a largura da linha do final do eixo principal é normal
// Quanto mais próxima a borda é do eixo menor, mais mais plano e mais fino da elipse, e até a interrupção é causada. Este é o resultado da escala.
// Essa desvantagem às vezes é uma vantagem, como ao expressar o efeito tridimensional do anel (halo planetário)
// Para o caso em que os parâmetros A ou B são 0, este método não é aplicável
função evencomsellipse (contexto, x, y, a, b)
{
context.Save ();
// Selecione o maior de A e B como o parâmetro raio do método do arco
var r = (a> b)? A: B;
VAR Ratiox = A / R; // Taxa de escala do eixo horizontal
var ratioy = b / r; // Taxa de escala de eixo dimensional
Context.Scale (Ratiox, Ratioy); // escala (até compressão)
context.BeginPath ();
// Desenhe no sentido anti -horário da extremidade esquerda da elipse
context.moveto ((x + a) / ratiox, y / ratioy);
context.arc (x / ratiox, y / ratioy, r, 0, 2 * math.pi);
context.ClosePath ();
context.stroke ();
context.restore ();
};
Método cúbico de curva bezier umO desenho da curva de Bezier cúbico de uma elipse é uma aproximação ao realmente desenhar e, em teoria, também é uma aproximação. No entanto, devido à sua alta eficiência, é frequentemente usado para desenhar elipses nos gráficos vetoriais de computadores, mas não estou muito claro sobre a teoria específica. A aproximação está na seleção das posições dos dois pontos de controle. A posição do ponto de controle desse método foi obtida por mim e a precisão é boa.
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Este método também produzirá quando a largura de linha for mais larga e a elipse é mais plana.
// A extremidade do eixo longa é nítida e não suave
função bezierellipse1 (contexto, x, y, a, b)
{
// A chave é a configuração de dois pontos de controle em BezierCurveto
//0.5 e 0,6 são dois coeficientes principais (obtidos para experimentação nesta função)
var ox = 0,5 * a,
oy = 0,6 * b;
context.Save ();
context.Translate (x, y);
context.BeginPath ();
// desenha no sentido anti -horário da extremidade inferior do eixo longitudinal elipse
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 ();
};
Método cúbico de curva bezier doisEste método é alterado da resposta para uma postagem no Stackoverflow, com alta precisão e também é um método comumente usado para desenhar elipses.
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Este método também produzirá quando a largura de linha for mais larga e a elipse é lisonjeira
//, a extremidade longa do eixo é nítida e não suave
// Este método é mais preciso que o método Bessel anterior, mas tem um método um pouco menos eficiente
função bezierellipse2 (ctx, x, y, a, b)
{
var k = 0,5522848,
Ox = A * K, // Offset de ponto de controle horizontal
oy = b * k; // Offset de ponto de controle vertical
ctx.BeginPath ();
// Desenhe quatro curvas de bezier cúbicas no sentido horário a partir do ponto final esquerdo da elipse
ctx.moveto (x - a, y);
ctx.beziercurveto (x - a, y - oy, x - ox, y - b, x, y - b);
ctx.bezierCurveto (x + ox, y - b, x + a, y - oy, x + a, y);
ctx.beziercurveto (x + a, y + oy, x + ox, y + b, x, y + b);
ctx.beziercurveto (x - ox, y + b, x - a, y + oy, x - a, y);
ctx.closePath ();
ctx.stroke ();
};
Método de gradeEsse método pode desenhar elipses com base nas características da tela capaz de operar pixels e usar algoritmos básicos em gráficos. Por exemplo, o algoritmo Ellipse de desenho médio, etc.
Um exemplo é uma postagem no blog de Doudou, um amigo do jardim, a classe de melhoria de tela HTML5 (i) - gráficos raster (1) algoritmo médio e círculo. Esse método é relativamente primitivo, flexível, eficiente e preciso, mas é mais complicado realizar uma função útil para desenhar elipses. Por exemplo, quando a largura da linha muda, o algoritmo se torna mais complicado. Embora seja um algoritmo para desenhar círculos, o algoritmo para desenhar elipses é semelhante a ele, para que você possa se referir a ele abaixo.
Demonstração
A seguir, são apresentadas várias demonstrações de desenhar funções de elipse, além do método raster. O código de demonstração é o seguinte:
<div id = "canvasWrap" style = "Background: #ffff; largura: 600px; altura: 600px; borda: 1px Solid Black;"> </div>
<script type = "text/javascript"> // <! [CDATA [
Var Canvas,
contexto;
var div = document.getElementById ("CanvasWrap");
div.innerhtml = "";
Canvas = document.createElement ("Canvas");
Canvas.style.width = "600px"
canvas.style.Height = "600px"
canvas.width = 600;
canvas.Height = 600;
context = canvas.getContext ("2d");
Div.AppendChild (Canvas);
função execraw ()
{
// Resolva o problema da largura da linha menor ou igual a 1 no cromo
context.LineWidth = 1.1;
Context.strokestyle = "Black"
Paramellipse (contexto, 130, 80, 50, 50); //Círculo
Paramellipse (Contexto, 130, 80, 100, 20); // Ellipes
Evencomsellipse (Contexto, 130, 200, 50, 50); //Círculo
Evencomsellipse (Contexto, 130, 200, 100, 20); // Ellipe
Bezierellipse1 (contexto, 470, 80, 50, 50); //Círculo
Bezierellipse1 (contexto, 470, 80, 100, 20); // Ellipe
Bezierellipse2 (contexto, 470, 200, 50, 50); //Círculo
Bezierellipse2 (contexto, 470, 200, 100, 20); // Ellipe
// Detecção de similaridade (grau de sobreposição)
Paramellipse (contexto, 300, 450, 250, 50);
context.strokestyle = "amarelo";
Bezierellipse1 (contexto, 300, 450, 250, 50);
context.strokestyle = "azul";
Bezierellipse2 (contexto, 300, 450, 250, 50);
};
função clearcavnas ()
{
context.clearrect (0, 0, 600, 600);
};
//]]> </script>
<p>
<button onclick = "ExecDraw ();" type = "Button"> Execute </botão>
<button onclick = "clearcanvas ();" type = "Button"> limpo </botão>
</p>
Observe que, para executar o código com sucesso, é necessário um navegador que suporta uma tela habilitada para HTML5.
Foi a primeira vez que escrevi um blog e não foi fácil fazer isso o dia todo! O modelo de pele escura no parque do blog não mostra bem o código inserido. Eu tomei grandes dores para obter o formato de código!