IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

NodeJS Discussion :

Affichage de chuncks au scroll de la page


Sujet :

NodeJS

  1. #1
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut Affichage de chuncks au scroll de la page
    Bonjour

    Je fais un jeu en 3D isométrique. Pour économiser la mémoire du browser (client), le jeu est décomposé en chuncks de 40x40 tiles. Les chuncks chargés par le client sont mis à jour à chaque fin de scroll : quand l’utilisateur a fini de scroller, le client fait deus choses : 1) il envoie sa position au serveur, qui lui retourne ensuite les chuncks encore non chargés, l’idée étant que le client a toujours en mémoire 25 chuncks (5x5), le centre de ces 5x5 chuncks étant le chunck qu’il affiche à l’écran. 2) le client supprime de sa mémoire les chuncks déjà chargés, mais qui sont hors de son scope, c’est à dire qui sont au delà d’un radius de 2 par rapport à là où il regarde.

    Nom : A.png
Affichages : 163
Taille : 16,1 Ko

    Dans le dessin A, les carrés à bords noirs sont des canvas, celui à bords rouge étant celui que le client ‘regarde’ (affiche à l’écran). Les chuncks sont de la data pure (herbe à tel endroit, eau à tel autre) et sont dessinés sur les canvas. Dans ma typolgie, un chunck peut être de type ‘full’ ou ‘cross’ : un full occupera un canvas entièrement, tandis qu’un cross sera dessiné et divisé sur les 4 canvas adjacents. exemple : le chunck 0,0, en rouge sur le dessin A, est un chunck full. le chunck 0,1 est un cross (divisé en 4 : vert, gris, cyan, jaune), chaque quart étant dessiné sur un canvas différent.

    Nom : B.png
Affichages : 164
Taille : 9,0 Ko

    Dans le dessin B, le client a scrollé vers le bas, et est donc passé du chunck 0,0 au chunck -2,2 en visu. J’ai laissé, remplis de blanc, les canvas que le client a supprimé mais en vrai ils sont totalement effacés de la mémoire du client. En foncé, sont les chuncks (ou les quarts de chunck) que le client a déjà dessiné. En clair, sont les chuncks (le serveur ne renvoie que des chuncks complets, pas de quarts) que le client va devoir dessiner, considérant le changement de scroll.

    Jusque là j’espère être clair Parce que je n’avais pas du tout anticipé mon problème, que je n’arrive en fait pas du tout à expliquer : au démarrage du jeu, node lance le serveur, le client se connecte, envoie au serveur qu’il regarde en 0,0, le serveur lui renvoie tous les chuncks de x=-2 à x=2 et de y=-2 à y=2, le client les reçoit, dessine d’abord tous les chuncks full en ajoutant un nouveau canvas au préalable, puis dessine tous les cross. Jusque là tout va bien. En revanche, quand je scroll vers le bas, et regarde le chunck -2,2, si je prends l’exemple de ce chunck -2,2 en particulier (mais c’est valable pour les autres aussi), le client ne devrait avoir à dessiner que les quarts de cross cyan et gris, puisque, quand il regardait en 0,0, le reste de ce canvas était déjà dessiné. Au lieu de ça, une fois que le client a reçu ses chuncks du serveur et les a dessinés, il s’avère que le canvas qui contient le chunck -2,2 est complètement effacé (donc transparent) pour une raison que j’ignore, et ensuite (comme prévu), les deux nouveaux quarts (cyan et gris donc), sont dessinés. Formulé autrement : après un scroll, si le client doit compléter un canvas qui n’était pas entièrement dessiné, le canvas est complètement effacé avant (et c’est bien là mon problème).

    Je précise que le client tient un répertoire des chuncks, et que dans le cas des chuncks cross, il note dans un bitset quels quarts sont dessinés et lesquels ne le sont pas, de sorte à s’économiser à la réception des chuncks.

    Je vous mets quelques fonctions pour que cela soit un peu plus clair :

    // côté serveur : en fin de scroll, le client renvoie un message 'iLookhere' avec sa position et le serveur lui renvoie les chuncks qui vont bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    socket.on('iLookHere', function(msg) // fol
        	    {   
        	        // position actuelle du client : servira à calculer quels chncks le client a déjà, par rapport à la nouvelle position et ce qu'on doit envoyer
        	        let prevPos = world._socketManager._sockets[socket.id].pos;
     
        	        world._socketManager._sockets[socket.id].pos = msg;
     
        	        let i, j;
        	        [i, j] = msg;
     
        	        let packet = [];
     
        	        // pr chaque chunck autour de cx, cy, à 2 de radius
        	        for (let cx=i-2; cx<i+1+2; cx++) {
     
                        for (let cy=j-2; cy<j+1+2; cy++) {
     
                            // si ce chcunk n'était pas dans le scope de previousPos
                            // (et donc n'a pas été envoyé dans la précédene udpte de chuncks envoyée)
                            if (prevPos == undefined || cx < prevPos[0]-2 || cx > prevPos[0]+2 || cy < prevPos[1]-2 || cy > prevPos[1]+2) {
     
                                let obj = {
                                    pos : [cx, cy],
                                    data : {
                                        _ground : [],
                    	                _entities : [],
                                    }
                                };
     
                    	        let ccx = cx * 40;
                    	        let ccy = cy * 40;
     
                                for (let x=0; x<40; x++)
                                    for (let y=0; y<40; y++) 
                                        obj.data._ground.push(world._map[[ccx+x,ccy+y]].ground);
     
                                packet.push(obj);
     
                            }
     
                        }
                    }
     
        	        world._socketManager.send('chunck', packet, [socket.id]);
     
     
        	    });
    // côté client : quand je reçois un message chunck, je crée les canvas si ce sont des full, et dessine sur les canvas :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    world._socket.on('chunck', function(packet) // fol
            	    {
     
                        let cx, cy;
                        [cx, cy] = world.chunckAt(-world._isometric._leftOffset, -world._isometric._topOffset);
     
                        console.log('looking at', cx, cy);
     
                        let cnt = 0;
     
                        // on store les offsets de _isometric parce qu'on va les manipuler dans les boucles
                        let oldLeftOffset = world._isometric._leftOffset;
                        let oldTopOffset = world._isometric._topOffset;
     
     
                        // 1 : on crée les canvas en damier et on dessine les fulls 
                        for (let n=0; n<packet.length; n++) {
     
                            let msg = packet[n];
     
                            // ici, on ne rentre qu'une fois (on ne dessine qu'une fois un full sur un cavnas)
                	        if (world._chuncks[[...msg.pos]]._type === 'full' && world._chuncks[[...msg.pos]]._loaded == false) {
     
     
                    	        world._chuncks[[...msg.pos]]['_canvas'] = document.createElement('canvas');
                    	        world._chuncks[[...msg.pos]]['_entities'] = new Set();
            	                world._chuncks[[...msg.pos]]['_reliefs'] = [];
     
                    	        world._chuncks[[...msg.pos]]._canvas.width = 2400;
                                world._chuncks[[...msg.pos]]._canvas.height = 1200;
     
                    	        world._chuncks[[...msg.pos]]._canvas.style.zIndex = 0;
     
                                world._chuncks[[...msg.pos]]._canvas.style.left = 8 + (40 * (msg.pos[0]+msg.pos[1]) + world._isometric._leftOffset + world._isometric._topOffset) * 30 + "px";
                                world._chuncks[[...msg.pos]]._canvas.style.top = 8 - 585 + (40 * (msg.pos[1]-msg.pos[0]) + world._isometric._topOffset - world._isometric._leftOffset) * 15 + "px";
     
                    	        document.body.appendChild(world._chuncks[[...msg.pos]]._canvas);
     
     
     
                    	        // les fulls
                    	        for (let i=0; i<msg.data._ground.length; i++) // fol
                    	        {
                    	            let top = i % 40;
                    	            let left = (i - top) / 40;
     
                    	            let groundValue = msg.data._ground[i];
     
                    	            // on store les offsets de _isometric
                                    world._isometric._leftOffset = 0;
                                    world._isometric._topOffset = 0;
     
                                    let pos = world._isometric.absoluteToScreen(left, top);
                                    pos.y += 585;
     
                                    world._isometric._leftOffset = oldLeftOffset;
                                    world._isometric._topOffset = oldTopOffset;
     
                    	            if (groundValue.includes('grass')) {
     
                    	                let regExp = /grass\/([0-9]*)/;
                                        let matches = regExp.exec(groundValue);
     
     
                                        world._chuncks[[...msg.pos]]._canvas.getContext('2d').drawImage(world._preloadedImages['grass/'+matches[1]], pos.x, pos.y);
                    	                cnt++;
     
     
                    	            } else {
     
                    	                world._chuncks[[...msg.pos]]._canvas.getContext('2d').drawImage(world._preloadedImages[groundValue], pos.x, pos.y);
                    	                cnt++;
     
                    	            }
     
     
     
     
     
                    	        }
     
                    	        world._chuncks[[...msg.pos]]._loaded = true;
     
     
                	        }  
     
     
     
                        }
     
     
     
                	    // les cross. ici, on peut rentrer pluseurs fois : un cx cy demandera qu'on dessine certaines area, un autre cx cy en demandera d'autres
                	    // 2 : on dessine les cross (mais au moins les canvas existent déjà grace à 1)
                	    for (let n=0; n<packet.length; n++) {
     
                            let msg = packet[n]; // 40x40
     
     
     
                            // 15 = 4 bits chargés (1 bit par area : bit0 = 1, bit2. =2, bit3 = 4..) 1+2+4+8 = 15
                            // si 15, les 4 areas sont dessinées 
                	        if (world._chuncks[[...msg.pos]]._type === 'cross' && world._chuncks[[...msg.pos]]._areaBool != 0b1111) {
     
     
     
                	            if (!world._chuncks[[...msg.pos]].hasOwnProperty('_entities')) {
                    	            world._chuncks[[...msg.pos]]['_entities'] = new Set();
                	                world._chuncks[[...msg.pos]]['_reliefs'] = [];
                	            }
     
                	            let areaBool = world._chuncks[[...msg.pos]]._areaBool;
     
                    	        for (let i=0; i<msg.data._ground.length; i++) // fol
                    	        {
                    	            let top = i % 40;
                    	            let left = (i - top) / 40;
     
                    	            // Where to draw ?? sur un aure chunck, un qui a un cavnas, ça depend de top et left, ils déterminerot sur quel chcnk on dessinera 
     
                    	            // Imaginon un tab 4x4 et xy : 
                    	            // 00 10 20 30 
                    	            // 01 11 21 31
                    	            // 02 12 22 32 
                    	            // 03 13 23 33
     
                    	            // condition a : (x + y < 3) -> donne la moitité nord ouest, sinon sud est (b) -> on prndra 39 au lieu de 3
                    	            // conditin c : (x < y) -> donne la moitié sud ouest, sinon nord est (d)
                    	            // attention au valeurs intermédiares, les <= 
                    	            // les quarts sont déterminés par cmbinaison des tests a et c 
     
                    	            //                 * *
                    	            //             **   |   **
                    	            //    x    **       |       **
                    	            //     **      axd  | bxd       **
                    	            // ** --------------|-------------  **
                    	            //     **      axc  | bxc       **
                    	            //     y   **       |       **
                    	            //             **   |   **
                    	            //                 *|*
     
                    	            // si on affiche que les a = 2, on dessine que sur le top left de chaue sprite. Normal ? 
     
     
                    	            // js pas bloquant et la diff entre full et cros c'est que cross dessine suvvessivement
                    	            // très vite sur diffrents chuncks à chaque icnrementation 
                    	            // peut etre que ça fait bugger le système 
                    	            // refaire la loop pour dessiner en 4 gros coups : 
                    	            // zone 0, 1, 2, 3 
                    	            // au lieu de fare top left et de déterminer 
     
                    	            // non pq mm en dessinan que area 0, 2,2 n'affiche que l'angle 0 et pas le full 
     
     
                    	            /*
                    	            pb : pr les packets cross recus apre!s le gros paquet initial,
                    	            si l'area x d'un cross doit être dessinée dans l'angle d'un full qui est déjà dessiné,
                    	            le full est commlètement erase avant 
                    	            
                    	            */
     
     
                    	            let area = [0,0,0,0]; // un pr chaque quart : N E S W 
     
                    	            area[0] = (left+top<=39) && (top<=left); // a x d
                    	            area[1] = (left+top>=39) && (top<=left); // b x d 
                    	            area[2] = (left+top>=39) && (left<=top); // b x c 
                    	            area[3] = (left+top<=39) && (left<=top); // a x c
     
                    	            // draw : faut il la dessine sur cette area ?
                    	            // delta : chucnk où je dois draw, en delta, par rapport à pos 
                    	            // offset : l'area Est du chunck -1,0 sera dessinée en Ouest sur le chuck 0,0, donc en relatif sur un chunk, on dessine pas au mm endroit
                    	            area[0] = { draw:area[0], delta:{'x':0,'y':-1} }; 
                    	            area[1] = { draw:area[1], delta:{'x':1,'y':0} };
                    	            area[2] = { draw:area[2], delta:{'x':0,'y':1} };
                    	            area[3] = { draw:area[3], delta:{'x':-1,'y':0} };
     
                    	            for (let a=0; a<4; a++) {
     
                    	                // c'est pas sur pos (cross) qu'il faut controler si dessiné, si ??? le _areaBool c'est celi de quel chunk ??
                    	                // si dans notre config, si ce tile doit être dessiné dans la zone a et qu'il n'y est pas déjà dessiné 
                    	                if (area[a].draw == true && (world._chuncks[[...msg.pos]]._areaBool & (1 << a)) == 0) {
     
                    	                    // chcnk sur lequel on va dessiner
                    	                    let drawOn = [msg.pos[0]+area[a].delta.x, msg.pos[1]+area[a].delta.y];
     
                    	                    if (world._chuncks[drawOn] != undefined) {
     
                    	                        // 0 -> 1
                                                // 1 -> 2 
                                                // 2 -> 4
                                                // 3 -> 8
                                                // on réécrit un 1 autant de fois qu'il y a de tile par area
                    	                        areaBool |= (1 << a);
     
                            	                let groundValue = msg.data._ground[i];
     
     
                                                world._isometric._leftOffset = -area[a].delta.x * 40;
                                                world._isometric._topOffset = -area[a].delta.y * 40;
     
                                                let pos = world._isometric.absoluteToScreen(left, top);
                                                pos.y += 585;
     
                                                world._isometric._leftOffset = oldLeftOffset;
                                                world._isometric._topOffset = oldTopOffset;
     
                                	            if (groundValue.includes('grass')) {
     
                                	                let regExp = /grass\/([0-9]*)/;
                                                    let matches = regExp.exec(groundValue);
     
     
     
                                                    world._chuncks[drawOn]._canvas.getContext('2d').drawImage(world._preloadedImages['grass/'+matches[1]], pos.x, pos.y);
     
     
     
                                	            } else {
     
                                	                world._chuncks[drawOn]._canvas.getContext('2d').drawImage(world._preloadedImages[groundValue], pos.x, pos.y);
     
     
     
                                	            }
     
     
     
     
                    	                    }
                    	                }
                    	            }
                    	        }
     
                    	        world._chuncks[[...msg.pos]]._areaBool = areaBool;
     
     
                	        }
            	        }
     
     
            	    });
    // côté client toujours : cette fonction est appelée dès que le client se connecte et après chaque fin de scroll.
    // les chuncks non nécessaires sont supprimés et une fonction détermine à l'avance si le chunck sera de type full ou cross
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    updateArea:function() 
        {
            let cx, cy;
            [cx, cy] = world.chunckAt(-world._isometric._leftOffset, -world._isometric._topOffset);
     
            // si je me déplace de 2 cases (et pas de 2 chunks), peu de chances de changer de chunk en fait 
            if (world._cx == cx && world._cy == cy)
                return;
     
            world._cx = cx;
            world._cy = cy;
     
            // server comprend tout seul qu'il doit envoyer radius 2 autour
            world._socket.emit('iLookHere', world.chunckAt(-world._isometric._leftOffset, -world._isometric._topOffset));
     
            for (let i=cx-world._radius; i<cx+1+world._radius; i++) {
     
                for (let j=cy-world._radius; j<cy+1+world._radius; j++) {
     
                    if (world._chuncks[[i,j]] == undefined) {
                        world._chuncks[[i,j]] = {};
                        if ((i+j) % 2 == 0) {
                            world._chuncks[[i,j]]['_type'] = 'full';
                            world._chuncks[[i,j]]['_loaded'] = false;
                        } else {
                            world._chuncks[[i,j]]['_type'] = 'cross';
                            world._chuncks[[i,j]]['_areaBool'] = 0b0000;
                        }
     
                    }
                }
            }
     
            for (let c in world._chuncks) {
     
                let posX = parseInt(c.split(',')[0]);
                let posY = parseInt(c.split(',')[1]);
     
                // s'il n'ets plus nécessaire
                if (posX < cx-world._radius || posX > cx+world._radius || posY < cy-world._radius || posY > cy+world._radius) {
     
                    // si chunk pas encore chargé (rien de dessiné dessus) -> entites ajouté dans index.js
                    if (!world._chuncks[c].hasOwnProperty('_entities')) {
     
                        // on le release de la mémoire
                        world._chuncks[c] = null;
                        delete world._chuncks[c];
     
                    } else {
     
                        // s'il est chargé et dessiné 
     
                        world._chuncks[c]._entities.forEach((id) => {
                            world._entities[id].destroy();
                            delete world._entities[id];
                        });
     
                        delete world._chuncks[c]._entities;
     
                        // si le chuncks que je supprime est un full 
                        // il affectera areaBool des chuncks voisins qui eux sont en cross 
                        if (world._chuncks[c].hasOwnProperty('_canvas')) {
     
                            //console.log('from', c);
     
                            let c0 = parseInt(c.split(',')[0]);
                            let c1 = parseInt(c.split(',')[1]);
     
                            // chuncks des cross arrounds, dans l'ordre des areas à supprimer 
                            let arrs = [
                                [c0,c1+1], // area 0 à supprimer 
                                [c0-1,c1],
                                [c0,c1-1],
                                [c0+1,c1],
                            ];
     
     
                            for (let a=0; a<4; a++) {
                                if (world._chuncks.hasOwnProperty(arrs[a]))
                                    world._chuncks[arrs[a]]._areaBool &= ~(1 << a);
                            }
     
                            console.log('canvas', c, 'removed');
     
                            document.body.removeChild(world._chuncks[c]._canvas);
                            world._chuncks[c]._canvas = null;
                        }
     
                        world._chuncks[c] = null;
                        delete world._chuncks[c];
                    }
                }
            }
        },
    Voilà c'est peut être pas très bien codé et je m'en excuse, normalement la logique est bonne mais j'ai dû passer à coté de quelque chose
    C'est peut être plus un problème de javascript que de node, mais en même temps je ne suis pas sûr que j'aurais eu ce problèmeen full JS.
    Dernière précision mais pas des moindres : dans la fonction client world._socket.on('chunck'), supprimer les deux lignes "world._chuncks[drawOn]._canvas.getContext('2d').drawImage....." résout plus ou moins le bug : les canvas ne sont plus effacés, en revanche bien sûr les quarts de sont pas complétés.
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  2. #2
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Bonjour,

    Après quelques tests supplémentaires je me rends compte que le bug est présent sur Brave et pas sur Firefox... J'ai donc un début de piste
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  3. #3
    Expert éminent sénior
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 235
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 235
    Points : 15 532
    Points
    15 532
    Par défaut
    si vous avec prévu de faire un jeu grand public, essayez le avec chrome ou chromium.

  4. #4
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Bonjour,

    Le bug est le même sur Chrome, de ce que j'avais compris Brave utilise le même core que Chrome, enfin je ne suis pas un spécialiste des browsers

    Je viens de faire un code minimal, que voici :
    Code html : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    <!DOCTYPE html>
    <html>
        <body>
     
            <canvas id="myCanvas" width="500" height="500"></canvas>
     
     
            <script>
            
                let img = new Image();
            
                function myFunction()
                {
                    let x = Math.random() * 100;
                    let y = Math.random() * 50;
                    
                    document.getElementById('myCanvas').getContext('2d').drawImage(img, x, y);
                }
                
                img.src = 'https://upload.wikimedia.org/wikipedia/commons/d/d5/Japan_small_icon.png';
                
            </script>
     
            <button onclick="myFunction()">Click me</button>
     
     
        </body>
    </html>

    De mon côté, cliquer sur le bouton réaffiche la boule rouge, mais le canvas est complètement effacé avant
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  5. #5
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    16 959
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 16 959
    Points : 44 122
    Points
    44 122
    Par défaut
    Bonjour,
    De mon côté, cliquer sur le bouton réaffiche la boule rouge, mais le canvas est complètement effacé avant
    avec le code que tu présente aucune raison que le contenu du <canvas> s'efface !

    Un raison pour laquelle le contenu d'un <canvas> s'efface est le (re)dimensionnement de celui-ci.

    Par exemple avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ctx.canvas.width = ctx.canvas.width;  // efface le contenu

  6. #6
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Salut,

    Tu prêches un convaincu Pour une fois que je peux dire que le problème vient du browser et pas de moi ça me fait vraiment plaisir lol
    Plus sérieusement, bug présent sur Brave (qui dépend de Chrome) et Chrome bien sûr, mais pas sur les autres navigateurs (Firefox, Edge, Safari).
    Du coup j'ai remonté le bug sur bugs.chromium.org...
    https://bugs.chromium.org/p/chromium...20canvas&can=2
    J'ai testé Chrome 108, pas de bug, j'en déduis que le bug vient d'une MAJ récente, c'est pas de chance.
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

  7. #7
    Membre régulier
    Homme Profil pro
    Développeur du dimanche
    Inscrit en
    Février 2013
    Messages
    154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur du dimanche

    Informations forums :
    Inscription : Février 2013
    Messages : 154
    Points : 105
    Points
    105
    Par défaut
    Bonjour !

    Vu l'aspect du problème j'ai fait quelques recherches pour voir si d'autres gens (non développeurs) avaient des problèmes d'affichage sur Brave/Chrome et mac OSX, sans pour autant qu'ils mettent le mot canvas dessus. C'est bien le cas, a priori le problème est un peu plus vaste que le mien, il touche aussi des services comme la suite google En tous cas une solution a été proposée sur cet autre forum, désactiver l'accélération matérielle. Et ça marche !
    "There should be no boundaries to human endeavor" - Hawking
    Retrouvez moi sur GitHub : https://github.com/JeanLouisMassei

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Affichage du message précédent en début de page
    Par Eusebius dans le forum Mode d'emploi & aide aux nouveaux
    Réponses: 2
    Dernier message: 10/07/2006, 16h35
  2. affichage d'un état à partir d'une page
    Par marceline dans le forum ASP
    Réponses: 2
    Dernier message: 29/06/2006, 13h31
  3. Affichage d'un tableau perl dans une page HTML
    Par Jim_Nastiq dans le forum Web
    Réponses: 7
    Dernier message: 13/04/2006, 11h27
  4. modifier color de scroll d'une page web+horloge[html+javasc]
    Par am.adnane dans le forum Général JavaScript
    Réponses: 1
    Dernier message: 13/12/2005, 14h26
  5. [scrolltop] La hauteur "scrollée" dans une page
    Par pmartin8 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 06/12/2005, 14h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo