Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[AS2] Tween; position & scale op midden van MovieClip

Pagina: 1
Acties:

  • Neejoh
  • Registratie: Juni 2001
  • Laatst online: 24-04 18:27
Ben inmiddels zo ver in de richting dat ik nog maar een klein steuntje in de rug nodig heb.

Mijn bedoeling van onderstaande script is dat ik inzoom op de aangeklikte MovieClip, deze moet gecentreerd op de stage komen te staan. Je kan het zien als een stadsplattegrond waarbij er ingezoomed wordt op een bepaalde wijk. Het is dus van belang dat zowel de background als de movieclips gelijk inzoomen.

Ik heb een container MC (mc_container) met hierin 3 MC's (mc_r1 / mc_r2 / mc_r3) die dienen als buttons.
Flash ActionScript:
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
/**
 * Position and scale on selected MovieClip 
 *
 * @author    R. ter Veen
 * @company   ComSi
 * @date      24-07-2007 
 *
 */
function zoomFunction(movieClip) {
    //-- import van de tweenclass
    import mx.transitions.Tween;
    import mx.transitions.easing.*;

    //-- exacte middelpunt van de gehele stage
    var midX:Number = Stage.width/2;
    var midY:Number = Stage.height/2;
    
    //-- functie die uitgevoerd wordt wanneer er op de MC geklikt wordt
    movieClip.onPress = function() {
        
        //-- bepaal de positie van de geklikte MC
        var mcX:Number = movieClip._x;
        var mcY:Number = movieClip._y;

        //-- bepaal de grootte van de geklikte MC
        var mcWidth:Number = movieClip._width / 2;
        var mcHeight:Number = movieClip._height / 2;

        //-- bepaal de nieuwe positie van de container
        var newX:Number = midX - mcX - mcWidth;
        var newY:Number = midY - mcY - mcHeight;

            var _pX:Tween = new Tween(mc_container, "_x", Strong.easeOut, mc_container._x, newX, 1, true);
            var _pY:Tween = new Tween(mc_container, "_y", Strong.easeOut, mc_container._y, newY, 1, true);
            //-- uncomment onderstaande tween voor de scale optie
            //var _sX:Tween = new Tween(mc_container, "_xscale", Strong.easeOut, mc_container._xscale, 200, 1, true);
            //var _sY:Tween = new Tween(mc_container, "_yscale", Strong.easeOut, mc_container._yscale, 200, 1, true);
    };
}

//-- roep de functie aan op de gewenste movieclips 
//-- (alle 3 childs van "mc_container" omdat ze mee moeten scalen met de background)
zoomFunction(mc_container.mc_r1);
zoomFunction(mc_container.mc_r2);
zoomFunction(mc_container.mc_r3);

Het probleem zit hem in de (commented) scale-tween (ln 36/37). Zodra ik deze comment weghaal verspringt de stage naar een heel verkeerd punt... Iemand een oplossing?

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Ik denk dat het probleem zit in het mechanisme wat je gebruikt.

Stel de container voor als een cirkel, met mc_r1 een vierkantje offcentre zeg tegen de rand aan. Als je nu de container verplaatst om het vierkantje in het midden van de stage te krijgen, en je vervolgens de container gaat scalen, dan verandert de positie van het vierkantje weer (drijft weg van het middelpunt van de cirkel). Daar zijn allerlei oplossingen voor te bedenken natuurlijk :)

[ Voor 6% gewijzigd door Bozozo op 25-07-2007 00:37 ]

TabCinema : NiftySplit


  • Neejoh
  • Registratie: Juni 2001
  • Laatst online: 24-04 18:27
Klopt, dat is ook wat lijkt te gebeuren.
Het punt zit hem in het feit dat de scale gebeurd vanaf punt 0,0 van de stage, niet het midden van de stage/MC. Dit is ook logisch, want de scale en de position worden tegelijk uitgevoerd -- zo weet je dus nooit het middelpunt omdat deze variabel/midden in een tween is.

Ik heb het idee dat ik via een formule de exacte afstand van punt 0,0 naar het midden van de gewenste MC moet weten, inclusief scaling.
Het leek me gemakkelijk door eerste de positie van de MC tot het middelpunt van de stage uit te rekenen en dit 2x te vergroten, but that's a big no go...

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Hmm ik ben aan het proberen een soortgelijk script te schrijven in as3 (ik wil zo min mogelijk in as2 werken om verwarring voor mezelf te voorkomen) en het eerste dat me opvalt is dat stage.width en stage.height zijn gedefinieerd aan de hand van het daardwerkelijk bezette deel van de stage. Dus een vierkant van 200x200 op een stage van 550x400 geeft een stage.width van 200. Misschien wist je dat al maar ik meld het maar even.

Ik knutsel nog even verder :)

TabCinema : NiftySplit


  • Neejoh
  • Registratie: Juni 2001
  • Laatst online: 24-04 18:27
Is dat zo? De stage.width blijft toch altijd 550, ook als er alleen een vierkant van maar 200 op staat?

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Nou hier niet :o

