Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    Curioso comportamento di una function con e senza setTimeout()

    Salve, vorrei capire il comportamento anomalo del seguente script, atto a colorare a caso 50 div generati con un ciclo for precedente.
    codice:
    function colora() {  let elemento = document.getElementById("contenitore").getElementsByTagName("div");
      let numero = elemento.length;
    
      for (let i = 0; i < numero; i++) {
        let colore = "#";
    
        for (let c = 1; c <= 3; c++) { 
          let casuale = Math.floor(Math.random()*255); 
          let esadecimale = casuale.toString(16); 
          colore = colore + esadecimale;
        }
    
        elemento[i].style.backgroundColor = colore;
      }
      setTimeout("colora()", 500); 
    }
    In sostanza succede che, se tolgo il setTimeout(), un buon 20% di div restano senza colore, nel senso che, da Ispeziona, noto che non gli viene assegnato il valore colore all'attributo CSS background-color, mentre col setTimeout() ho che tutti i div ricevono un colore.
    Perché alcuni div saltano l'istruzione??

  2. #2
    Allego schermata della situazione affinché sia più chiaro cosa intendo: nel codice alcuni div saltano lo style nel tag HTML relativo.
    div.jpg

  3. #3
    Utente di HTML.it L'avatar di ninja72
    Registrato dal
    May 2020
    residenza
    -
    Messaggi
    319
    Se non ho capito male l'errore sta nella generazione dell'esadecimale, ottieni valori casuali errati per colpa del valore 255, che va bene per il calcolo di valori rgb ma non esadecimali.

    codice:
    function colora() {
        const elemento = document.querySelectorAll("#contenitore div")
        const numero = elemento.length
    
        for (let i = 0; i < numero; i++) {
            let colore = "#"
    
            for (let c = 1; c <= 6; c++) {
                let esadecimale = Math.floor(Math.random() * 16).toString(16)
                colore += esadecimale
            }
    
            elemento[i].style.backgroundColor = colore
        }
    }
    
    setTimeout(colora, 500)

  4. #4
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    Ciao, non è così semplice scovare la causa, ma con qualche console.log puoi verificare tu stesso cosa avviene e capire dove sta il problema.

    Mettendo console.log(colore) dopo il ciclo che popola tale variabile, puoi vedere cosa ti salta fuori.

    Esempio:
    codice:
    ...
    #19d880
    #175b73
    #617d7
    #81b2ae
    #343868
    #b76ad7
    #c4806
    ...

    Puoi notare che alcune di queste stringhe hanno un carattere in meno; questo rende il valore con un formato non conforme a quello richiesto per il codice colore. Attualmente i formati validi possono essere espressi con diverse quantità di caratteri esadecimali:
    3 (forma ridotta #RGB)
    4 (forma ridotta con trasparenza #RGBA)
    6 (forma estesa #RRGGBB)
    8 (forma estesa con trasparenza #RRGGBBAA)

    ma la forma con 5 caratteri non esiste ed è perciò considerato come valore non valido. Questo impedisce quindi di attribuire la proprietà CSS specifica che viene semplicemente tralasciata.

    Per risolvere dovrai effettuare un cosiddetto "zero padding" (o "zero leading"), in modo da anteporre il carattere 0 per i valori esadecimali che hanno solo un carattere, ed ottenere quindi sempre dei blocchi di 2 caratteri.

    Per fare questo puoi usare vari metodi. Attualmente è disponibile il metodo padStart() (EcmaScript 2017) che può fare al caso.

    Nel tuo script puoi applicarlo al valore calcolato per la variabile "esadecimale", in questo modo:
    codice:
    let esadecimale = casuale.toString(16).padStart(2, '0');


    mentre col setTimeout() ho che tutti i div ricevono un colore
    Il problema lo hai comunque anche col setTimeout, solo che lo noti meno.

    La prima volta che viene richiamata la funzione avrai un certo numero di probabilità che il backgroundColor non sia applicato; ma richiamando man mano la funzione, non fai altro che andare a "colmare" i div tralasciati precedentemente.

    Dal momento che la proprietà viene semplicemente sovrascritta solo quando il valore è valido, dopo qualche volte che viene richiamata la funzione, tutti i div avranno comunque un valore valido.

    In altre parole, i valori validi restano invariati anche se al successivo giro viene calcolato un valore non valido, perché in tal caso non viene sovrascritta la regola esistente in cui il valore è valido. Bastano quindi 2 o 3 giri per avere tutti i div colorati rendendo il problema impercettibile.
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  5. #5
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    Quote Originariamente inviata da ninja72 Visualizza il messaggio
    ottieni valori casuali errati per colpa del valore 255, che va bene per il calcolo di valori rgb ma non esadecimali.
    I valori vengono però convertiti in esadecimale con toString(16)

    La causa del problema non era esattamente quella ma c'eri vicino

    Lo script che hai proposto non genera errori perché otterrai sempre la forma ridotta #RGB, dal momento che il valore casuale da 0 a 16 (anzi 15, vedi EDIT), convertito in esadecimale produce sempre solo un carattere (da 0 a F).

    Questo potrebbe andare bene in generale, ma in tal modo ottieni un colore tra una serie limitata di (16 alla terza) colori, anziché tra quella completa (255 alla terza) EDIT (256 alla terza).


    EDIT: mi correggo, il tuo script non va comunque bene perché il valore massimo di F (esadecimale) corrisponde a 15 (decimale).
    Usando questo:
    codice:
    Math.floor(Math.random() * 16)
    è possibile che avvenga questa situazione (anche se le probabilità sono minime):
    codice:
    (1 * 16).toString(16)
    che produrrebbe il valore "10", e potrebbe generare comunque l'errore sopracitato.

    Il valore massimo deve chiaramente essere 15:
    codice:
    Math.floor(Math.random() * 15)
    Ultima modifica di KillerWorm; 14-03-2022 a 19:04
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  6. #6
    Moderatore di CSS L'avatar di KillerWorm
    Registrato dal
    Apr 2004
    Messaggi
    5,771
    mi son documentato meglio e mi ricorreggo stavo prendendo un granchio

    Math.random() genera un numero casuale da 0 (incluso) a 1 (escluso), per cui lo script proposto da ninja72 è ok, non genera errori.
    Questa parte:
    codice:
    Math.floor(Math.random() * 16).toString(16)
    è perfettamente valida per ottenere un valore esadecimale da 0 a F.

    Mentre nello script postato da Gas75, sarebbe meglio correggere quel 255 sostituendolo con il più appropriato 256 (cioè 16 alla seconda), così:
    codice:
    let casuale = Math.floor(Math.random()*256);
    questo infatti genera un valore tra 0 e 255 che, convertito in esadecimale, restituisce un valore tra 0 e FF.

    Le indicazioni che ho postato prima restano comunque valide riguardo il problema in oggetto.

    buon proseguimento
    Installa Forum HTML.it Toolset per una fruizione ottimale del Forum

  7. #7
    Grazie KillerWorm! La spiegazione è chiarissima, non era facile intuire che un numero esadecimale potesse essere di una cifra e, come tale, concatenato alla stringa colore.
    Per sistemare le cose, in un contesto di visualizzazione di orari, utilizzo una semplice funzione che probabilmente emula padStart():
    codice:
        function zero(numero) {
    
          if (numero < 10){
            numero = "0" + numero;
          }
    
    
          return numero;
        }

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.