Canvas tiene una API muy poderosa llamada drawImage() (w3c):
Su función principal es realizar dibujos, vídeos e incluso otros lienzos.
pregunta:Llegó allí admirado, pero falló. Cuando bajó la cabeza, vio un gran agujero en el suelo.
La cosa es así, después de leer la introducción de w3c y la demostración muy convincente y didáctica, decidí intentarlo basándome en la idea de practicar para obtener un conocimiento verdadero. pruébalo ~
Establecí las siguientes tareas básicas según el proyecto de la línea de montaje:
1. etiqueta de lienzo + identificación
<canvas id=canvas1></canvas>
2. Obtener lienzo + establecer ancho y alto
var cav1 = document.getElementById('canvas1'), wWidth = 800, wHeight = 600; cav1.width = wWidth;3. getContext('2d') prepara el lienzo
var ctx1 = cav1.getContext('2d');4. Crea un nuevo objeto Image() y dale los atributos de las imágenes que me gustan... (no pienses demasiado)
var bgImg = nueva Imagen();bgImg.src = 'imágenes/fondo.jpg';
5. Finalmente es hora de dibujar. Escribí con entusiasmo este código:
ctx1.drawImage(bgImg,0,0,wAncho,wAlto);
Nerviosa, presioné F5 en el navegador.
Luego se hizo un silencio de muerte...
Pensé que el código estaba escrito mal, así que volví y lo revisé cuidadosamente y era correcto.
Copie los nombres de los atributos clave y los métodos de w3c y verifique nuevamente. De hecho, es correcto.
Cuando se imprime la imagen, ¡también aparece esta imagen (de una persona)!
Luego, cuando observé el caso del W3C, la diferencia con mi código es que sus imágenes están en HTML.
Luego aprendí a insertar imágenes en html,
<img src=./images/background.jpg id=imgs style=display:none></img>
Y use getElementById para obtener este elemento,
var bgImg = document.getElementById('imgs')Ejecutar el dibujo nuevamente funcionó.
¡Él realmente puede!
Pienso tristemente, ¿tiene que ser físico? ¿No se coloca simplemente delante de la etiqueta del lienzo? js load también tiene entidades, y todavía uso new, ¡qué diferente a las personas reales!
Así es, ¿no se pone simplemente al frente? ¡Esto implica una cuestión de secuencia!
Es cierto que la imagen cargada en js se coloca delante del dibujo, pero tardará un poco en cargar la imagen. Es necesario dar tiempo para el almacenamiento en búfer de la imagen. Espere hasta que la imagen se cargue correctamente antes de poder dibujarla. El método drawImage no se llamará cuando la imagen se utilice antes de haber sido cargada. El dibujo fallará. ¡Veo!
¿Algunas personas argumentan que las imágenes en etiquetas img no tardan en cargarse? ¿En este momento drawImage no está restringido? ! Pero no ignore window.onload al comienzo de js. Incluso si la imagen se carga lentamente, incluso si el orden de las etiquetas de la imagen es posterior a la etiqueta del lienzo, pero tengo window.onload cubriéndola, mi imagen no puede ser. cargado, y tu drawImage no tendrá ninguna posibilidad, ¿verdad?
El orden aproximado es este:
<img src=>ventana.onload = función(){ drawImage}Si la imagen no estuviera insertada en la estructura html, mi descuido habría eludido esta restricción:
Como solicitud de recurso, cuando la imagen se carga en js, naturalmente habrá un tiempo de carga de la imagen.
Pero como no hay límite, en la mayoría de los casos se llama a drawImage cuando la imagen no se ha cargado y este método no funcionará.
resolver:Entonces, ¿existe una buena manera de resolver el problema de falla en el dibujo de drawImage debido a la secuencia de carga de la imagen?
He resumido los siguientes tres métodos:
1. etiqueta+ventana.onload <img src=>ventana.onload = función(){ contexto.drawImage()}La solución principal de este método es la carga, que carga la imagen y drawImage por separado. La img se carga primero para garantizar que el dibujo se utilice una vez completada la carga.
1-2. ¿Insertar etiquetas más tarde? ¿Es factible?Una situación es que cuando usa la función de captura de pantalla, también puede usar drawImage, y la captura de pantalla no toma una captura de pantalla de su propia imagen existente, sino que usa la dirección de una imagen como parámetro.
Creo que este tipo de cosas requiere que js cree una img y le asigne la dirección. Luego genere la imagen y tome una captura de pantalla.
var myImg = document.createElement('img');myImg.src = '///';document.body.appendChild(myImg);ctx1.drawImage(myImg,0,0,wWidth,wHeight);¿No quieres agregar etiquetas adicionales? ¿Necesito usar js como se muestra a continuación para crear un nuevo objeto de imagen?
var bgImg = nueva Imagen();bgImg.src = 'imágenes/fondo.jpg';
Como se mencionó anteriormente, este tipo de imagen creada usando new Image() requiere tiempo para almacenar la imagen en el buffer. Espere hasta que la imagen se cargue correctamente antes de poder dibujarla.
El objeto de imagen está listo, pero ¿cómo saber cuándo está realmente cargada la imagen? Bueno, hay otra manera:
Mientras se ejecuta la tarea js, ¿crees que estoy demasiado cerca de tu tiempo de ejecución? ¿Puedes sacarme solo y ponerme en cola nuevamente y luego ejecutarla nuevamente más tarde?
2. Implementación asincrónica del temporizador setTimeout(función(){ ctx1.drawImage(bgImg,0,0,wWidth,wHeight);},10)¿Por qué hay un retraso al escribir aquí 10 en lugar del conocido 1000 o 0?
Porque bajo la prueba de mi entorno wifi específico y mi computadora de escritorio específica, 10 puede aparecer simplemente después de cargar la imagen, a diferencia de 0 que no aparece, y no quiero esperar medio día como 1000.
Pero imagina que si cambias la imagen por una más grande, ¿seguirían aplicándose estos 10? ¿Se seguirá aplicando este 10 si se cambia el wifi a 2g?
Por lo tanto, la desventaja del temporizador es que no hay garantía de que la imagen se cargue una vez transcurrido el tiempo y aún se colgará si la red no es rápida.
3. img.onloadwindow.onload nos da una idea. ¿No podemos monitorear directamente la finalización de la carga?
Utilice el evento de carga de img para monitorear la carga exitosa de la imagen y luego ejecutar el efecto de dibujo del lienzo. Y este método es más confiable.
bgImg.onload = function(){ console.log('Imagen cargada correctamente'); console.log(this); ctx1.drawImage(bgImg,0,0,wWidth,wHeight);De hecho, estos tres métodos tienen el mismo núcleo, que es dejar que la imagen se cargue primero. Es decir, precarga de imágenes. Pero para las imágenes almacenadas en caché, la precarga de imágenes también debe resolver el problema de monitorear las imágenes almacenadas en caché cuando la página no se actualiza.
Encontré otro problema. . . . Primero, así es como se ve la pintura de fondo después de terminarla.
Entonces finalmente apareció la imagen de fondo y continué felizmente.
Entonces inmediatamente dibujé una línea roja para evitar no verla, también aumenté el ancho a 20:
bgImg.onload = function(){ ctx1.drawImage(bgImg,0,0,wWidth,wHeight); } /* Dibuja la línea roja de la siguiente manera: */ ctx1.beginPath(); ctx1.lineTo (10,wHeight-100); ctx1.lineWidth = 20; ctx1.strokeStyle = 'rojo'; ctx1.stroke(); ctx1.closePath();Pero cuando presiono F5, todavía no hay cambios y todavía no puedo ver la línea roja.
Después de buscar durante mucho tiempo, no lo vi hasta que desactivé la imagen de fondo:
¡Ah, resulta que estaba cubierto por la imagen de fondo!
¿Pero por qué?
Estoy pensando que hay dos posibilidades.
1. Problemas de jerarquía
2. Problemas de secuencia
Con respecto a 1, se siente como el índice z de CSS, donde la imagen de fondo cubre la línea roja. ¿Podría ser que el nivel de la imagen de fondo sea superior a la línea roja?
No tenía forma de probar esta hipótesis, así que renuncié a la segunda posible revelación.
¿Pero por qué la imagen de fondo está en la parte superior? ¿Es porque la imagen de fondo se dibuja más tarde?
Esto se puede observar más fácilmente mediante la impresión de console.log() para observar la secuencia de ejecución.
Resulta que el culpable es la devolución de llamada de carga. Al igual que el temporizador, es una tarea asincrónica. Naturalmente, está clasificado detrás de la tarea de sincronización (dibujando líneas a continuación)
Entonces, la carga parece ser una buena solución, pero sus deficiencias también se exponen aquí.
¡Muy bien, parece que el plan de aprendizaje prometido debería programarse lo antes posible! Jajaja
Lo anterior es el contenido completo de este artículo. Espero que sea útil para el estudio de todos. También espero que todos apoyen VeVb Wulin Network.