entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

1voto

javascript drawimage sólo carga un grupo de imágenes si pongo un alert

En un bucle en javascript, cargo un grupo de imágenes. Sin embargo, no se ven salvo que ponga un "alert" entre la carga de cada imagen:

    dibplanet[i] = new Image();
    dibplanet[i].src = "simbolos/" + nombreplanet[i] +".png";
    dibplanet[i].onload = function() {
      dib.drawImage(dibplanet[i], x, y, sca,sca); 
    }; 
    alert("asi funciona");

3 Respuestas

1voto

oraculus Puntos310

He logrado resolverlo de la siguiente manera:

    dibplanet[i].xx=x;
    dibplanet[i].yy=y;
    dibplanet[i].onload = function() {
      dib.drawImage(this, this.xx, this.yy, sca, sca);
    }; 

Así si funcionan las variables dentro de "onload".
Muchas gracias por todo. :-)

0voto

Peter comentado

Si esta es la respuesta correcta y solución, por favor maraca como correcta. :)

1voto

Leonardo-Tadei Puntos226990

Hola Juan,

estodebe estarte pasando porque el buble se ejecuta tan rápido que no alcanzan a verse las imágenes. Asumo que sin el alert() la única que se ve es la última.

Una forma de conseguir lo que querés es sacar la variable de control de tu bucle fuera del ámbito, y que la llamada sea vía setInterval() para darle tiempo a que se vea cada una de las imágenes:

<script>
var i = 0;
function drawImage(){
...
dibplanet[i] = new Image();
    dibplanet[i].src = "simbolos/" + nombreplanet[i] +".png";
    dibplanet[i].onload = function() {
      dib.drawImage(dibplanet[i], x, y, sca,sca); 
    }; 
...
}
</script>
</head>
<body onload="myVar=setInterval('drawImage()',100)">

Así se dibujan las imágenes de a una, con una pausa de 0.1 segundos. La función setInterval() reemplaza al bucle.

Para cortar el bucle al detectarlo con tu variable de control, tenés que llamar a

clearInterval(myVar);

posiblemente puedas hacer esto dentro de drawImage() al detectar la condición de terminación a través de la variable i

0voto

oraculus comentado

Muchas gracias Leonardo. He realizado una prueba con setInterval, antes de aplicarlo a la función definitiva:

var myVar;
var cti = 0;
function prueba(){
  cti = cti + 1:
  alert(cti);
  if (cti > 10) {
     clearInterval(myVar);
  } 
}

