Recientemente, el autor tiene un requisito. El contenido del requisito es: se muestra un grupo de texto alrededor del anillo. El texto rodea el anillo. Cada palabra corresponde a un pequeño punto azul alrededor del anillo. Pasa el mouse sobre El pequeño punto azul sobre el anillo irradiará el triángulo y luego mostrará el texto. ¡Primero echemos un vistazo al efecto de animación!
Como se muestra en la imagen de arriba, cuando se coloca el mouse sobre el pequeño punto azul correspondiente, se debe emitir un rayo en forma de triángulo, el texto correspondiente se muestra fuera del triángulo y el pequeño punto azul se convierte en un pequeño punto blanco.
Cuando el usuario ingresa el contenido de arriba, el contenido se agrega alrededor del anillo de abajo. Como se muestra en la imagen de arriba.
La idea original del autor era usar CSS para implementarlo, al igual que el menú secundario dinámico en la imagen a continuación.
Sin embargo, considerando que el contenido en el borde del anillo es variable y debe colocarse alrededor del anillo, CSS puede resultar difícil de implementar. Vaya, el autor decidió utilizar lienzo para lograrlo. (El autor se ha enterado recientemente del lienzo. Si hay algún problema, acepto sus correcciones).
Proceso de implementación:primero:
La parte html del código es la siguiente:
<canvas style=margin-left: 50px;padding-top: 20px; display:block; id=canvas > La versión actual de su navegador no admite lienzo</canvas>
Los pasos de implementación específicos son los siguientes:
1. Dibuja un círculo grande.
Utilice el método del lienzo: context.arc(x, y, radio, startAngle, endAngle [, antihorario]);
x, y: coordenadas del centro del círculo, radio: radio del centro del círculo, startAngle: dibujar el radian inicial, endAngle: dibujar el radian final, [, antihorario]: parámetro opcional, si se dibuja el arco en el sentido de las agujas del reloj o en el sentido contrario a las agujas del reloj.
Para facilitar el dibujo, el autor movió el origen del lienzo desde la esquina superior izquierda anterior al centro del lienzo.
El radio del anillo calculado por el autor es r-80.
canvas.width = 500canvas.height = 500//Calcular el radio del centro del lienzo let r = 500/2//Mover el origen del lienzo al centro del lienzo cuando se inicializa la interfaz ctx.translate(r ,r) //Mueve el pincel para redondear
El código específico es el siguiente:
//Inicialización del lienzo let canvas = document.getElementById('canvas')let ctx= canvas.getContext('2d')let ratio = getPixelRato(ctx)canvas.width = 500canvas.height = 500//Calcular el radio del centro del lienzo let r = 500 / 2// Cuando se inicializa la interfaz, mueve el origen del lienzo al centro del lienzo ctx.translate(r,r) //Mueve el pincel al círculo ctx.lineWidth = 3; //Establece el ancho de línea del pincel ctx.beginPath() //Inicia el pincel//Dibuja el color del borde degradado del borde del 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;//Establece el color del pincel ctx.arc(0,0,r - 80,0,2*Math.PI,false) //Dibuja un círculo, coordenadas 0,0, radio 250-80, círculo completo (0 -360 grados), falso significa en el sentido de las agujas del reloj ctx.closePath()ctx.stroke() //DibujoLos resultados del dibujo son los siguientes.
2. Dibuja la imagen de fondo en el medio del anillo (el origen del lienzo actual es el centro del lienzo)
dibujarImagen(imagen, dx, dy, dAncho, dAlto)
imagen: recurso de imagen de lienzo, como imagen <img>, imagen SVG, elemento de lienzo en sí, etc.
dx, dy: planifique un área en el lienzo del lienzo para colocar imágenes. dx son las coordenadas horizontales y verticales de la esquina superior izquierda de esta área.
dAncho, dAlto: Planifique un área en el lienzo del Lienzo para colocar imágenes, el ancho y el alto de esta área.
Las siguientes coordenadas son calculadas por el autor.
let image = new Image()image.src = 'image/quan.png'image.onload = () => { // Mueve el origen al centro ctx.drawImage(image,-140,-140,280,280)}Los resultados del dibujo son los siguientes:
3. Dibuja texto y pequeños puntos en el anillo (el origen del lienzo actual es el centro del lienzo)
Objetivos de dibujo para texto y puntos pequeños:
3.1 Los puntos pequeños se muestran uniformemente en el anillo grande
3.2 El texto está un poco disperso fuera de los pequeños puntos.
Solución:1. El autor usa una matriz para almacenar las palabras actuales.
let textArr = ['Amplio mar y cielo','Capacidades técnicas','Fondos fuertes','Control de mantenimiento','Vive y trabaja en paz y satisfacción','Cuida las flores','Termina el toque final',' Deshacerse de la escoria','Vaya contra el viento','Desarrollo profesional']
2. Debido a que la cantidad de puntos pequeños y la cantidad de palabras son las mismas, la cantidad de ambos es la longitud de la matriz textArr anterior.
3. El radian de un círculo completo es 2π Para que los puntos pequeños dividan equitativamente el anillo, el autor primero calcula el radian del punto donde se encuentra cada punto pequeño.
for(let i = 0;i<lengths;i++){ // Calcular radianes let rad = 2*Math.PI/lengths*i}4. Según funciones trigonométricas, se pueden calcular las coordenadas (x, y) del pequeño punto actual en el lienzo (el origen del lienzo actual es el centro del lienzo)
Entre ellos, la relación entre radianes, puntos pequeños, anillos, radio del anillo y origen del lienzo, el autor hizo un dibujo para describirlos.
Calcula las coordenadas del texto:
// Calcula las coordenadas del centro del círculo pequeño sea x = (r - 40)*Math.cos(rad)let y = (r - 40)*Math.sin(rad)
Calcule las coordenadas del punto pequeño: debido a que el centro del punto pequeño debe caer sobre el anillo, las coordenadas horizontales y verticales calculadas son,
// Calcula las coordenadas del texto sea x = (r - 80)*Math.cos(rad) sea y = (r - 80)*Math.sin(rad)
El código específico es el siguiente:
// Dibujar texto ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ //radianes let rad = 2*Math.PI/lengths*i // Calcula las coordenadas del centro del círculo pequeño let x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// Dibuja pequeños puntos para(let i = 0;i<longitudes;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)// // Dibuja pequeños puntos grises translúcidos en el borde ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0.8)' ctx.arc(x,y,8,0,2*Math.PI,false) ctx.closePath() ctx.fill() // Dibuja pequeños puntos azules ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx.closePath( ) ctx .llenar() }Los resultados del dibujo son los siguientes:
4. Dibuja un triángulo fuera de cada punto pequeño (el origen del lienzo actual es el centro del lienzo)
4.1 Debido a que desea dibujar una forma de triángulo, la idea de dibujar un triángulo es dibujar líneas a ambos lados con el centro del pequeño punto actual como punto inicial, luego usar ctx.fill() para cerrar la forma y llena el interior con color degradado.
Dibuja un triángulo: las coordenadas se calculan por sí mismas. El autor suma y resta 35 en abscisas y 70 en ordenadas (lo que quieras, jajaja)
//Inicia el pincel ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()
Dibuja el texto debajo del triángulo: (Para distinguirlo del texto anterior, usé rojo para mi texto aquí)
ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)
El código específico es el siguiente:
for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad) // // Dibujar el triángulo // // ctx.rotate( -Math.PI / 4) ctx.beginPath() //Inicia el pincel ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath() // // Establece el degradado de color- - ->Añadir color desde el centro a ambos 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)}Los resultados del dibujo son los siguientes:
4.2 El requisito es que la dirección de cada triángulo sea extenderse hacia afuera, y ahora la dirección de los triángulos es hacia abajo, por lo que ahora debe usar el método de rotación del lienzo.
ctx.save() ctx.translate(x,y) // El ángulo de rotación está centrado en cada punto pequeño ctx.rotate( rad - Math.PI/2 ) // Porque el punto pequeño ctx.translate(- x, - y) Omita el código para dibujar triángulos y texto.
Se puede ver en el cálculo que tomando el centro del punto pequeño como punto inicial de rotación, el arco de rotación del triángulo debe ser el arco del punto pequeño actual menos π/2, porque la posición inicial de la rotación siempre comienza desde la dirección positiva del eje de coordenadas x, es decir, comienza en 0 radianes, pero ahora todos los triángulos están en π/2 radianes, entonces:
Radianes de rotación = Radianes de punto pequeño - π/2
Recuerde utilizar el método de almacenamiento del estado de Canvas save() al rotar.
restablece() muestra el estado del Canvas almacenado desde la parte superior de la pila a su vez. Si no hay un estado del Canvas almacenado, no habrá cambios al ejecutar este método.
Asegúrese de recordar usar el método restaurar () al final. En este punto, el autor derramó lágrimas de arrepentimiento. . .
Código específico:
for(let i = 0;i<lengths;i++){ // // let rad = 2*Math.PI/lengths*i let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad) // Dibuja un triángulo s ctx.save() // El ángulo de rotación está centrado en cada punto pequeño porque los puntos pequeños están al principio ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // Inicia el pincel ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70 ) ctx.lineTo(x+35,y+70) ctx.closePath() //Establecer degradado de color--->Agregar var de color desde el centro hacia ambos 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()}Trazar el resultado:
Eche un vistazo más de cerca, ¿qué? ? ? Algunos textos están al revés debido a problemas de rotación. A través de la observación, el resultado es que cuando el radianes es mayor que π, el texto queda al revés.
Es hora de escribir una ola de juicios. . . .
Cómo rotar texto:
function rotarContext(ctx, x, y, grado) { // Rotar texto ctx.translate(x, y) // ctx.rotate(grado * Math.PI / 180) ctx.rotate(grado) ctx.translate(-x , -y) }Determinar puntos pequeños cuyo radianes sea mayor que π
if (rad > Math.PI) { // Debido a que el texto debe mostrarse en el borde del triángulo, el texto debe rotar con el triángulo para que siempre pueda mantenerse en el // borde del triángulo después de la rotación. , el texto aparecerá cuando el radianes sea mayor que π. Invierta el problema, así que gire el texto ctx.save() ctx.beginPath() // Gire el texto turnContext(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)}Los resultados del dibujo son los siguientes:
De cara a la victoria, casi lo hemos logrado. Al menos tenemos un diseño aproximado. ¡La revolución aún no ha tenido éxito y los camaradas todavía necesitan trabajar duro! !
5. La siguiente es la implementación. Cuando el mouse está sobre el punto pequeño, se muestran el triángulo en el borde y el texto en el borde del triángulo, pero no se muestra el texto en el borde del círculo.
Idea:1. Vincula el evento de entrada del mouse al lienzo.
2. Determine si las coordenadas de la posición actual del mouse en el lienzo son iguales a las coordenadas cerca de un punto pequeño. Si es así, muestre el triángulo correspondiente al punto pequeño.
5.1 Vincular el evento mousemove al lienzo: el mouse está encima del evento
lienzo.addEventListener('mousemove',clickEvent)5.2 Calcular las coordenadas actuales del mouse en el lienzo.
El método de cálculo es: use las coordenadas actuales del mouse en el DOM para restar la distancia desde la izquierda o la parte superior del lienzo para calcular la distancia del lienzo.
El método drawOne en la figura siguiente es el método de dibujo, que se analizará más adelante en este artículo.
function clickEvent() { // Las coordenadas de la posición del mouse let x = event.clientX - canvas.getBoundingClientRect().left let y = event.clientY - canvas.getBoundingClientRect().top drawOne(x,y)}5.3, porque las coordenadas del mouse en el lienzo calculadas anteriormente se calculan con la esquina superior izquierda del lienzo como origen, pero el origen del lienzo actual ya se ha movido al centro del lienzo (250,250), por lo que cuando se usa para determinar si un clic son pequeños puntos Debes restar 250 de las coordenadas horizontales y verticales para compararlas con las coordenadas del pequeño punto en el lienzo actual. Cuando estaba haciendo el juicio, encontré un problema, no sé por qué la diferencia en la dirección y. del autor es 260 en lugar de 250. Entonces el autor restó 260 en la dirección y.
El código es el siguiente:
Entre ellos, Cx, Cy son las coordenadas del mouse en el lienzo (la esquina superior izquierda del lienzo es el origen), x, y son las coordenadas del pequeño punto actual,
El autor calculó directamente la posición de 15 px cerca del centro del punto pequeño, se mostraron todos los triángulos y el punto pequeño se volvió blanco.
Lo más importante es que debes borrar el lienzo anterior cada vez que vuelvas a dibujar: recuerda usar el método clearRect para borrar el lienzo.
sea XX = Cx - 250 sea YY = Cy- 260 sea izquierdaX = x - 15 sea derechaX = x + 15 sea arribaY = y - 15 sea inferiorY = y + 15if (XX >= izquierdaX && XX <= derechaX && YY <= abajoY && YY > = topY ) {//Se hace clic. . . . . . //Escribe el código de dibujo en el medio}El código va seguido de un enlace:
6. Defina una entrada en la interfaz y vincule el evento de cambio a la entrada.
Implementación: La interfaz se vuelve a dibujar cada vez que cambia el valor en la Entrada.
código html:
<tipo de entrada = id de texto = estilo de entrada = margen izquierdo: 100 px; margen superior: 50 px marcador de posición = Ingrese...>
código js:
let inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) //Esto El método es el método de dibujo, el código fuente se proporcionará más adelante en el artículo}})7. Hay un problema. Cada vez que hace clic en la interfaz y la vuelve a dibujar, habrá una situación intermitente.
Como se muestra a continuación:
Cada vez que se desliza, debido a que las coordenadas del mouse cambian, debe borrar el contenido alrededor del anillo y volver a dibujarlo. Por lo tanto, es necesario limpiar el lienzo para lograr efectos dinámicos.
clearRect() se usa muy comúnmente en el dibujo de animación de Canvas. Borra continuamente el contenido del lienzo y luego lo dibuja para formar un efecto de animación.
clearRect() puede hacer transparente un área rectangular en el lienzo del elemento Canvas.
contexto.clearRect(x, y, ancho, alto);
x, y: coordenadas x, y de la esquina superior izquierda del rectángulo.
ancho, alto: el ancho y alto del área rectangular despejada.
Dado que clearRect () solo puede borrar el área rectangular del lienzo, cada vez que se borra, la imagen de fondo en el medio se borrará junta.
Por lo tanto, la imagen de fondo debe recargarse cada vez y la imagen tarda una cierta cantidad de tiempo en cargarse, por lo que parpadeará cada vez que aparezca.
Solución:dibujarImagen(imagen, dx, dy, dAncho, dAlto)
La imagen del parámetro: recurso de imagen de Canvas, como imagen <img>, imagen SVG, elemento Canvas en sí, etc.
Luego puedes usar otro lienzo para almacenar imágenes en caché.
Use un lienzo adicional para dibujar la imagen de fondo, pero para ese lienzo que no se muestra en la interfaz: display:none, y luego úselo para borrar el lienzo y representar directamente el objeto del lienzo almacenado en caché en el medio del lienzo que se mostrará, eso Es decir, no es necesario cargar imágenes una vez. Lleva mucho tiempo.
código html:
<ancho del lienzo = 280 alto = 280 estilo = margen izquierdo: 50 px; relleno superior: 20 px; pantalla: ninguno;
código js:
//Utilice el almacenamiento en caché para resolver el problema de flasheo de imágenes redibujadas var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; tempCanvas.height = 280let image = new Image( )image.src = 'image/quan.png'image.onload = () => { // El origen se mueve al centro tempCtx.drawImage(image,0,0,280,280)}Después de borrar el lienzo, dibuje el lienzo almacenado en caché: tempCanvas directamente al volver a dibujar la imagen.
// Dibuja el lienzo almacenado en caché directamente en la interfaz (la interfaz del neumático intermedio está en caché) ctx.drawImage(tempCanvas,-140,-140)
Bien, lo logré, aquí está la imagen del resultado:
La dirección del código fuente es la siguiente:
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
ResumirLo anterior es la introducción del editor al uso del lienzo html5 para dibujar animaciones de anillos. Espero que le resulte útil. Si tiene alguna pregunta, déjeme un mensaje y el editor le responderá a tiempo. ¡También me gustaría agradecer a todos por su apoyo al sitio web de artes marciales VeVb!