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 :

Journal de bord de création d'une application de dessin


Sujet :

JavaScript

  1. #1
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut Journal de bord de création d'une application de dessin
    Journal de bord: création d’une application de création de schéma en HTML5: Jour 1

    Introduction
    Depuis quelques temps déjà j’ai besoin de créer des schémas, si possible interactif.
    Principalement des schémas d’architecture avec des serveurs, des bases de données ainsi que des liens entre eux.

    Avec le développement des derniers jeux RTS et Bomberman en HTML5, j’ai appris à utiliser les canvas.

    Je viens donc vous présenter ici l’application sur laquelle je travaille en ce moment: MkDraw.

    Présentation fonctionnelle de l’application
    Cette application, basée sur le mkframework, permet de créer des schémas si besoin interactif.
    Vous pouvez actuellement:
    • gérer des calques
    • afficher/cacher des calques/objets
    • créer des rectangles, lignes, flèches et bases de données
    • créer des liens entre certains éléments
    • placer des éléments de manière fixe ou relative (comme un aimant)
    • définir une couleur de fond, de bord ainsi que son épaisseur
    • écrire un texte sur un rectangle/base de données
    • créer une infobulle (avec html si besoin)
    • enregistrer votre schéma


    Présentation technique
    Dans cette application, je créé autant de canvas que de calques, chaque objet ajouté sur la map est un objet javascript.
    Chaque objet est une instanciation de la classe Data dans le fichier public/js/data.js
    Le constructeur:

    Code javascript : 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
    function Data(type,idLayer){
        this.type=type;
        this.idLayer=idLayer;
        this.x;
        this.y;
        this.x2;
        this.y2;
     
        this.texte='';
        this.id=oApplication.idObject;
        this.size=11;
        this.visible=1;
     
        this.fillStyle='#ffffff';
        this.lineWidth=2;
        this.strokeStyle='#000000';
     
        this.from;
        this.to;
     
        this.comment='comment';
     
        this.info='';
     
        this.relativeObject='';
     
        this.relativeX=0;
        this.relativeY=0;
     
        this.points='';
     
        oApplication.tObject[this.id]=this;
     
        oApplication.idObject++;
     
        if(!oApplication.tMenuLayerObject[idLayer]){
            oApplication.tMenuLayerObject[idLayer]=Array();
        }
     
     
        oApplication.tMenuLayerObject[idLayer].unshift(this.id);
     
     
    }
    Dans ce constructeur, on définit les variables par défaut, incrément l’id général et on ajoute le nouvel objet en début de tableau d’objet.
    Au moment de dessiner un objet sur la map, on appelle la méthode build() de l’objet:
    Code javascript : 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
    Data.prototype={
        build:function(){
     
            if(this.relativeObject!=''){
                var tmpRelativeObject=oApplication.getObject(this.relativeObject);
                if(tmpRelativeObject){
                    this.x=this.relativeX+tmpRelativeObject.x;
                    this.y=this.relativeY+tmpRelativeObject.y;
                }
            }
     
            if(this.type=='carre'){
                oApplication.tLayer[this.idLayer].drawRect(this.x,this.y,this.width,this.height,this.lineWidth,this.strokeStyle,this.fillStyle);
                oApplication.tLayer[this.idLayer].fillText(this.x+10,this.y+10,this.texte,this.strokeStyle,this.size);
            }else if(this.type=='texte'){
                oApplication.tLayer[this.idLayer].fillText(this.x,this.y,this.texte,this.strokeStyle,this.size);
            }else if(this.type=='ligne'){
                oApplication.tLayer[this.idLayer].line(this.x,this.y,this.x2,this.y2,this.strokeStyle,this.lineWidth);
            }else if(this.type=='fleche'){
                oApplication.tLayer[this.idLayer].arrow(this.x,this.y,this.x2,this.y2,this.strokeStyle,this.lineWidth);
            }else if(this.type=='bdd'){
                oApplication.tLayer[this.idLayer].drawBdd(this.x,this.y,this.width,this.height,this.lineWidth,this.strokeStyle,this.fillStyle);
                oApplication.tLayer[this.idLayer].fillText(this.x+10,this.y+30,this.texte,this.strokeStyle,this.size);
            }else if(this.type=='link'){
     
                var oFrom=oApplication.getObject(this.from);
                var oTo=oApplication.getObject(this.to);
                console.log('build link from:'+this.from+' to:'+this.to);
     
                if(!oFrom || !oTo){
                }else if(this.points!=''){
                    oApplication.tLayer[this.idLayer].linkPoint(oFrom,oTo,this.points,this.strokeStyle,this.lineWidth);
                }else{
                    console.log('oFrom et oTo'+oFrom+' '+oTo);
                    oApplication.tLayer[this.idLayer].link(oFrom,oTo,this.strokeStyle,this.lineWidth);
     
                }
            }
     
            this.updateInfo();
        },

    La suite dans le bilet: http://blog.developpez.com/ducodeetdulibre/
    Images attachées Images attachées  

  2. #2
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Bonjour,

    Une question me taraude : puisque vous parlez de gérer différents calques ainsi que d'apporter des fonctions d'interactivité, le tout avec un code très orienté objet, pourquoi ne pas avoir opté pour SVG plutôt que canvas ? Il me semble que la techno se prête davantage à la réalisation de schémas interactifs comparé au canvas qui offre plus des fonctions de "dessin" à proprement parler.

  3. #3
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut
    Pour plusieurs raisons j'ai choisi les cancas plutot que le svg
    • Possibilité de dessiner des images
    • Capitaliser sur les librairies developpées pour les 2 derniers jeux
    • Je connais canvas, je connais peu svg

    D'ailleurs c'est possible de faire la même chose en svg ?
    Comment gerer les différents calques ? (avec les différents plans)

  4. #4
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Je vous suggère de vous y intéresser par la suite, car les possibilités sont très nombreuses :
    http://snapsvg.io/
    http://bonsaijs.org/
    http://d3js.org/

    Pour faire simple, canvas = bitmap et SVG = vectoriel.

    Gérer les calques en SVG est très simple, on définit des groupes d'éléments <g> et ils seront affichés dans l'ordre dans lequel ils sont déclarés, un peu comme si l'on posait un à un des éléments sur une feuille de papier. De la même façon gérer l'interactivité est un jeu d'enfant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <circle onclick="mafonction(evt)" cx="300" cy="225" r="100" fill="red"/>
    http://www.w3.org/TR/SVG/images/script/script01.svg

    Effectivement si vous êtes amenés à manipuler des images ou des sprites, canvas est plus approprié. Mais ce n'est pas ce qui m'est venu à l'esprit en premier pour un schéma interactif

  5. #5
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut
    Merci pour ces informations, j'y jetterai un coup d'oeil (peut etre pour un fork vectoriel

    QUand je dis que le schema doit etre interactif c'est assez limité, je veux 2 choses
    1. permettre de mettre des infobulle sur certains elements
    2. pouvoir sur ces infobulles mettre un lien vers la doc associé (doc d'un serveur par exemple)
    3. permettre via des liens de faire des cartes avec des zones "zoomable" pour avoir plus de détail (qui switcherai entre un shema macro et le shema detaillé d'un serveur par exemple)

    Et ces 3 choses sont possible avec la version actuelle

  6. #6
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut Journal de bord: création d’une application de création de schéma en HTML5: Jour 2
    Introduction
    Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-1

    Dans ce billet je vais un peu plus expliquer comment fonctionne l’application, puis dans un second temps j’indiquerai les modifications du jour.

    Les calques
    L’application à la manière d’un photoshop/inkscape ou Gimp gère les calques: il y a un bouton pour ajouter des calques qui fait appel à la méthode addLayer de la classe application
    Dans le fichier public/js/application.js
    Code javascript : 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
    addLayer:function(){
        this.addMenuLayer(this.idLayer);
     
        var sCanvas='';
     
        this.addContent('tCanvas',sCanvas);
     
     
        this.tLayer[this.idLayer]=new Canvas('canvas_'+this.idLayer);
     
        this.tLayer[this.idLayer].fillText(0,0,'Nouveau calque '+this.idLayer,'#000');
     
        this.selectLayer(this.idLayer);
     
        this.idLayer++;
    },

    Cette méthode créé un canvas sur la page + instancie un objet Canvas puis le stoque dans un tableau indexé par un id pour que l’on puisse interagir par la suite à chaque calque.
    Puis le selectionne, pour que l’on puisse facilement lui ajouter des éléments

    Pour information la classe Canvas se situe dans public/js/canvas.js elle permet de simplifier le dessin sur le canvas.

    Les calques objets
    Plutot que de dessiner simplement sur le canvas, comme on le ferait sur paint, l’idée est de créer des objets que l’on dessine sur les calques afin de pouvoir les modifier individuellement par la suite.
    Pour cela, à chaque fois que l’on dessine un élement, on instancie un objet en utilisant la classe Data ( et en lui indiquant son calque).
    Puis on lui demande de se dessiner sur le calque en appelant sa méthode build
    Fichier public/js/data.js
    Code javascript : 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
    build:function(){
     
            if(this.relativeObject!=''){
                var tmpRelativeObject=oApplication.getObject(this.relativeObject);
                if(tmpRelativeObject){
                    this.x=this.relativeX+tmpRelativeObject.x;
                    this.y=this.relativeY+tmpRelativeObject.y;
                }
            }
     
            if(this.type=='carre'){
                oApplication.tLayer[this.idLayer].drawRect(this.x,this.y,this.width,this.height,this.lineWidth,this.strokeStyle,this.fillStyle);
                oApplication.tLayer[this.idLayer].fillText(this.x+10,this.y+10,this.texte,this.strokeStyle,this.size);
            }else if(this.type=='texte'){
                oApplication.tLayer[this.idLayer].fillText(this.x,this.y,this.texte,this.strokeStyle,this.size);
            }else if(this.type=='ligne'){
                oApplication.tLayer[this.idLayer].line(this.x,this.y,this.x2,this.y2,this.strokeStyle,this.lineWidth);
            }else if(this.type=='fleche'){
                oApplication.tLayer[this.idLayer].arrow(this.x,this.y,this.x2,this.y2,this.strokeStyle,this.lineWidth);
            }else if(this.type=='bdd'){
                oApplication.tLayer[this.idLayer].drawBdd(this.x,this.y,this.width,this.height,this.lineWidth,this.strokeStyle,this.fillStyle);
                oApplication.tLayer[this.idLayer].fillText(this.x+10,this.y+30,this.texte,this.strokeStyle,this.size);
            }else if(this.type=='link'){
     
                var oFrom=oApplication.getObject(this.from);
                var oTo=oApplication.getObject(this.to);
                console.log('build link from:'+this.from+' to:'+this.to);
     
                if(!oFrom || !oTo){
                }else if(this.points!=''){
                    if(oApplication.pointIdSelected!==''){
                        oApplication.tLayer[this.idLayer].linkPointWithSelected(oFrom,oTo,this.points,oApplication.pointIdSelected,this.strokeStyle,this.lineWidth);
                    }else{
                        oApplication.tLayer[this.idLayer].linkPoint(oFrom,oTo,this.points,this.strokeStyle,this.lineWidth);
                    }
                }else{
                    console.log('oFrom et oTo'+oFrom+' '+oTo);
                    oApplication.tLayer[this.idLayer].link(oFrom,oTo,this.strokeStyle,this.lineWidth);
     
                }
            }
     
            this.updateInfo();
        },
    Comme vous pouvez le voir: en fonction du type d’element on va appeler une méthode différente de dessin sur le layer où est dessiné l’objet.

    A partir de là on peut cocher/decocher un objet pour l’afficher ou non sur son calque.
    Pour ce faire, on joue sur la propriété visible de l’objet et on demande à l’application de redessiner le calque:
    Fichier public/js/application.js
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    showHideObject:function(idObject){
            var a=getById('checkbox_object_'+idObject);
            if(a){
                var oObject=this.getObject(idObject);
     
                if(a.checked){
                    oObject.visible=1;
                }else{
                    oObject.visible=0;
                }
     
                this.buildLayer(oObject.idLayer);
            }
     
        },
    Qui appelle ensuite la methode de reconstruction du calque (toujours dans le même fichier)
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    buildLayer:function(idLayer){
            oApplication.tLayer[idLayer].clear();
     
            var iLength=this.tMenuLayerObject[idLayer].length-1;
     
            for(var i=iLength;i&gt;=0;i--){
                var tmpObj=this.getObject(this.tMenuLayerObject[idLayer][i]);
                if(tmpObj &amp;&amp; tmpObj.visible==1){
                    tmpObj.build();
                }
            }
     
        },
    Qui comme vous le voyez efface le calque (canvas) avant de boucler sur les claques objets pour dessiner ou non celui-ci en fonction de sa propriété visible.

    Voila pour ce premier tour d’explication du fonctionnement de l’application

    Le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-2
    Images attachées Images attachées  

  7. #7
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut Journal de bord: création d’une application de création de schéma en HTML5: Jour 3
    Introduction
    Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-2

    Dans ce billet, je vais expliquer la méthode pour enregistrer un schéma et le charger.
    Je vais également indiquer les dernières avancées.

    Enregistrer un schéma
    L’idée est simple: sérialiser les éléments et les enregistrer en base de données.
    Pour cela, un bouton « save » qui fait appel à une function save()
    Code javascript : 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
     
    function loadSave(){
        //on serialize le tableau tObject
        var stObject=JSON.stringify( oApplication.tObject); 
     
        //on enregistre la serialisation dans l'input tObject
        var b=getById('tObject');
        if(b){
            b.value=stObject;
        }
     
        //on fait de meme pour les calques objet, afin de conserver l'ordre
        var stMenuLayerObject=JSON.stringify( oApplication.tMenuLayerObject); 
     
        var c=getById('tMenuLayerObject');
        if(c){
            c.value=stMenuLayerObject;
        }
    }
    function save(){
     
        loadSave();
     
        //une fois le chargement fait, on soumet le formulaire
        var a=getById('formSave');
        if(a){
            a.submit();
        }
    }
    Et coté php, dans le framework dans me module default
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    private function processSave($oSchema){
    		if(!_root::getRequest()->isPost()){
    			return;
    		}
     
    		$oSchema->tObject=_root::getParam('tObject');
    		$oSchema->tMenuLayerObject=_root::getParam('tMenuLayerObject');
    		$oSchema->save();
     
    		//var_dump($oSchema);exit;
     
    		_root::redirect('default::schema',array('id'=>$oSchema->id));
    	}
    Processus de chargement du shéma
    L’idée est simple: on récupère le tableau d’objet sérialisé ainsi que le tableau indiquant l’ordre des calques objets
    Données que l’on assigne à la vue
    Code php : 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
     
    public function _schema(){
     
    		$tObject=null;
    		$tMenuLayerObject=null;
     
    		$oSchema=model_schema::getInstance()->findById(_root::getParam('id'));
    		if($oSchema){
    			$this->processSave($oSchema);
     
    			$tObject=$oSchema->tObject;
    			$tMenuLayerObject=$oSchema->tMenuLayerObject;
    		}
     
     
    	    $oView=new _view('default::index');
    		$oView->tObject=html_entity_decode($tObject);
    		$oView->tMenuLayerObject=html_entity_decode($tMenuLayerObject);
     
    		$this->oLayout->add('main',$oView);
    	}
    Ensuite dans la vue, on va reconstruire le schéma: on instancie un tableau avec la valeur serialisé de tObject
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    var tObject=<?php echo $this->tObject?>;
    On boucle sur ce tableau serialisé pour recréé les objets Datas
    Code javascript : 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
     
    for(var i=0;i< tObject.length;i++){
    	if(!tObject[i]){ continue; }
    	var oData=new Data(tObject[i].type,tObject[i].idLayer);
    	oData.x=tObject[i].x;
    	oData.y=tObject[i].y;
    	oData.strokeStyle=tObject[i].strokeStyle;
    	oData.fillStyle=tObject[i].fillStyle;
    	oData.width=tObject[i].width;
    	oData.height=tObject[i].height;
    	oData.from=tObject[i].from;
    	oData.comment=tObject[i].comment;
    	oData.to=tObject[i].to;
    	oData.lineWidth=tObject[i].lineWidth;
    	oData.x2=tObject[i].x2;
    	oData.y2=tObject[i].y2;
    	oData.texte=tObject[i].texte;
    	oData.size=tObject[i].size;
    	oData.info=tObject[i].info;
    	oData.relativeObject=tObject[i].relativeObject;
    	oData.relativeX=tObject[i].relativeX;
    	oData.relativeY=tObject[i].relativeY;
    	oData.textAlign=tObject[i].textAlign;
    	oData.strokeStyleText=tObject[i].strokeStyleText;
     
    	oData.fromPosition=tObject[i].fromPosition;
    	oData.toPosition=tObject[i].toPosition;
     
    	oData.build();
     
    	oApplication.addLayerObject(1,oData);
    }
    On fait de même pour le tableau de calques objet: sauf que cette fois on l’enregistre dans l’objet application, puis on boucle pour reconstruire les différents calques.
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    oApplication.tMenuLayerObject=<?php echo $this->tMenuLayerObject?>;
     
    for(var i=1;i<=iMax;i++){
     
    	oApplication.clearMenuObject(i);
    	oApplication.builListMenuLayerObject(i);
    }
    Les avancées
    On peut désormais ordonner les calques objets et cliquer sur un objet pour l’envoyer sur un autre calque.

    Dépot Github
    Le dépot github: https://github.com/imikado/mkdraw

    Le billet : http://blog.developpez.com/ducodeetd...n-html5-jour-3

  8. #8
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut Journal de bord: création d’une application de création de schéma en HTML5: Jour 4
    Introduction
    Ce billet fait suite au billet: http://blog.developpez.com/ducodeetd...n-html5-jour-3

    Dans ce billet on va voir plusieurs choses: l’ajout d’un webservice, la possibilité de sélectionner un objet sur le dessin et enfin la possibilité de dupliquer un objet.

    Ajout d’un webservice
    Il peut être utile de pouvoir générer un schéma à la volée. Ceci va être permis grâce à l’installation d’un webservice.
    C’est également l’occasion de montrer comment développer un serveur webservice.

    D’abord un fichier webservice.php dans le répertoire public/
    Dans celui-ci on inclut le fichier index.php et l’on force le lancement du module de webservice
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <?php
    $_GET['nav']='webservice::index';
    include('index.php');
    Ensuite on créé un module webservice dans le répertoire module/
    Code php : 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
     
    <?php
    class module_webservice{
     
    	public function _index(){
    		ini_set("soap.wsdl_cache_enabled","0");
     
    		$oPluginWsdl=new plugin_wsdl;
    		$oPluginWsdl->setName('mkdraw');
    		$oPluginWsdl->setUrl('http://localhost/mkframework/data/genere/mkdraw/public/webservice.php');
    		$oPluginWsdl->addFunction('setContent');
    			$oPluginWsdl->addParameter('id','int');
    			$oPluginWsdl->addParameter('tObject','string');
    			$oPluginWsdl->addParameter('tMenuLayerObject','string');
    			$oPluginWsdl->addReturn('return','string');
    			$oPluginWsdl->addReturn('ok','int');
     
     
    		if(isset($_GET['WSDL'])) {
     
     
    			$oPluginWsdl->show();
     
     
    		}else {
     
    			$oServer = new SoapServer( 'http://localhost/mkframework/data/genere/mkdraw/public/webservice.php?WSDL', array('cache_wsdl' => WSDL_CACHE_NONE));					
    			$oServer->setClass('webservice');
    			$oServer->handle();
     
     
    		}
    		exit;
    	}
    }
    class webservice{
    	public function setContent($id,$tObject,$tMenuLayerObject){
     
    		$oSchema=model_schema::getInstance()->findById($id);
    		$oSchema->tObject=$tObject;
    		$oSchema->tMenuLayerObject=$tMenuLayerObject;
    		$oSchema->save();
     
    		return array('return'=>'test','ok'=>1);
     
    	}
    }
    Ici, à la récupération de deux paramètres que sont le tableau d’objet sérialisé ainsi que le tableau de l’ordre des calques objets.

    Possibilité de sélectionner un objet sur le dessin
    L’idée c’est de permettre de cliquer sur un objet sur le dessin pour pouvoir l’éditer plutot que de cliquer à droite dans les calques objets.
    Pour cela on va afficher un crayon cliquable sur les objets dont on veut permettre cette fonctionnalité: les carrés et bdd

    Premièrement, on permet d’afficher un icone de crayon au dessus des objets
    Ajout d’une méthode enableEdit sur la classe Data (data.js)
    Code javascript : 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
     
    enableEdit:function(){
     
    		var divEdit=getById('edit_'+this.id);
    		if(divEdit){
    			divEdit.style.top=(this.y-5)+'px';
    			divEdit.style.left=(this.x+10)+'px';
     
    		}else{
     
    			var sHtml='';
    			sHtml+='<div id="edit_'+this.id+'" onclick="oApplication.selectObject('+this.id+')"  class="edit" style="left:'+(this.x+10)+'px;top:'+(this.y-5)+'px;">';
     
    			sHtml+='&nbsp;';
     
    			sHtml+='</div>';
     
    			oApplication.addContent('tEdit',sHtml);
    		}
    	},
    Qui créé une cellule div avec une action lors du clic pour selectionner l’objet en question.
    La question qui se pose ensute c’est quand afficher cette fonctionnalité, je suis parti sur le fait de cliquer sur un calque pour afficher tous les « crayons » des objets sur le calque.

    Ensuite on va boucler pour afficher ces boutons d’édition lorsque l’on selectionne un calque.
    Editez la méthode selectLayer() de la classe application.js
    En ajoutant à la fin
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    var a=getById('tEdit');
    		if(a){
    			a.innerHTML='';
    		}
    		for(var i=0;i<this.tObject.length;i++){
    			if(!this.tObject[i]){ continue; }
    			if(this.tObject[i].idLayer==idLayer && (this.tObject[i].type=="carre" || this.tObject[i].type=="bdd") ){
     
    				this.tObject[i].enableEdit();
    			}
     
    		}
    Permettre de dupliquer un objet
    Il est souvent utile lorsque l’on fait un shéma de dupliquer un objet, on va le permettre en ajoutant un bouton dans le formulaire d’édition d’un objet.
    Dans la méthode getForm() de data.js
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    if(this.type=='carre' || this.type=='bdd' || this.type=='losange'){
     
    			sHtml+='<p><input type="button" value="Dupliquer" onclick="oApplication.duplicateObject('+this.id+')" /></p>';
    		}
    On ajoute un bouton qui appelera la methode duplicate de la classe Application

    Et dans la classe application, cette méthode de duplication:
    Code javascript : 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
     
    duplicateObject:function(idObject){
    		//on recupere l'objet à dupliquer
    		var oTmpData=this.getObject(idObject);
     
    		//on cree un nouvel objet
    		var oNewData=new Data(oTmpData.type,oTmpData.idLayer);
    		//que l'on decale de 10, afin de le voir
    		oNewData.x=oTmpData.x+10;
     
    		//liste des propriétés à copier
    		var tColumn=Array(
    					'strokeStyle',
    					'fillStyle',
    					'width',
    					'height',
    					'from',
    					'comment',
    					'to',
    					'lineWidth',
    					'y',
    					'x2',
    					'y2',
    					'texte',
    					'size',
    					'info',
    					'relativeObject',
    					'relativeX',
    					'relativeY',
    					'textAlign',
    					'strokeStyleText',
    					'fromPosition',
    					'toPosition'
     
    				);
     
    		//on boucle sur ce tableau pour copier les propriétés
    		//sur le nouvel objet
    		for(var i=0;i<tColumn.length;i++){
    			oNewData[tColumn[i] ]=oTmpData[tColumn[i] ];
    		}
    		//on demande à l'afficher.
    		oNewData.build();
     
    		this.addLayerObject(oTmpData.idLayer,oNewData);
     
    		this.selectObject(oNewData.id);
     
    	},
    Voila pour les dernières fonctionnalités ajoutées.
    On continue petit à petit à améliorer l’ergonomie et le confort de création de schéma avec cette application

    Dépot Github
    Le dépot github: https://github.com/imikado/mkdraw

    Le billet: http://blog.developpez.com/ducodeetd...n-html5-jour-4

  9. #9
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut
    Je travaille sur une version SVG du même projet, c'est en cours de conversion

    Le projet gitHub: https://github.com/imikado/mkdrawsvg

    La majorité de la traduction se fait dans le fichier public/js/Canvas.js

    Par exemple traduction du dessin de rectangle
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    drawRect : function(x,y,ilargeur,ihauteur,lineWidth,strokeStyle,fillStyle){
     
    	this.ctx.beginPath();
     
    	this.ctx.lineWidth=lineWidth;
    	this.ctx.strokeStyle=strokeStyle;
    	this.ctx.fillStyle=fillStyle;
     
    	this.ctx.fillRect(x,y,ilargeur,ihauteur);
    	this.ctx.strokeRect(x,y,ilargeur,ihauteur);
     
    	this.ctx.closePath();
     
    },
    Devient
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    drawRect : function(x,y,ilargeur,ihauteur,lineWidth,strokeStyle,fillStyle){
     
    	var sSvg='<rect class="chartRect" id="rect'+x+''+y+'" x="'+x+'" y="'+y+'" width="'+ilargeur+'" height="'+ihauteur+'" style="fill:'+fillStyle+';stroke-width:'+lineWidth+';stroke:'+strokeStyle+'"></rect>';
     
    	this.addObject(sSvg);
     
    },

  10. #10
    Rédacteur
    Avatar de imikado
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2006
    Messages
    5 239
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Finance

    Informations forums :
    Inscription : Décembre 2006
    Messages : 5 239
    Points : 19 098
    Points
    19 098
    Billets dans le blog
    17
    Par défaut
    Introduction
    Il y a quelques mois j’ai travaillé sur un projet d’application web permettant de dessiner des schémas en utilisant le canvas.
    Un membre du forum « SylvainPV » (que je remercie au passage) m’avais demandé pourquoi je n’avais pas utilisé SVG à la place du canvas.
    Le projet étant bien avancé (sans parler du fait que je connaissais plus canvas qu’SVG) je ne me voyais pas tout reprendre de zéro en changeant de technologie de dessin.

    Mais suite à des retours sur l’application actuelle, j’ai remis les mains dans le code et analysé l’effort à faire pour modifier la méthode de dessin du canvas au SVG

    Canvas VS SVG
    Deux technologies qui ont leurs avantages et inconvénients, deux technologies différentes de dessin l’un dessine en bitmap (canvas) l’autre en vectoriel (SVG)
    Les avantages dont je souhaite profiter en migrant cette application

    Permettre de selectionner un objet sur le calque en cliquant dessus
    Profiter du format vectoriel: on peut ainsi augmenter la taille du schéma sans perdre en qualité
    Permettre d’ajouter des fenêtre contextuel + des liens sur les objets
    Un des défauts de la version Canvas, c’est que l’on dessine sur une image, mais il est ensuite difficile de sélectionner sur l’espace de travail un objet pour pouvoir le déplacer, redimensionner ou autre. Pour pallier à ce problème j’ai ajouté des petits icones de crayons en utilisant des « div » avec un lien javascript.

    L’objet de la migration
    Pour migrer en SVG, il faut supprimer toute trace de canvas: on garde les div utilisés mais on ne dessine plus sur le canvas.
    Pour dessiner en SVG on créé dans le DOM de la page HTML du code SVG.

    Quelques exemples de migration
    On modifie ici principalement le fichier public/js/canvas.js
    On passe de ceci:
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    drawRect : function(x,y,ilargeur,ihauteur,lineWidth,strokeStyle,fillStyle){
     
        this.ctx.beginPath();
     
        this.ctx.lineWidth=lineWidth;
        this.ctx.strokeStyle=strokeStyle;
        this.ctx.fillStyle=fillStyle;
     
        this.ctx.fillRect(x,y,ilargeur,ihauteur);
        this.ctx.strokeRect(x,y,ilargeur,ihauteur);
     
        this.ctx.closePath();
     
    },
    A ceci
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    drawRect : function(x,y,ilargeur,ihauteur,lineWidth,strokeStyle,fillStyle){
     
    	var sSvg='<rect class="chartRect" id="rect'+x+''+y+'" x="'+x+'" y="'+y+'" width="'+ilargeur+'" height="'+ihauteur+'" style="fill:'+fillStyle+';stroke-width:'+lineWidth+';stroke:'+strokeStyle+'"></rect>';
     
    	this.addObject(sSvg);
     
     
    },

Discussions similaires

  1. Réponses: 2
    Dernier message: 09/11/2006, 22h22
  2. [VS2005/C#]création d'une application MDI
    Par malikoo dans le forum Windows Forms
    Réponses: 1
    Dernier message: 20/07/2006, 17h48
  3. Réponses: 19
    Dernier message: 10/05/2006, 09h40
  4. Réponses: 4
    Dernier message: 08/01/2006, 04h30
  5. [tomcat] Création d'une application WEB
    Par bob33 dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 25/10/2004, 19h35

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