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 :

Enlever une image dessinée sur le canvas [API HTML5]


Sujet :

JavaScript

  1. #1
    Membre chevronné
    Avatar de tails
    Homme Profil pro
    Inscrit en
    Novembre 2003
    Messages
    799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 799
    Points : 2 148
    Points
    2 148
    Billets dans le blog
    15
    Par défaut Enlever une image dessinée sur le canvas
    Bonjour Je développe une application (avec l'EDI Intel SDK) principalement pour Mobile android, avec les technologies HTML5/Javascript(/CSS).
    J'ai fait le choix de ne pas utiliser de framework pour l'instant, car je semble m'en sortir sans, voire je m'en sors mieux sans !!! (Par exemple, pour l'utilisation du canvas, j'ai mieux réussi à redimensionner celui-ci à la taille de l'écran sans framework canvas qu'avec !!!).

    J'ai donc créé une classe pour gérer une position du jeu d'échecs : jointe au message.
    Voici un exemple simple d'utilisation (qui est d'ailleurs le test que je réalise actuellement dans mon projet) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // Script de point d'entrée de l'application
    (function() {
        document.addEventListener('DOMContentLoaded', function() {
            var chessBoard = new ChessBoard(document.getElementById("mainCanvas"));
            chessBoard.setPieceAt("b", "E", "1");
            chessBoard.setPieceAt("b", "F", "4");
            chessBoard.setPieceAt("N", "D", "8");
            chessBoard.setPieceAt("_", "D", "8"); // Censé supprimer la pièce de la case d8 (le cavalier blanc).
            chessBoard.setPieceAt("B", "c", "4");
            chessBoard.clearValues(); // Censé retirer toutes les pièces de l'échiquier.
        }, false);
    }());
    Le problème c'est que les fonctions setPieceAt() et clearBoard() ne parviennent pas (telles que je les ai codées bien sûr ) à supprimer/annuler un pièce figurant déjà sur une case donnée.
    Ainsi je n'ai pas réussi à retirer le cavalier en d8 dans un premier temps, ni à enlever toutes les pièces de l'échiquier.

    Je vous remercie d'avance

    N.B : B désigne un fou blanc, b un fou noir. Comment le savoir ? Veuillez jeter un coup d'oeil rapide à la page wikipédia suivante : La notation FEN pour les échecs
    Fichiers attachés Fichiers attachés

  2. #2
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    'clearBoard()' ou 'clearValues()' ?

    Peu importe au final, j'irais plûtot (pas le chien de mickey) regarder 'clearCanvas()', le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    for (currImage in this.drawnImages){
      delete currImage;
    }
    ne fonctionne pas comme tu t'y attends.

    Question qui n'a rien à voir avec ton problème : tu as écris ... = Array(8) et non ... = new Array(8) sais tu pourquoi ?

  3. #3
    Membre chevronné
    Avatar de tails
    Homme Profil pro
    Inscrit en
    Novembre 2003
    Messages
    799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 799
    Points : 2 148
    Points
    2 148
    Billets dans le blog
    15
    Par défaut J'ai trouvé en retravaillant la classe
    Merci pour la réponse, mais le problème ne se situe pas au niveau de tes observations.
    Je ne sais pas si en Javascript écrire Array(8) sans le new est recommandé, mais il se trouve que le problème ne vient pas de là. (Mais plus un quand même pour m'avoir pointé celà Je pense que cela vient du temps où je m'éssayais au Python ... ).

    C'est plus subtil : j'ai ordonné à ma classe de dessiner les images sur leurs évènements "load" => Inapproprié !!!
    Il faut plutôt charger les images auparavant, quitte à utiliser callbacks sur callbacks, mais au moins ça fonctionne.


    J'ai joint la classe chessboard modifiée, et l'utilisation exemple devient la suivante :

    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
     
    (function() {
        document.addEventListener('DOMContentLoaded', function() {
     
            var chessBoard = new ChessBoard(document.getElementById("mainCanvas"), function(){
                chessBoard.setPieceAt("b", "E", "1");
                chessBoard.setPieceAt("b", "F", "4");
                chessBoard.setPieceAt("N", "D", "8");
                chessBoard.setPieceAt("_", "D", "8");
                chessBoard.setPieceAt("B", "c", "4");
     
                //chessBoard.clearValues();
            });
     
        }, false);
    }());
    (Il faut noter ici l'utilisation d'un callback en 2e paramètre).

    Les fonctions publiques de la classe chessboard sont mieux documentées.

    Merci beaucoup pour m'avoir lu et/ou suggéré des solutions
    Fichiers attachés Fichiers attachés

  4. #4
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Citation Envoyé par tails Voir le message
    Je ne sais pas si en Javascript écrire Array(8) sans le new est recommandé
    Bin ... j'en sais rien, ce qui est recommandé, pour moi, c'est de savoir ce qu'on fait Là, pour Array, avec ou sans new c'est pareil. Mais ce n'est pas toujours le cas, avec String par exemple. A mon avis, 'new' permet de distinguer un contexte d'appel d'une fonction, sématiquement j'aime bien la différence entre 'new uneFonction()' et 'uneFonction()' (mais je ne veux pas être accusé de prosélytisme ).

    J'ai pas bien compris le coté inapproprié du dessin sur 'load' et encore moins le rapport avec ton problème initial mais tant que ça fonctionne ...

    Par contre, et sans que ce soit une recommandation, tu utilises pas mal de déclaration de fonctions dans des fonctions. Pour les autres je ne sais pas, mais au moins pour moi ce n'est pas toujours simple à lire et ce n'est surtout pas nécessaire. Tu lies 'outer' à 'this' pour pouvoir l'utiliser dans des clôtures (je n'ai pas vu d'autres variables prises dans la cloture), mis à part dans tes gestionnaires d'évènements c'est inutile. Tu peux remplacer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    this.uneFonction = function(...) {
      var outer = this;
      var uneFonctionInterne = function(...) {
        outer.uneMéthode(...);
      }
    }
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function uneFonctionInterne (...) {
      this.uneMéthode(...);
    }
    this.uneFonction = function(...) {
      uneFonctionInterne.call(this, ...);
    }
    ou encore

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    function uneFonctionInterne (that, ...) {
      that.uneMéthode(...);
    }
    this.uneFonction = function(...) {
      uneFonctionInterne(this, ...);
    }
    Moins d'imbrication de code, plus clair. Et tu ne recrées pas une fonction à chaque valeur différente de 'this'.

    Autre chose (j'essaye de justifier mon point!), tu définis tes méthodes lors de la création de ton instance (dans le constructeur). C'est pas gravé dans le marbre, mais on a plûtot l'habitude de les partager au travers du 'prototype'. C'est à dire de passer de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    var Chessboard = function (...) {
      ...
      this.uneMethode = function (....) {
        ...
      };
      ...
    };
    à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var Chessboard = function (...) {
      ...
    };
    Chessboard.prototype.uneMethode = function (...) {
    };
    Et puis si tu ne l'as pas déjà fait : un peu de lecture et un test

  5. #5
    Membre chevronné
    Avatar de tails
    Homme Profil pro
    Inscrit en
    Novembre 2003
    Messages
    799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 799
    Points : 2 148
    Points
    2 148
    Billets dans le blog
    15
    Par défaut
    Merci beaucoup pour les conseils techniques (je suis d'ordinaire beaucoup plus habitué à Java).
    Je vais tâcher de lire l'article sur lequel tu m'as passé le lien dès maintenant : il a l'air vraiment pas mal et semble être d'une simplicité que j'ai toujours recherchée concernant les tutos sur la programmation fonctionnelle en Javascript

  6. #6
    Membre chevronné
    Avatar de tails
    Homme Profil pro
    Inscrit en
    Novembre 2003
    Messages
    799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 799
    Points : 2 148
    Points
    2 148
    Billets dans le blog
    15
    Par défaut
    Bonjour, après avoir lu de la doc sur Javascript (EloquentJavascript, disponible en ebook gratuit), j'ai relu les recommandations qui m'ont été adressées dans les précédents postes :

    • Pour la définition des méthodes en passant par le prototype : ok, j'ai compris et je me sens apte à y recourir.
    • C'est pour le premier point, utilisation de la méthode call, que cela ne me semble pas clair : en effet, je préfère pour l'instant ma méthode, car au moins les fonctions restent locales/internes et donc privées. Ai-je tort ?

  7. #7
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Citation Envoyé par tails Voir le message
    les fonctions restent locales/internes et donc privées. Ai-je tort ?
    Bin ... oui et non. Pour moi, il n'y a aucune notion de privé, public, protected, friend et autres mots-clefs définissant la visibilité, en Javascript. Je trouve que cela embrouille plus qu'autre chose. Ok pour locales/internes.

    Si tu es plus à l'aise avec ta méthode, continue. Tu évolueras dans ta façon de coder avec ta connaissance du langage.

    Simplement, ce que tu fais s'appelle une cloture, c'est une fonction qui capture ta variable 'outer'. Pour chaque valeur différente de 'outer' tu vas générer une fonction différente. Dans ton cas particulier, l'importance est toute relative puisqu'a priori tu ne vas pas créer plusieurs 'Chessboard' dans le même code. Mais, si c'était le cas, alors il vaudrait mieux, à mon avis, passer par une autre méthode. Et ce, dans la mesure où ta cloture n'est pas nécessaire.

    Pour conserver, tes fonctions locales/internes tu peux encapsuler la définition de ton objet Chessboard dans une fonction, un peu comme ça
    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
    var Chessboard = (function(){
      function Chessboard () {
        ...
      }
     
      function uneMéthodeInterne ( arg0, arg1 ) {
        this.uneMéthodeQuelconque(...);
      }
     
      function uneFonctionInterne ( that, arg0, arg1 ) {
        that.uneMéthodeQuelconque(...);
      }
     
      Chessboard.prototype.uneMéthode = function( ... ) {
        uneMéthodeInterne.call(this, arg0, arg1);
        uneFonctionInterne(this, arg0,arg1);
      };
     
      return Chessboard;
    })()
    'uneMéthodeInterne' et 'uneFonctionInterne' n'existent pas en dehors de leur portée de définition déclaration, c'est à dire la '(function(){ ... })()' qui les englobe. D'ailleurs 'Chessboard' non plus c'est pour ça qu'il faut la retourner et l'affecter à une variable définie à l'extérieur.

    Que fait '.call' ? Elle te permet de spécifier quel sera la valeur de 'this' que tu utiliseras dans ta méthode. Tu peux voir la différence dans les arguments reçus par 'uneMéthodeInterne' et 'uneFonctionInterne'. Dans les deux cas, à l'appel tu passes 'this', mais dans 'uneMethodeInterne', il ne fait pas partie de la liste des arguments. L'une ou l'autre de ces formes te permet d'éviter une cloture qui n'est pas nécessaire.

    Il faut faire attention au fait que 'this' est toujours défini. S'il ne l'a pas été au moment de l'appel avec 'unObjet.uneMéthode()' ou 'uneMéthode.call(unObjet)', sa valeur sera celle de l'objet global, donc 'uneFonction()' est équivalent à l'appel '<global>.uneFonction()'. Il faut donc être attentif, lors d'un appel de fonction sans préciser de contexte pour 'this', à l'utilisation qui est faite de 'this' dans le corps de la fonction. Le risque étant de modifier sans le vouloir des propriétés de l'objet global.

    NB: avec 'uneFonctionInterne' on passe 'this' comme argument 'that' utilisé dans la fonction. Dans la fonction, 'this' est quand même défini avec pour valeur l'objet global.
    Et puis lire, essayer, lire, ess...

  8. #8
    Membre chevronné
    Avatar de tails
    Homme Profil pro
    Inscrit en
    Novembre 2003
    Messages
    799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 799
    Points : 2 148
    Points
    2 148
    Billets dans le blog
    15
    Par défaut C'est déjà plus clair
    Merci, ça commence à devenir plus clair pour moi.

    Si tu veux, j'avais déjà appréhendé le concept de cloture : c'est juste que cela me paraissait plus compliqué en Javascript. J'ai bien noté, que le fait de capturer une variable extérieure à la fonction risque de poser problème si j'ai plusieurs instances de ChessBoard, ce qui est probable au fur et à mesure que je ferais évoluer mon application (l'affichage du plateau n'en est pas la finalité : je dirais même que je compte passer auparavant par un explorateur de fichiers, que je devrais coder).

    J'avais aussi vu rapidement les fonctions call/apply/bind, sans vraiment avoir bien compris, mais avec ton explication cela semble s'éclaircir. Enfin je connais aussi le procédé (function(){})() permettant de créer et éxécuter une fonction anonyme en suivant, mais je l'avais oublié.

    L'essentiel, c'est que je vois mieux comment réduire la visibilité des fonctions/variables inutiles pour l'utilisateur final (encapsulation), tout en respectant les conseils relatifs aux clotures.

    J'aurais bien voulu te proposer la lecture de mes sources javascript pour que tu me confirme/infirme les bonnes ou mauvaises pratiques (mon projet est open source), le problème est qu'il commence déjà à "grossir" en terme de volume de code : j'ai déjà 3 classes personnelles, en plus du fichier internationalisation. Mais si tu veux je peux poster le lien vers la forge Bitbucket du projet (pour des raisons pratiques compliquées à expliquer, je n'ai pas chosit GitHib). Sachant tout de même que pour l'instant, je dois toutes les refactoriser pour tenir compte de tes remarques sur les clotures.

    Merci

  9. #9
    Membre averti
    Profil pro
    à la bougie alors
    Inscrit en
    Mai 2006
    Messages
    224
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : à la bougie alors

    Informations forums :
    Inscription : Mai 2006
    Messages : 224
    Points : 362
    Points
    362
    Par défaut
    Mm ...

    Si tu te poses des questions sur les bonnes ou mauvaises pratiques ou comment coder telle ou telle fonctionnalité, pose des questions, tu auras plein de réponses ! Et peut-être même trés différentes
    Il y a aussi beacoup d'articles, d'avis à lire sur ce site, par exemple http://www.developpez.net/forums/d11...ux-javascript/, ou http://www.developpez.net/forums/d14...aise-pratique/ bref des angles de vues instructifs. Il faut fouiller et se faire une idée avant de refactoriser son code.
    Ah et les classes n'existent pas en Javascript ... enfin à mon avis

  10. #10
    Membre chevronné
    Avatar de tails
    Homme Profil pro
    Inscrit en
    Novembre 2003
    Messages
    799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations forums :
    Inscription : Novembre 2003
    Messages : 799
    Points : 2 148
    Points
    2 148
    Billets dans le blog
    15
    Par défaut
    Merci pour ces liens, en regardant dans la section Javascript du site, je n'y était pas parvenu : je tâcherais au moins de lire les 3 fondamentaux.
    Il est vrai qu'en Javascript, il y a des objets, mais pas de classe : c'est que c'est encore difficile pour moi à concevoir, venant du monde Java.

    Pour le refactoring, je l'ai déjà fait, mais je pense que l'essentiel est que j'ai réussi à encapsuler méthodes et propriétés, en évitant de polluer la portée globale.

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

Discussions similaires

  1. Dessin sur un canvas dans une DLL
    Par colorid dans le forum Langage
    Réponses: 1
    Dernier message: 07/03/2009, 15h09
  2. Chargement d'une image BMP sur 24 bits
    Par kj_83 dans le forum C++Builder
    Réponses: 3
    Dernier message: 26/12/2006, 20h32
  3. [Tkinter] Insérer une image jpg sur un canvas avec PIL
    Par Kyojimbo dans le forum Tkinter
    Réponses: 2
    Dernier message: 23/02/2006, 17h46
  4. Appeler une image faite sur 3DS Max ??
    Par CCin dans le forum OpenGL
    Réponses: 4
    Dernier message: 24/10/2005, 11h41
  5. [Servlet] [Image] Dessiner sur une image
    Par gaia_dev dans le forum 2D
    Réponses: 5
    Dernier message: 01/09/2004, 18h11

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