Forums Développement Multimédia

Aller au contenu

Positionnement dynamique d'objets dans une grille ✔

position dynamique x/y modulo CODE Actionscript

5 réponses à ce sujet

#1 Wak

    Ceinture Jaune

  • Members
  • PipPip
  • 26 messages

Posté 19 June 2012 - 19:45 PM

Bonjour,

je suis en train de refaire mon site web, orienté portfolio, et je suis confronté à un problème en apparence tout bête, mais que je n'arrive pas à surmonter.

Je souhaite positionner mes images sur une grille. J'ai repéré un site qui utilise ce système : http://www.michelraj...olio/1-nowhere/
Bon, lui c'est carrément la classe parce qu'en plus d'utiliser swfaddress sur plusieurs niveaux (moi je n'arrive que sur un seul), la grille se recalcule selon les dimensions de l'écran et créé plusieurs "pages" au besoin.

Bref, je n'en suis pas là et tout ce que j'ai trouvé sur le web pour positionner dynamiquement des objets sous forme de grille, ce sont de sombres histoires de modulo auxquelles je ne comprends rien malgré le temps que j'ai passé à tenter de comprendre la méthode. Et à moins d'être bigleux je n'ai rien vu dans le wiki (et je ne comprends pas l'exemple de Thibault Imbert dans son livre, p.135).

Pourriez-vous m'expliquer comment qu'on fait pour réaliser ce genre de positionnement ?

A vot' bon coeur, merci m'sieur dame ! :roi:

#2 tlecoz

  • Honoris
  • PipPipPipPipPipPipPipPip
  • 3486 messages

Posté 19 June 2012 - 21:39 PM

Hello !

Je ne vois pas immédiatement à quoi te servirais des modulo dans ce cas là (enfin si, je vois, mais c'est pas absolument nécessaire non plus), mais vu que c'est quand même pas très compliqué je vais essayer de t'expliquer vite fait

faire le modulo de A sur B ( A % B ) , c'est limiter A à un chiffre compris entre 0 et B.

si on devait le coder en AS3, ca donnerait quelque chose du genre

var i:int;
var A:int = 21;
var B:int = 10;
var result:int = 0;
for(i=0;i<A;i++){
        result++;
        if(result == B  ) result = 0;
}
trace(result ) ;  //--> 1
trace(A % B  ); //--> 1
 


Pour ce qui est de ton problème de grille

Tu peux passer par une double boucle pour t'aider a positionner tes objets


var elementSize:Number = 100;
var spacer:int = 10;
var nbLine:int = 5;
var nbColumn:int = 5;
var element:Object;
var elements:Array = [];
var i:int, j:int
var nb:int = 0;
for (i = 0; i < nbColumn; i++) {
   for (j = 0; j < nbLine; j++) {
         element = new Object();
         element.x = j * (elementSize + spacer);
         element.y = i * (elementSize + spacer);
         elements.push(element);
   }
}
 


Tant que j'y étais, j'ai essayé de bidouiller le principe d'animation, mais j'ai la flemme d'expliquer comment tout marche, et je ne te recommande d'ailleurs pas de t'y prendre comme moi car la méthode que j'utilise est contraignante dans le cas d'un vrai projet (à savoir utiliser un seul displayObject dans lequel je dessine tout), mais le principe général est bon.


package
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.InterpolationMethod;
import flash.display.Shape;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
/**
  * ...
  * @author tlecoz
  */

public class TEST extends Sprite
{

  private var gridElements:Array = [];
  private var elements:Array = [];
  private var elementSize:Number = 100;
  private var spacer:int = 10;
  private var reverse:Boolean = false;


  public function TEST()
  {
 
   var nbLine:int = 5;
   var nbColumn:int = 5;
   var element:Object;
 
  var m:Matrix = new Matrix();
  var w:Number = (nbColumn * (spacer + elementSize));
  var h:Number = (nbLine * (spacer + elementSize));
  m.createGradientBox(w, h, Math.PI / 180 * 45, 0, 0);
  graphics.beginGradientFill("radial", [0xff0000,0x0ff0f0, 0x0000ff], [1,1, 1], [0,127, 255], m,SpreadMethod.REFLECT,InterpolationMethod.LINEAR_RGB);
  graphics.drawRect(0, 0, w, h);
  var picture:BitmapData = new BitmapData(w, h, false, 0);
  picture.draw(this);
  graphics.clear()
 
 
 
   var i:int, j:int
   var r:Rectangle = new Rectangle(0,0,elementSize,elementSize)
   var pict:BitmapData = new BitmapData(elementSize, elementSize, false, 0);
   var newPt:Point = new Point();
   var nb:int = 0;
   for (i = 0; i < nbColumn; i++) {
        gridElements[i] = [];
        for (j = 0; j < nbLine; j++) {
         element = new Object();
         element.endX = r.x = j * (elementSize + spacer);
         element.endY = r.y = i * (elementSize + spacer);
         element.startX = element.x = -100;
         element.startY = element.y = -100;
       
         element.delay = element.startDelay = nb * 2;
         pict.copyPixels(picture, r, newPt);
         element.picture = pict;
       
         gridElements[i][j] = element;
         elements[nb] = element;
       
         nb++;
         pict = pict.clone();
        }
   }
 
   stage.addEventListener(MouseEvent.CLICK, onClick);
 
  }
  private function onClick(e:MouseEvent):void {
   var i:int, len:int = elements.length;
   for (i = 0; i < len; i++) {
        elements[i].delay = elements[i].startDelay;
        if (!reverse) {
         elements[i].nextX = elements[i].endX;
         elements[i].nextY = elements[i].endY;
        }else {
         elements[i].nextX = elements[i].startX;
         elements[i].nextY = elements[i].startY;
        }
   }
   addEventListener(Event.ENTER_FRAME, update);
   reverse = !reverse
 
  }
  private function update(e:Event):void {
 
   graphics.clear();
 
   var i:int, len:int = elements.length;
   var element:Object;
   var speed:Number = 0.3
   var matrix:Matrix = new Matrix();
 
   for (i = 0; i < len; i++) {
        element = elements[i];
        if (element.delay -- < 0) {
         if (Math.abs(element.x - element.nextX) > 1) {
          element.x -= (element.x - element.nextX) * speed;
          element.y -= (element.y - element.nextY) * speed;
         }else {
          element.x = element.nextX;
          element.y = element.nextY;
         }
        }
 
        matrix.identity();
        matrix.translate(element.x, element.y);
        graphics.beginBitmapFill(element.picture, matrix);
        graphics.drawRect(element.x, element.y, elementSize, elementSize);
        graphics.endFill();
   }
  }
}
}
 

Bon courage pour la suite !

Fichier(s) joint(s)



#3 Wak

    Ceinture Jaune

  • Members
  • PipPip
  • 26 messages

Posté 29 June 2012 - 15:28 PM

Bonjour tlecoz,

Je découvre à l'instant ton message avec un peu de retard. Merci beaucoup de ton aide. Je vais tester tout ça à tête reposée :)

Ton code en POO va m'aider pour voir le contexte car je commence à m'y mettre. Je viens de me confronter au problème de réutilisation d'une partie de mon code "au fil de l'eau" d'un précédent projet et... c'est bien galère ;)

A bientôt !

#4 paodao

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 7081 messages

Posté 29 June 2012 - 16:26 PM

salut
si tu veux repartir des elements sur une grille en fonction des dimensions du swf tu peux faire ainsi
le code important est dans la fonction place()

import flash.display.Sprite;
import flash.events.Event;

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;

function creerRectangle():Sprite
{
        var s:Sprite = new Sprite();
        s.graphics.beginFill(0xff0000);
        s.graphics.drawRect(0,0,50,50);
        addChild(s);
        return s;
}

var tab:Array = new Array();
for(var i:int = 0; i< 50; i++)tab.push(creerRectangle());

function place():void
{
       
        //on determine le nombre d'element que l'on peux afficher
        var nbColonne:int = int(stage.stageWidth/tab[0].width);
        //on calcul la marge que l'on doit avoir entre 2 elements afin qu'il soit bien placé
        var marge:Number = (stage.stageWidth - nbColonne*tab[0].width)/(nbColonne-1);
        for(var i:int = 0; i<  tab.length; i++)
        {
                //on utilise le modulo pour determiner la colonne dans laquel on est
                tab[i].x = (tab[i].width+marge)*(i%nbColonne);
                //faire int(i/nbColonne) reviens a faire Math.floor(i/nbColonne)
                //cela permet de determiner la ligne
                tab[i].y = (tab[i].height+marge)*int(i/nbColonne)
        }
       
}

place();
stage.addEventListener(Event.RESIZE, resizeHandler);
function resizeHandler(e:Event):void
{
        place();
}
 

resize le swf obtenue tu verra que les carres rouge se repositionne pour occuper l'espace

a+

Fichier(s) joint(s)



#5 Nataly

    Community Jane

  • Moderateur
  • PipPipPipPipPipPipPipPip
  • 5783 messages

Posté 29 June 2012 - 16:39 PM

Salut wak :)

Effectivement te voilà avec un beau gros exemple (que je n'ai pas vraiment lu :oops: )


Vu que tu demandais des explications, je vais prendre ma part ;)

Que veux tu ? tout bonnement disposer des objets selon un certain nombre de lignes et de colonnes ? (c'est là que le modulo est bien utile et évite des tartines gavées de if)

imaginons que tu veux disposer 15 éléments (des rectangles par exemple) en 3 lignes / 5 colonnes le premier en haut à gauche en 0/0 (ensuite rien ne t'empêche de changer ça, mais ne nous compliquons pas tout de suite)

réfléchissons d'abord sur la position x et considérons que l'on commence à compter à 0 (pas à 1)
le premier élément (l'élément zéro en fait) on le met tout au bord, coordonnée 0, facile.
Le suivant (imaginons qu'on les colle) aura pour x la largeur du précédent (largeur x 1), le suivant deux largeurs (largeurs x2), le suivant trois largeurs (largeur x3) , et s'il n'y avait qu'une ligne on les poserait côte côte aussi simplement que ça :


var nbTot:int=15
for (var i:int=0; i<nbTot; i++) {
        var laCase:Mv_Case=new Mv_Case();      
        laCase.x=i*laCase.width;
        addChild(laCase);
}


j'ai inventé un clip Mv_Case pour l'occasion

le problème c'est que dans notre cas on veut plusieurs lignes. Arrivé au quatrième objet (puisqu'il y a trois colonnes) on veut revenir à gauche (x=0)

Et c'est là qu'intervient le modulo. C'est le reste de la division d'un nombre par un autre.
Si tu divises le numéro de l'élément courant par le nombre de colonnes, regarde ce que ça donne :

0/3=0 reste 0
1/3=0 reste 1
2/3=0 reste 2
3/3=1 reste 0
4/3=1 reste 1
5/3=1 reste 2
6/3=2 reste 0


en gros le modulo (en vert) te permet de te balader sur les x : zéro fois la largeur le premier, une fois la largeur le suivant, deux fois la largeur le dernier, et hop ligne du dessous on recommence : zéro fois la largeur…

quant aux y en imaginant la ligne du haut en zéro (zéro fois la hauteur), celle du desous est à une fois la hauteur, la suivante deux fois etc… regarde ce sont les chiffres rouges ;) donc la partie entière de la division.

var nbCol:int=5;
var nbLig:int=3;
var nbTot:int=nbLig*nbCol;

for (var i:int=0; i<nbTot; i++) {
        var laCase:Mv_Case0=new Mv_Case0();
        laCase.y=int(i/nbCol)*laCase.height;
        laCase.x=i%nbCol*laCase.width;
        addChild(laCase);
}

si tu veux ajouter un espace entre les éléments


var nbCol:int=5;
var nbLig:int=3;
var nbTot:int=nbLig*nbCol;
var espace:int= 5

for (var i:int=0; i<nbTot; i++) {
        var laCase:Mv_Case0=new Mv_Case0();
        laCase.y=int(i/nbCol)*(laCase.height+espace);
        laCase.x=i%nbCol*(laCase.width+espace);
        addChild(laCase);
}

voilà qui te permettra sans doute de comprendre plus facilement le code de Tlecoz :)
Le savoir est le seul bien qui s'accroit quand on le partage
une tartine de tutos

#6 Wak

    Ceinture Jaune

  • Members
  • PipPip
  • 26 messages

Posté 02 July 2012 - 10:59 AM

Bonjour à tous et merci vraiment pour votre aide et vos explications détaillées. Nataly, quel sens de la vulgarisation ! ;-)

Je n'avais vraiment pas compris l'utilisation du modulo (pour moi, c'était des math de haut niveau !). Maintenant c'est clair et limpide. Tous vos exemples présentent des situations différentes de placement et je pense m'en sortir avec tout ça.

Je pourrai peut-être bientôt présenter un joli site dans la rubrique ad-hoc du forum... ;-) Mais, quelque chose me dit que je reposerai encore 2 ou 3 questions avant (j'essaye de le faire en POO -merci Nataly pour le super tuto dans le wiki-, avec swfaddress, en relation avec du php, et le plus optimisé possible, ouch!) :mrgreen:

Merci beaucoup !



1 utilisateur(s) li(sen)t ce sujet

0 membre(s), 1 invité(s), 0 utilisateur(s) anonyme(s)