function dibuja_carta(ctx, width, height){
        myVar=setInterval('prueba()',100);
...

Pero el programa se congela sin que actúe ningún alert(cti), ni continúe la función dibuja_carta. No sé donde he metido la pata.

1voto

Leonardo-Tadei comentado

Hola Juan,

el código funciona, pero tenés un error de sintaxis. La línea:

cti = cti + 1:

termina con dos puntos en vez de con punto y coma

cti = cti + 1;

Tengo abajo todo un script que funciona para que lo pruebes y adaptes:

<!DOCTYPE html>
<html>
<head>
    <title>prueba</title>
<script type="text/javascript">
var myVar;
var cti = 0;

function prueba(){
  cti = cti + 1;
  alert(cti);
  if (cti > 10) {
     clearInterval(myVar);
  } 
}

function dibuja_carta(ctx, width, height){
    myVar=setInterval('prueba()',100);
}
</script>

</head>

<body>
    <a href="javascript:dibuja_carta(1,2,3);">Probar!</a>
</body>
</html>

0voto

jaime_pastor comentado

Poner un temporizador para cargar las imágenes no es una solución correcta. Simplemente soluciona el problema añadiendo más complejidad y añadiendo posibles efectos secundarios dependiendo del resto de código.

0voto

Leonardo-Tadei comentado

Hola Juan!

qué respuesta te sirvió??? o sigue sin funcionar?

0voto

oraculus comentado

Hola Leonardo. Sigue sin funcionar. El hecho de tener que emplear "onload" hace que no tenga control alguno sobre las variables x, y y sca, ya que estas variables dependen de los datos que introduce el usuario al inicio.

0voto

Leonardo-Tadei comentado

Hola Jaime,

si los valores de x, y y sca los introduce el usuario en una página distinta, podrías hacer que este script las procese en PHP y las declare globales antes de que se ejecute el enLoad.

Si los valores de x, y y sca los introduce el usuario en la misma página, es más fácil todavía, ya que en el onClick del botón del formulario con los valores llamás a una función JS que defina las variables y luego llame a dibuja_carta() en vez de llamarla en el onLoad.

Igual, el problema de que no se ven las imágenes es independiente del valor de las variables: podrías probar con valores fijos, y en otra pregunta podemos ver con detalle el tema de las llamadas.

Saludos cordiales!

2votos

jaime_pastor Puntos440

El problema es debido a que estás utilizando el índice i en el callback de onload de la imagen, y aunque no pones el código completo del for es casi seguro que estés indexando con esa variable.

En ese caso, si el código dentro del for es exactamente lo que pones, puedes sustituir el acceso al vector por this.

dibplanet[i].onload = function() {
  dib.drawImage(this, x, y, sca, sca); 
};

El tener el alert puesto y que así funcione es porque estás paralizando la ejecución, y en ese tiempo que está parada la petición de la imagen por debajo se ha completado.

Hay otras muchas maneras de resolver esto, pero en este caso con esto es suficiente.

1voto

oraculus comentado

Efectivamente Jaime, con "this" todas las figuras se dibujan. Con setInterval seguían sin dibujarse.
Ahora surge un problema nuevo; con el "alert" cada figura se dibujaba en la posición x,y, pero con "this" todas las figuras se dibujan superpuestas en la última posición de x,y.

1voto

jaime_pastor comentado

Como sólo pones ese trozo de código no te puedo decir nada sobre las otras variables. Me imagino que el problema que tienes es porque la posición depende del índice.

Una solución para que te funcione, sin conocer lo que has puesto sería usar el patrón módulo dentro del for:

for (i...) {
  (function(i) {
    // Use 'i' to calculate the coordenades or whatever you need
    dibplanet[i] = new Image();
    dibplanet[i].src = "simbolos/" + nombreplanet[i] +".png";
    dibplanet[i].onload = function() {
      // Now you can use the 'i' here, but 'this' is better
      dib.drawImage(dibplanet[i], x, y, sca, sca);
    };
  }(i));
}

1voto

oraculus comentado

Muchas gracias Jaime. El código es más complejo, puede verse en "dibuja.js" aqui. Hay que introducir una fecha, hora y lugar de nacimiento para que dibuje las posiciones planetarias.
Lo que he hecho es lo siguiente:

 dibplanet[i].onload = function(x, y, sca) {
      dib.drawImage(this, x, y, sca, sca);
    }; 

La consola no devuelve ningún error, pero no dibuja nada.

0voto

jaime_pastor comentado

Quizá el problema esté en que las variables x, y y sca sean globales. Las tienes que declarar dentro del patrón módulo, osea, dentro de la función del for.

(function(i) {
  var x, y, sca;
  // TODO
}(i))

0voto

oraculus comentado

"x", "y" y "sca" no son globales. Están declaradas dentro de la función en la que se encuentra el bucle for(i.
¡Qué misterio! :-)

  for(i= 1; i<= 11; i++){
    pg = parseFloat(IniRad) + parseFloat(lpl[i]);                
    x = cx + Math.round(Radi * Math.sin(Degtorad(pg)));
    pg2 = parseFloat(IniRad) + Math.abs(parseFloat(lonpla[i]));
    x2 = cx + Math.round(Radi2 * Math.sin(Degtorad(pg2)));
    y = cy + Math.round(Radi * Math.cos(Degtorad(pg)));
    y2 = cy + Math.round(Radi2 * Math.cos(Degtorad(pg2)));
    // colorPincel(imprimir, Tv);
    grueso= Math.round(sc * 1);
    // alert(grueso);
    Line(dib,x, y, x2, y2, parseInt(grueso));
    pg = parseFloat(IniRad) + parseFloat(lpl[i]);
    x = cx + Math.round(Radi3 * Math.sin(Degtorad(pg)));
    x = x - Math.round(correc);
    y = cy + Math.round(Radi3 * Math.cos(Degtorad(pg)));
    y = y - Math.round(correc);
    dibplanet[i] = new Image();
    dibplanet[i].src = "simbolos/" + nbplanet[i] +".png";
    // ***NO*** dibplanet[i].getContext("2d");
    // alert(x + " " + y);
    // alert(pg);

    dibplanet[i].onload = function(x, y, sca) {
      dib.drawImage(this, x, y, sca, sca);
    }; 
    // alert();

} // next i

1voto

jaime_pastor comentado

El error es debido a que x, y y sca se las estás pasando como parámetro a la función onload.

Y por otro lado, no has metido todo el código del for dentro del patrón módulo que ya te indiqué.

0voto

oraculus comentado

x, y, y sca dependen de otras variables fuera del bucle for. Al final, habría que meter el programa entero en la función onload.

0voto

oraculus comentado

Supongo que se trata de una limitación de Javascript el hecho de que dentro de "onload" no tengas el control que necesito para que mi programa funcione, por lo que quedo muy agradecido por vuestra ayuda sin dar el tema como solucionado.

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta