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

JavaScript Discussion :

Créer une map pixel par pixel


Sujet :

JavaScript

  1. #1
    Membre du Club
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 194
    Points : 45
    Points
    45
    Par défaut Créer une map pixel par pixel
    Bonjour,
    j'aimerais créer une map un peut comme celle si: http://mineatlas.com/?levelName=Rand...58781385609764, mais je ne sais pas comment le site fait.
    Actuellement j'ai essayé en canvas et ça rame trop car je dois générer chaque case et je peux pas zommé sans recréer l'image. Normalement je peux déplacer la map mais comme ça rame je peux pas^^. Donc c'est vraiment pas bon.
    Le code pour chaque case que j'utilise:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	canvas.drawRect({
    		layer: true,
    		draggable: true,
    		fromCenter: false,
    		groups: ['shapes'],
    		dragGroups: ['shapes'],
    		fillStyle: "<?=$listeBiome[$biomeName];?>",
    		strokeStyle: "#000",
    		strokeWidth: 0,
    		x: <?=(($x-$tailleBloc)*$tailleBloc);?>, y: <?=(($z-$tailleBloc)*$tailleBloc);?>,
    		width: <?=$tailleBloc;?>, height: <?=$tailleBloc;?>
    	});
    Comment je pourrais faire ? car j'ai vraiment aucune idée.

  2. #2
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Salut,
    Citation Envoyé par Lprofessionnelle
    je peux pas zommé sans recréer l'image
    connais-tu la méthode .toDataURL() ? Elle te permet de faire un cliché du canevas. Tu peux ensuite réutiliser ce cliché avec .drawImage() plutôt que de redessiner les pixels à chaque fois.

    Voici un exemple :
    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
    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
    <!DOCTYPE html>
    <html lang="fr">
    <head>
      <meta charset="utf-8" />
      <title>Génération carte canvas</title>
      <style>
     
      body {
        background: black;
        color: white;
        font: 16px/120% sans-serif;
      }
      canvas {
        outline: dashed 1px cyan;
      }
     
      </style>
    </head>
    <body>
     
    <canvas width="400" height="300">
      Pas de canevas ?
    </canvas>
    <p>Essayez de zoomer sur le canevas. Quelques infos sont affichées dans la console (<kbd>F12</kbd>).</p>
     
    <script>
     
    "use strict"; // voir https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Strict_mode
     
    // constantes à ajuster selon l’envie
    const BLOCK_SIZE = 2;
    const MAX_ZOOM = 10;
    const ZOOM_SPEED = 0.25;
     
    const $canvas = document.querySelector("canvas");
    const cx = $canvas.getContext("2d");
    const w = $canvas.width;
    const h = $canvas.height;
     
    let zoomLevel = 1;
     
    const arrayToCSSColor = ([ red, green, blue ]) => {
      const sRed   = (red   < 16 ? "0" : "") + red.toString(16);
      const sGreen = (green < 16 ? "0" : "") + green.toString(16);
      const sBlue  = (blue  < 16 ? "0" : "") + blue.toString(16);
      return "#" + sRed + sGreen + sBlue;
    };
     
    const pickRandomColor = () => {
      return [ null, null, null ].map(() => Math.floor(256 * Math.random()));
    };
     
    // choisit 3 couleurs de base au hasard
    const baseColors = [ pickRandomColor(), pickRandomColor(), pickRandomColor() ];
     
    // génération de la carte dans un canevas hors-écran
    // on doit générer en zoom maximal pour éviter un effet « flou » lors des agrandissements
    const bigW = w * MAX_ZOOM;
    const bigH = h * MAX_ZOOM;
    const bigBlockSize = BLOCK_SIZE * MAX_ZOOM;
     
    const $offscreen = document.createElement("canvas");
    const offscreenCx = $offscreen.getContext("2d");
    $offscreen.width = bigW;
    $offscreen.height = bigH;
     
    for (let y = 0; y < bigH; y += bigBlockSize) {
      for (let x = 0; x < bigW; x += bigBlockSize) {
        // choisit une des 3 couleurs de base
        const pixelColor = baseColors[ Math.floor(baseColors.length * Math.random()) ];
     
        offscreenCx.fillStyle = arrayToCSSColor(pixelColor);
        offscreenCx.fillRect(x, y, bigBlockSize, bigBlockSize);
      }
    }
     
    const drawMap = () => {
      cx.clearRect(0, 0, w, h);
      cx.drawImage( // https://developer.mozilla.org/fr/docs/Web/API/CanvasRenderingContext2D/drawImage
        /* image    */ $snapshot,
        /* sx       */ 0,
        /* sy       */ 0,
        /* sLargeur */ bigW / zoomLevel,
        /* sHauteur */ bigH / zoomLevel,
        /* dx       */ 0,
        /* dy       */ 0,
        /* dLargeur */ w,
        /* dHauteur */ h
      );
    };
     
    // prépare une image pour sauvegarder un cliché du canvas hors-écran
    const $snapshot = new Image();
     
    // même avec une URL data:, l’image met un certain temps à charger
    // il faut donc utiliser son évènement onload
    $snapshot.onload = () => {
      console.log("snapshot loaded");
     
      // dessin initial du canevas visible
      drawMap();
    }
     
    // prend le cliché
    $snapshot.src = $offscreen.toDataURL();
     
    // écoute les évènements de « zoom » sur le canevas
    $canvas.addEventListener("wheel", (event) => {
      console.log("deltaY =", event.deltaY);
      if (event.deltaY > 0) {
        if (zoomLevel > 1) zoomLevel -= ZOOM_SPEED;
        else               zoomLevel = 1;
      }
      else {
        if (zoomLevel < MAX_ZOOM) zoomLevel += ZOOM_SPEED;
        else                      zoomLevel = MAX_ZOOM;
      }
      console.log("zoomLevel =", zoomLevel);
     
      drawMap();
    });
     
    </script>
    </body>
    </html>
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  3. #3
    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,
    mais je ne sais pas comment le site fait.
    visiblement le site utilise la bibliothèque Leaflet, regarde ces deux exemples sur Leaflet Tutorials

  4. #4
    Membre du Club
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 194
    Points : 45
    Points
    45
    Par défaut
    Citation Envoyé par Watilin Voir le message
    connais-tu la méthode .toDataURL() ? Elle te permet de faire un cliché du canevas. Tu peux ensuite réutiliser ce cliché avec .drawImage() plutôt que de redessiner les pixels à chaque fois.
    Je vois pas en quoi faire "un cliché du canevas" me parait peut utile dans ce qu'a, car la position de chaque coin de bloc est importante en fonction de la taille choisit et donc si je zoom le coin est décaler et je dois donc tout recalculer ou alors j'ai mal comprit. Moi j'utilise la lib https://projects.calebevans.me/jcanvas/


    NoSmoking: merci je vais regarder ça aussi

    Merci pour vos réponse je vais continuer a regarder ça, j'ai bien cru devoir abandonner

  5. #5
    Expert éminent
    Avatar de Watilin
    Homme Profil pro
    En recherche d'emploi
    Inscrit en
    Juin 2010
    Messages
    3 093
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : En recherche d'emploi

    Informations forums :
    Inscription : Juin 2010
    Messages : 3 093
    Points : 6 754
    Points
    6 754
    Par défaut
    Citation Envoyé par Lprofessionnelle Voir le message
    Je vois pas en quoi faire "un cliché du canevas" me parait peut utile dans ce qu'a
    L’intérêt du cliché est que le navigateur ne va pas recalculer tous les dessins à faire à chaque fois, l’image est déjà produite et on peut la réutiliser à l’infini.

    Citation Envoyé par Lprofessionnelle Voir le message
    car la position de chaque coin de bloc est importante en fonction de la taille choisit et donc si je zoom le coin est décaler et je dois donc tout recalculer ou alors j'ai mal comprit.
    J’ai voulu rester simple dans mon exemple et je n’ai pas codé la gestion de la position du curseur lors du zoom, mais c’est tout à fait faisable.

    Citation Envoyé par Lprofessionnelle Voir le message
    Ce n’est pas incompatible, au contraire. Tu peux toujours utiliser la lib pour produire l’image initiale, en zoom maximal, et ensuite tu fais un cliché de cette image initiale
    La FAQ JavaScript – Les cours JavaScript
    Touche F12 = la console → l’outil indispensable pour développer en JavaScript !

  6. #6
    Membre du Club
    Homme Profil pro
    Employé magasin
    Inscrit en
    Août 2012
    Messages
    194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Employé magasin

    Informations forums :
    Inscription : Août 2012
    Messages : 194
    Points : 45
    Points
    45
    Par défaut
    Encore moi.

    J'ai du mal avec le calcul des coordonnées, code de test:

    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
    		var bounds4 = [[5, 2], [4, 3]]; // BLEU
    		var bounds3 = [[3, 2], [4, 3]]; // JAUNE
    		var bounds1 = [[2, 2], [3, 3]]; // ROUGE
     
    		var bounds2 = [[2, 1], [3, 2]]; // BLANC
    		var bounds5 = [[4, 1], [3, 2]]; // BLEU CLAIR
     
    		var bounds0 = [[0, 0], [1, 1]]; // NOIR
     
    // create an orange rectangle
    L.rectangle(bounds4, {color: "#0000FF", weight: 1}).addTo(map); // BLEU
    L.rectangle(bounds3, {color: "#FFFF00", weight: 1}).addTo(map); // JAUNE
    L.rectangle(bounds1, {color: "#FF0000", weight: 1}).addTo(map); // ROUGE
     
    L.rectangle(bounds2, {color: "#FFFFFF", weight: 1}).addTo(map); // BLANC
    L.rectangle(bounds5, {color: "#00FFFF", weight: 1}).addTo(map); // BLEU CLAIR
     
    L.rectangle(bounds0, {color: "#000000", weight: 1}).addTo(map); // NOIR
    Résultat:
    Nom : map.png
