Newsletter Developpez.com

Inscrivez-vous gratuitement au Club pour recevoir
la newsletter hebdomadaire des développeurs et IT pro

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

Le , par imikado, Rédacteur
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
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
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/


Vous avez aimé cette actualité ? Alors partagez-la avec vos amis en cliquant sur les boutons ci-dessous :


 Poster une réponse

Avatar de SylvainPV SylvainPV - Rédacteur/Modérateur https://www.developpez.com
le 05/02/2014 à 17:06
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.
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 05/02/2014 à 20:27
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)
Avatar de SylvainPV SylvainPV - Rédacteur/Modérateur https://www.developpez.com
le 06/02/2014 à 14:27
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
<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
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 06/02/2014 à 14:57
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
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 07/02/2014 à 19:29
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
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
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
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
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>=0;i--){ 
            var tmpObj=this.getObject(this.tMenuLayerObject[idLayer][i]); 
            if(tmpObj && 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
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 11/02/2014 à 22:00
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
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
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
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
1
2
  
var tObject=<?php echo $this->tObject?>;
On boucle sur ce tableau serialisé pour recréé les objets Datas
Code javascript : Sélectionner tout
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
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
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 17/02/2014 à 8:51
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
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
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
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
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
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
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
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 13/06/2014 à 22:43
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
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
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); 
  
},
Avatar de imikado imikado - Rédacteur https://www.developpez.com
le 13/06/2014 à 23:17
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
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
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); 
  
  
},
Offres d'emploi IT
Web developer e-commerce h/f
Groupe Etam - Ile de France - Clichy (92110)
Développeur web front end / intégrateur h/f
CRESCENDO VAISE - Rhône Alpes - Lyon (69000)
Webmaster développeur / développeuse
non divulgué - Midi Pyrénées - Toulouse (31000)

Voir plus d'offres Voir la carte des offres IT
Responsable bénévole de la rubrique Développement Web : Xavier Lecomte -