Ik heb het trouwens voor elkaar denk ik, zij het zonder Tween oid. Ik heb nu gewoon een kaart + drie knopjes, en als je op een knopje drukt verplaatsen kaart en knopjes en worden ze vergroot, waarna het geklikte knopje in het midden staat. Ik hoop dat je het kunt lezen... het is even wennen maar het lijkt erg op de as2 code.

code:
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
--- code box 2 bevat betere code! ---


(containers (en kaart en knopjes erin) definieren en op stage zetten)
(elk knopje luister naar MouseEvent.CLICK met als uitvoerende functie 'zoom')

var verg:Number = 2; //in te stellen vegroting.
function zoom(event:MouseEvent):void{
    var mc:Object = event.target; //mc is nu een referentie naar het knopje waarop werd geklikt
    
    var difx:Number = 275 - mc.x; // de benodigde verplaatsing om het onvergrote object op het midden te plaatsen.
    var dify:Number = 200 - mc.y;

    var vergdifx:Number = mc.x*(verg-1); // de ongewilde verplaatsing tengevolge van de vergroting.
    var vergdify:Number = mc.y*(verg-1);

    kaart.width*=verg;
    kaart.height*=verg;
    kaart.x+=difx - vergdifx;
    kaart.y+=dify - vergdify;
    
    knoppen.width*=verg;
    knoppen.height*=verg;
    knoppen.x+=difx - vergdifx;
    knoppen.y+=dify - vergdify;
}

Hierbij zijn zowel 'kaart' als 'knoppen' containers op x=0 y=0 met de kaart en de knoppen op willekeurige posities erin.

edit: ik heb de code wat sexier gemaakt. Je kunt nu meerdere keren inzoomen en een stapgrootte instellen. Dat zijn geen fratsen: de code is nu niet meer incrementeel maar berekent steeds nieuwe scale/positie t.o.v. 1x vergroting. Door step aan te passen (bijvoorbeeld step = 0 als verg == 2) kun je bijvoorbeeld focussen op een nieuw punt zonder opnieuw te zoomen.
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var verg:Number = 1;
var step:Number = 1;
function zoom(event:MouseEvent):void{
    verg+=step;
    var mc:Object = event.target;
    var newx:Number = 275 - (mc.x)*(verg); // zie a
    var newy:Number = 200 - (mc.y)*(verg);
    
    kaart.width/=(1-step/verg); // zie b
    kaart.height/=(1-step/verg);
    kaart.x=newx;
    kaart.y=newy;
    
    knoppen.width/=(1-step/verg);;
    knoppen.height/=(1-step/verg);
    knoppen.x=newx;
    knoppen.y=newy;
}

A ) De nieuwe positie is simpelweg het midden van de stage. Omdat je de container verplaatst en niet de knoppen zelf in hun container, wordt de nieuwe positie dus 275 - [positie van knop in container] * [huidige vergroting van container].
B ) De eigenlijke formule: width = [beginwidth] / [vorige uitrekking] * [nieuwe uitrekking] = width / (verg - step) * verg = width / (1 - step/verg). Immers vergnieuw = veroud + step (zie bovenaan ergens in code).

Resultaat: http://www.zshare.net/flash/28430372ad0b49/

[ Voor 42% gewijzigd door Bozozo op 25-07-2007 15:40 ]

TabCinema : NiftySplit


  • Neejoh
  • Registratie: Juni 2001
  • Laatst online: 24-04 18:27
He bozozo, dat lijkt er inderdaad op! AS3 is best goed te lezen, dat is het probleem niet. Toch ga ik proberen het terug te brengen naar AS2.
btw, line14 heb je een dubbele ;; staan

Flash ActionScript:
1
2
3
4
    kaart.width/=(1-step/verg); // zie b
    kaart.height/=(1-step/verg);
    kaart.x=newx;
    kaart.y=newy;

Als ik dus een tween toepas op de kaart.x met als nieuwe waarde newx (en op Y uiteraard), moet dit goed gaan. Nu zit ik alleen te kijken hoe ik een tween kan toepassen op de scaling omdat hier geen positie aan meegegeven kan worden en altijd vanuit punt 0,0 van de scalende MC gebeurd. Ook in de code van jou hierboven zal hij dus scheef wegtrekken.

Weet je een manier om het representationpoint van de MC via AS in het midden van een MC te krijgen? Dat is volgens mij de oplossing.

  • Bozozo
  • Registratie: Januari 2005
  • Laatst online: 20-02 16:10

Bozozo

Your ad here?

Nee dat zou ik zo niet weten. Heb je het al daardwerkelijk geprogrammeerd? Ik denk namelijk niet dat hij scheef weg gaat trekken zolang de scaling en verplaatsing tweens hetzelfde aantal frames meekrijgen.

edit: http://www.zshare.net/flash/2856785bffa703/
Dit is niet met tweens maar met een eigen ENTER_FRAME event handler, die start als je klikt en stopt als het target is bereikt. Uitzoomen en van plek naar plek 'schuiven' zonder te zoomen kan ook maar dan moet je wat uitzonderingen inbouwen en daar ben ik te lui voor.

[ Voor 44% gewijzigd door Bozozo op 26-07-2007 13:46 ]

TabCinema : NiftySplit

Pagina: 1