Recentemente, o autor tem um requisito. O conteúdo do requisito é: um grupo de texto é exibido ao redor do anel. O texto circunda o anel. passa o mouse sobre O pequeno ponto azul acima do anel irá irradiar o triângulo e então exibir o texto. Vamos dar uma olhada no efeito de animação primeiro!
Como mostrado na imagem acima, quando o mouse é colocado no pequeno ponto azul correspondente, um raio semelhante a um triângulo precisa ser emitido, e o texto correspondente é exibido fora do triângulo, e o pequeno ponto azul se torna um pequeno ponto branco.
Quando o usuário insere o conteúdo acima, o conteúdo é adicionado ao redor do anel abaixo. Conforme mostrado na imagem acima.
A ideia original do autor era usar css para implementá-lo, assim como o menu secundário dinâmico da imagem abaixo.
No entanto, considerando que o conteúdo na borda do anel é variável e precisa ser posicionado ao redor do anel, o CSS pode ser difícil de implementar. Então, uau, o autor decidiu usar a tela para conseguir isso. (O autor aprendeu canvas apenas recentemente. Se houver algo errado, aceito suas correções).
Processo de implementação:primeiro:
A parte html do código é a seguinte:
<canvas style=margin-left: 50px;padding-top: 20px; display:block id=canvas > A versão atual do seu navegador não suporta canvas</canvas>;
As etapas específicas de implementação são as seguintes:
1. Desenhe um círculo grande.
Use o método canvas: context.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);
x, y: coordenadas do centro do círculo, radius: raio do centro do círculo, startAngle: desenhando o radiano inicial, endAngle: desenhando o radiano final, [, sentido anti-horário]: parâmetro opcional, se deseja desenhar o arco no sentido horário ou anti-horário.
Para maior comodidade do desenho, o autor moveu a origem da tela do canto superior esquerdo anterior para o centro da tela.
O raio do anel calculado pelo autor é r-80
canvas.width = 500canvas.height = 500 //Calcule o raio do centro da tela, deixe r = 500 / 2//Mova a origem da tela para o centro da tela quando a interface é inicializada ctx.translate(r ,r) //Move o pincel para arredondar
O código específico é o seguinte:
//Inicialização do Canvas let canvas = document.getElementById('canvas')let ctx= canvas.getContext('2d')let ratio = getPixelRato(ctx)canvas.width = 500canvas.height = 500 //Calcule o raio do centro do canvas let r = 500 / 2// Quando a interface é inicializada, mova a origem do canvas para o centro do canvas ctx.translate(r,r) //Move o pincel para o círculo ctx.lineWidth = 3; //Defina a largura da linha do pincel ctx.beginPath(); //Inicie o pincel //Desenhe a cor da borda do gradiente da borda do círculo var arcColor =; ctx.createLinearGradient(-170, -170, 0, 170)arcColor.addColorStop(0, '#8ec1ff')arcColor.addColorStop(0.2, '#83beff')arcColor.addColorStop(0.5, '#75b1ff')arcColor.addColorStop(0.7,'#5998ff')arcColor.addColorStop(1, '#2065ff')ctx .strokeStyle= arcColor;//Define a cor do pincel ctx.arc(0,0,r - 80,0,2*Math.PI,false) //Desenha um círculo, coordenadas 0,0, raio 250-80, círculo completo (0 -360 graus), falso significa sentido horário ctx.closePath()ctx.stroke() //Desenho
Os resultados do desenho são os seguintes
2. Desenhe a imagem de fundo no meio do anel (a origem da tela atual é o centro da tela)
drawImage(imagem, dx, dy, dLargura, dAltura)
imagem: recurso de imagem Canvas, como imagem <img>, imagem SVG, próprio elemento Canvas, etc.
dx, dy: Planeje uma área na tela do Canvas para colocar as imagens. dx são as coordenadas horizontais e verticais do canto superior esquerdo desta área.
dWidth, dHeight: Planeje uma área na tela do Canvas para colocar as imagens, a largura e a altura dessa área.
As seguintes coordenadas são calculadas pelo autor
let image = new Image()image.src = 'image/quan.png'image.onload = () => { // Move a origem para o centro ctx.drawImage(image,-140,-140,280,280)}
Os resultados do sorteio são os seguintes:
3. Desenhe texto e pequenos pontos no anel (a origem da tela atual é o centro da tela)
Desenhando alvos para texto e pequenos pontos:
3.1 Pequenos pontos são exibidos uniformemente no anel grande
3.2 O texto está um pouco espalhado fora dos pequenos pontos
Solução:1. O autor usa um array para armazenar as palavras atuais
deixe textArr = ['Mar amplo e céu','Capacidades técnicas','Fundos fortes','Controle de manutenção','Viva e trabalhe em paz e contentamento','Observe as flores','Termine o toque final',' Livre-se da escória','Vá contra o vento','desenvolvimento de carreira']
2. Como o número de pequenos pontos e o número de palavras são iguais, o número de ambos é o comprimento da matriz textArr acima.
3. O radiano de um círculo completo é 2π Para fazer com que os pequenos pontos dividam igualmente o anel, o autor primeiro calcula o radiano do ponto onde cada pequeno ponto está localizado.
for(let i = 0;i<lengths;i++){ // Calcula radianos let rad = 2*Math.PI/lengths*i}
4. De acordo com funções trigonométricas, as coordenadas (x, y) do pequeno ponto atual na tela podem ser calculadas (a origem da tela atual é o centro da tela)
Entre eles, a relação entre radiano, pequeno ponto, anel, raio do anel e origem da tela, o autor fez um desenho para descrevê-los.
Calcule as coordenadas do texto:
// Calcula as coordenadas do centro do pequeno círculo let x = (r - 40)*Math.cos(rad)let y = (r - 40)*Math.sin(rad)
Calcule as coordenadas do ponto pequeno: Como o centro do ponto pequeno deve cair no anel, as coordenadas horizontais e verticais calculadas são,
// Calcula as coordenadas do texto let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)
O código específico é o seguinte:
// Desenha texto ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ //radianos let rad = 2*Math.PI/lengths*i // Calcula as coordenadas do centro do pequeno círculo let x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// Desenhe pequenos pontos for(let i = 0;i<comprimentos;i++){ // // deixe rad = 2*Math.PI/comprimentos*i deixe x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)// // Desenha pequenos pontos cinza translúcidos na borda ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0,8)' ctx.arc(x,y,8,0,2*Math.PI,falso) ctx.closePath() ctx.fill() // Desenha pequenos pontos azuis ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx.closePath() ctx .preencher() }
Os resultados do sorteio são os seguintes:
4. Desenhe um triângulo fora de cada pequeno ponto (a origem da tela atual é o centro da tela)
4.1 Como você deseja desenhar uma forma de triângulo, a ideia de desenhar um triângulo é desenhar linhas em ambos os lados com o centro do pequeno ponto atual como ponto inicial e, em seguida, usar ctx.fill() para fechar a forma e preencha o interior com cor gradiente.
Desenhe um triângulo: as coordenadas são calculadas por si mesmas. O autor soma e subtrai 35 na abscissa e 70 na ordenada (o que você quiser, hahaha)
//Inicie o pincel ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()
Desenhe o texto abaixo do triângulo: (Para distingui-lo do texto anterior, usei vermelho para o meu texto aqui)
ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)
O código específico é o seguinte:
for(let i = 0;i<lengths;i++){ // // deixe rad = 2*Math.PI/lengths*i deixe x = (r - 80)*Math.cos(rad) deixe y = (r - 80)*Math.sin(rad) // // Desenha um triângulo // // ctx.rotate( -Math.PI / 4) ctx.beginPath() //Inicie o pincel ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath() // // Definir gradiente de cor- - ->Adicione cor do centro para ambos os lados var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0,5)') sColor.addColorStop(0,6,'rgba(83,183,243,0,5)') sColor.addColorStop(0,7,'rgba(129,200,224,0,5)') sColor.addColorStop(0,8,'rgba(130,219,251,0,5)') sColor.addColorStop(1,'rgba(195,228,223,0,5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)}
Os resultados do sorteio são os seguintes:
4.2 O requisito é que a direção de cada triângulo se espalhe para fora, e agora a direção dos triângulos seja para baixo, então agora você precisa usar o método de rotação da tela.
ctx.save() ctx.translate(x,y) // O ângulo de rotação está centrado em cada ponto pequeno ctx.rotate( rad - Math.PI/2 ) // Porque o ponto pequeno ctx.translate(- x, - y) Omita o código para desenhar triângulos e texto.
Pode-se observar pelo cálculo que tomando o centro do pequeno ponto como ponto inicial da rotação, o arco de rotação do triângulo deve ser o arco do pequeno ponto atual menos π/2, pois a posição inicial da rotação sempre começa na direção positiva do eixo da coordenada x, ou seja, começa em 0 radianos, mas agora os triângulos estão todos em π/2 radianos, então:
Radiano de rotação = Radiano do ponto pequeno - π/2
Lembre-se de usar o método de armazenamento de estado do Canvas save() ao girar.
restore() exibe o estado armazenado do Canvas do topo da pilha. Se não houver nenhum estado armazenado do Canvas, não haverá alteração na execução deste método.
Lembre-se de usar o método restore() no final. Nesse ponto, o autor derramou lágrimas de arrependimento. . .
Código específico:
for(let i = 0;i<lengths;i++){ // // deixe rad = 2*Math.PI/lengths*i deixe x = (r - 80)*Math.cos(rad) deixe y = (r - 80)*Math.sin(rad) // Desenha um triângulo s ctx.save() // O ângulo de rotação é centralizado em cada ponto pequeno porque os pontos pequenos estão no início ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // Inicia o pincel ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70) ctx.lineTo(x+35,y+70) ctx.closePath() //Definir gradiente de cor--->Adicionar var de cor do centro para ambos os lados sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0,5)') sColor.addColorStop(0,6,'rgba(83,183,243,0,5)') sColor.addColorStop(0,7,'rgba(129,200,224,0,5)') sColor.addColorStop(0,8,'rgba(130,219,251,0,5)') sColor.addColorStop(1,'rgba(195,228,223,0,5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore()}
Trace o resultado:
Dê uma olhada mais de perto, o quê? ? ? Alguns textos ficam de cabeça para baixo devido a problemas de rotação. Através da observação, o resultado é que quando o radiano é maior que π, o texto fica de cabeça para baixo.
É hora de escrever uma onda de julgamentos. . . .
Como girar o texto:
function rotateContext(ctx, x, y, grau) { // Girar texto ctx.translate(x, y) // ctx.rotate(degree * Math.PI / 180) ctx.rotate(degree) ctx.translate(-x , -y) }
Determine pequenos pontos cujo radiano é maior que π
if (rad > Math.PI) { // Como o texto precisa ser exibido na borda do triângulo, o texto deve girar com o triângulo para que possa sempre ser mantido na // borda do triângulo Após a rotação. , o texto aparecerá quando o radiano for maior que π Inverta o problema, então gire o texto ctx.save() ctx.beginPath() // Gira o texto rotateContext(ctx, x, y+75, Math.PI) ctx.font = '13px Arial' ctx.textAlign = 'centro' ctx.fillStyle = #ff2238 ctx.fillText(textArr[i], x, y+ 75) ctx.restore()} else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i ], x, y + 75)}
Os resultados do sorteio são os seguintes:
Ansiosos pela vitória, estamos quase bem sucedidos. Pelo menos temos um layout aproximado. A revolução ainda não teve sucesso e os camaradas ainda precisam trabalhar duro! !
5. A seguir está a implementação. Quando o mouse está sobre o pequeno ponto, o triângulo na borda e o texto na borda do triângulo são exibidos, mas o texto na borda do círculo não é exibido.
Ideia:1. Vincule o evento de entrada do mouse à tela
2. Determine se as coordenadas da posição atual do mouse na tela são iguais às coordenadas próximas a um pequeno ponto. Em caso afirmativo, exiba o triângulo correspondente ao pequeno ponto.
5.1 Vincule o evento mousemove à tela: o mouse está acima do evento
canvas.addEventListener('mousemove',clickEvent)
5.2 Calcule as coordenadas atuais do mouse na tela
O método de cálculo é: use as coordenadas atuais do mouse no DOM para subtrair a distância da esquerda ou do topo da tela para calcular a distância da tela.
O método drawOne na figura abaixo é o método de desenho, que será discutido posteriormente neste artigo.
function clickEvent() { // As coordenadas da posição do mouse let x = event.clientX - canvas.getBoundingClientRect().left let y = event.clientY - canvas.getBoundingClientRect().top drawOne(x,y)}
5.3, porque as coordenadas do mouse na tela calculadas acima são calculadas com o canto superior esquerdo da tela como origem, mas a origem da tela atual já foi movida para o centro da tela (250.250), então quando usado para determinar se um clique consiste em pequenos pontos Você precisa subtrair 250 das coordenadas horizontais e verticais para comparar com as coordenadas do pequeno ponto na tela atual. Quando estava fazendo o julgamento, encontrei um problema, não sei por que a diferença na direção y. do autor é 260 em vez de 250. Portanto, o autor subtraiu 260 na direção y.
O código é o seguinte:
Entre eles, Cx, Cy são as coordenadas do mouse na tela (o canto superior esquerdo da tela é a origem), x, y são as coordenadas do pequeno ponto atual,
O autor calculou diretamente a posição de 15px próximo ao centro do pequeno ponto, e todos os triângulos foram exibidos, e o pequeno ponto ficou branco.
O mais importante é que você precisa limpar a tela anterior toda vez que redesenhar: lembre-se de usar o método clearRect para limpar a tela
deixe XX = Cx - 250deixe YY = Cy- 260deixe esquerdaX = x - 15 deixe direitaX = x + 15deixe topoY = y - 15deixe fundoY = y + 15if (XX >= esquerdaX && XX <= direitaX && YY <= inferiorY && YY > = topY ) {//É clicado. . . . . . //Escreva o código do desenho no meio}
O código é seguido por um link:
6. Defina uma entrada na interface e vincule o evento change à entrada.
Implementação: A interface é redesenhada toda vez que o valor na entrada muda.
código HTML:
<input type=text id=inpt style=margin-left: 100px;margin-top: 50px placeholder=Por favor, insira...>
código js:
deixe inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) //Este O método é o método de desenho, o código fonte será fornecido posteriormente no artigo}})
7. Há um problema sempre que você clicar na interface e redesenhá-la, haverá uma situação de flash.
Conforme mostrado abaixo:
Cada vez que você desliza, porque as coordenadas do mouse mudam, você precisa limpar o conteúdo ao redor do anel e redesenhá-lo. Então você precisa limpar a tela para obter efeitos dinâmicos.
clearRect() é muito comumente usado no desenho de animação do Canvas. Ele limpa continuamente o conteúdo do canvas e depois o desenha para formar um efeito de animação.
clearRect() pode tornar transparente uma área retangular na tela do elemento Canvas.
context.clearRect(x, y, largura, altura);
x, y: coordenadas x, y do canto superior esquerdo do retângulo.
largura, altura: a largura e a altura da área retangular limpa.
Como clearRect() só pode limpar a área retangular da tela, toda vez que ela for limpa, a imagem de fundo no meio será limpa junto.
Portanto, a imagem de fundo deve ser recarregada todas as vezes e leva um certo tempo para carregar a imagem, por isso ela piscará sempre que aparecer.
Solução:drawImage(imagem, dx, dy, dLargura, dAltura)
O parâmetro imagem: recurso de imagem Canvas, como imagem <img>, imagem SVG, próprio elemento Canvas, etc.
Então você pode usar outra tela para armazenar imagens em cache.
Use uma tela adicional para desenhar a imagem de fundo, mas para aquela tela não exibida na interface: display:none, e então use-a para limpar a tela e renderizar diretamente o objeto de tela em cache no meio da tela a ser exibida, que isto é, não há necessidade de carregar imagens uma vez. É demorado carregar imagens uma vez.
código HTML:
<largura da tela=280 altura=280 estilo=margem-esquerda: 50px;padding-top: 20px; display:none;
código js:
//Use o cache para resolver o problema de flashing de imagens redesenhadas var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; )image.src = 'image/quan.png'image.onload = () => { // A origem se move para o centro tempCtx.drawImage(image,0,0,280,280)}
Depois de limpar a tela, desenhe o canvas:tempCanvas em cache diretamente ao redesenhar a imagem.
// Desenha a tela em cache diretamente na interface (a interface do barramento intermediário é armazenada em cache) ctx.drawImage(tempCanvas,-140,-140)
Ok, consegui, aqui está a imagem do resultado:
O endereço do código-fonte é o seguinte:
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
ResumirO texto acima é a introdução do editor ao uso da tela HTML5 para desenhar animações de anel. Espero que seja útil para você. Se você tiver alguma dúvida, deixe-me uma mensagem e o editor responderá a tempo. Gostaria também de agradecer a todos pelo apoio ao site de artes marciais VeVb!