Affichages : 202
Taille : 4,9 Ko

    Avec JCanvas j'ai juste a calculer le coin supérieur gauche et je donne la taille du carré/rectangle, mais la je n'y arrive pas. Quelqu'un peut m'éclairé, je suis pas fort avec l'anglais.
    Donc comme tu as dit Watilin Watilin il faudrait limite que je crée l'image avec JCanvas et que je la transmette a l'autre si on peut, il a cette méthode, https://projects.calebevans.me/jcanv...etCanvasImage/ mais pas réussi

  7. #7
    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
    J'ai du mal avec le calcul des coordonnées
    Le positionnement est en coordonnées cartésienne, le [0,0] en bas à gauche SW-NE, il te faut transposer les valeurs Y.

    Tu peux le faire en utilisant une L.transformation ou via une fonction d'affichage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    function setRectangle(map, rect, option) {
      // rect => [[bottom, left], [top, right]]
      const pSW = rect[0].slice(0);
      const pNE = rect[1].slice(0);
      pSW[0] = canvasSize.height - pSW[0];
      pNE[0] = canvasSize.height - pNE[0];
      const layer = L.rectangle([pSW, pNE], option || {}).addTo(map);
      return layer;
    }
    Exemple pour voir l'approche :
    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
    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
    <!DOCTYPE HTML>
    <html lang="fr">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Leaflet CRS.Simple</title>
    <meta name="Author" content="NoSmoking">
    <meta name="DVP-discussion" content="d2017643">
    <link href="https://unpkg.com/leaflet@1.5.1/dist/leaflet.css" rel="stylesheet">
    <script src="https://unpkg.com/leaflet@1.5.1/dist/leaflet.js"></script>
    <style>
    #div-map {
      width: 800px;
      height: 600px;
      margin: 1em auto;
      border: 1px solid #069;
      background: #FFF;
    }
    </style>
    </head>
    <body>
      <h1>Leaflet: L.CRS.Simple</h1>
      <div id="div-map"></div>
    <script>
    // taille canvas souhaité
    const canvasSize = {
      width: 10,
      height: 8
    }
    // création limites
    const mapBounds = [ [0,0], [canvasSize.height, canvasSize.width]];
    const oMap = L.map("div-map", {
        zoomSnap: 0.1,             // permet un zoom plus précis
        crs: L.CRS.Simple
      });
    oMap.fitBounds(mapBounds);
     
    ////////////////////////////
    function setRectangle(map, rect, option) {
      // rect => [[bottom, left], [top, right]]
      const pSW = rect[0].slice(0);
      const pNE = rect[1].slice(0);
      pSW[0] = canvasSize.height - pSW[0];
      pNE[0] = canvasSize.height - pNE[0];
      const layer = L.rectangle([pSW, pNE], option || {}).addTo(map);
      return layer;
    }
    const data = [{
        bound: mapBounds,
        option: { color: "#89A", weight: 0}
      },
      {
        bound: [[0, 0], [1, 1]],
        option: { color: "#000", weight: 1}
      },
      {
        bound: [[2, 2], [3, 3]],
        option: { color: "#F00", weight: 1}
      },
      {
        bound: [[2, 1], [3, 2]],
        option: { color: "#FFF", weight: 1}
      },
      {
        bound: [[3, 2], [4, 3]],
        option: { color: "#FF0", weight: 1}
      },
      {
        bound: [[5, 2], [4, 3]],
        option: { color: "#00F", weight: 1}
      },
      {
        bound: [[4, 1], [3, 2]],
        option: { color: "#0FF", weight: 1}
      }
    ];
    /* coordonnées cartésiennes
    data.forEach(function (el) {
      L.rectangle(el.bound, el.option).addTo(oMap);
    });
    /*--*/
    data.forEach(function (el) {
      setRectangle(oMap, el.bound, el.option);
    });
    </script>
    </body>
    </html>

Discussions similaires

  1. créer une map ordonée
    Par xduris dans le forum Collection et Stream
    Réponses: 4
    Dernier message: 11/08/2008, 13h59
  2. Créer une map avec un type comme clé
    Par mister3957 dans le forum C++
    Réponses: 14
    Dernier message: 26/06/2008, 20h45
  3. Créer une table accessible par tous
    Par Wilgard dans le forum Administration
    Réponses: 2
    Dernier message: 19/06/2007, 10h45
  4. [c#] Comment créer une icone reconnaisable par VS2005
    Par padodanle51 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 10/04/2006, 11h44
  5. [Interbase]Comment créer une source ODBC par programme ?
    Par touhami dans le forum Bases de données
    Réponses: 1
    Dernier message: 13/03/2006, 16h40

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