Kaste objekter ved å opprette en PanAndThrow Class

Throw objekter ved å opprette en PanAndThrow Class
Del
Del
Del
Del

Dette Cyber ​​mandag Envato Tuts + kurs vil bli redusert til bare $ 3. Ikke gå glipp av.

I denne opplæringen vil vi tentamen opp og etterbehandling en panne og kaste klasse som vil tillate oss å legge denne effekten til ethvert element vi ønsker. For å oppnå dette, vil vi lage en bildeviser - men ikke din gjennomsnittlige seer. Her vil vi ha zooming, kaste, panorering .. Nesten høres ut som en ninja app, he




Trinn 1: Innledning

Pan og Throw klasse vil tillate deg å legge pannen og kaste funksjonalitet til noen Action objektet du vil. Selv om denne opplæringen er spesielt for Flex, hvor som helst Action er klassen i seg selv kan brukes. Jeg hadde sett denne effekten på flere nettsteder, deretter i Photoshop CS4 og besluttet at jeg ville ha denne på mine prosjekter også

Det er mange bruksområder for denne effekten.; den som vi skal bruke for denne opplæringen er en bildeviser som lar deg zoome inn og ut av am bildet og endre friksjon som kastet effekt bruker. Imidlertid er denne opplæringen ikke egentlig om bildeviser, det handler om å gjøre en panne og kast klasse. Så la oss komme i gang med det. Åpne opp din favoritt Flex redaktør og få et prosjekt på gang; for informasjon om hvordan du gjør dette i Flex Builder se Adobe LiveDocs. Når prosjektet er opprettet, åpne MXML filen. Vi må legge til noen kode til dette før vi skaper vår klasse



Trinn 2:. Vår MXML

Siden dette ikke er den største delen av opplæringen jeg har ikke tenkt å tilbringer mye tid her. Hvis du har spørsmål om denne delen som ikke er dekket, kan du spørre i kommentarfeltet nedenfor. For det første, her er de MXML objekter for å sette i søknaden:?
≪ xml version = "1.0" encoding = "UTF-8" > < mx:? Søknad xmlns: mx = "http: //www .adobe.com /2006 /MXML "framerate =" 24 "layout =" absolutt "creationComplete =" init () "bakgrunnsfarge =" # 888888 "> < mx: Canvas id = "utenfor" height = "100%" width = "100%" verticalScrollPolicy = "off" horizontalScrollPolicy = "off" > < mx: Bilde id = "innsiden" source = "@ Bygg ('img /selfportrait.jpg')" creationComplete = "smoothImage (event);" /> < /mx: Canvas > < mx: ". 6" VBox id = "kontroll" bakgrunnsfarge = "# 000000" backgroundAlpha = height = "120" width = "200" cornerRadius = "5" Border = "solid" borderThickness = "0" top = " -5 "venstre =" - 5 "paddingTop =" 10 "paddingLeft =" 10 "> < mx: HSlider id = "hSlider" minimum = "10" maksimal = "200" value = "100" allowTrackClick = "true" liveDragging = "true" change = "zoom ()" /> < mx: Etikett color = "# aaaaaa" text = "Zoom" /> < mx: ". 7" HSlider id = "sldDecay" minimum = ". 1" maksimal = "1" value = allowTrackClick = "true" liveDragging = "true" change = "changeDecay ()" /> < mx: Etikett color = "# aaaaaa" text = "Decay" /> < /mx: VBox > < /mx: Application >

Du vil merke de fire funksjonene kalles i kodene: init (), changeDecay (), smoothImage () og zoom (). Vi trenger å skrive opp disse funksjonene. Dette er koden mellom < mx: script > tags:
import mx.states.SetStyle, importere mx.effects.Move, import mx.containers.HBox; import mx.containers.Box, privat Var imageWidth: Antall = 0; privat Var imageHeight: Antall = 0; private Var mover: Move = new Move (); //dette vil bli kalt når programmet loadsprivate funksjonen init (): void {//Dette arrangementet vil legge evnen til å skjule og vise våre kontroller med et klikk. control.addEventListener (MouseEvent.CLICK, controlClick); mover.target = kontroll;} //denne funksjonen vil zoome inn og ut av våre bildet i henhold til verdien av vår zoom slider.private funksjon zoom (): void {inside.width = (imageWidth * hSlider.value) /100; inside.height = (imageHeight * hSlider.value) /100;} //dette blir kalt når vårt bilde endrer size.private funksjon smoothImage (ev: Hendelses): void {//sett bildeutjevning slik bildet ser bedre når forvandlet. Var bmp: Bitmap = ev.target.content som Bitmap; bmp.smoothing = true; imageWidth = inside.width; imageHeight = inside.height;} //vi ikke skal bruke dette yetprivate funksjon changeDecay (): void {//dette vil endre forfall (friksjon) verdien av vår klasse, når vi kommer dit} privat funksjon controlClick (. e: MouseEvent): void {mover.play (); //denne funksjonen skjuler /viser kontrollene klikk hvis {mover.stop () (control.y = -5!); mover.yTo = -5; mover.play (); } Else if (e.target == kontroll) {mover.stop (); mover.yTo = (control.height - 10) * -1; mover.play (); }}

Når du har din MXML må du opprette en mappe som heter "klasser" i samme mappe som MXML filen. (Hvis du bruker Flash, må mappen være i samme dir som din FLA-fil.) Dette er vår klasser pakke og er der PanAndThrow.as filen vil gå. I Flex Builder, opprette en ny klasse, sette den i klasser pakken, og kaller det PanAndThrow; Dette vil skape din klasse - standardstil



Trinn 3:. makings av en klasse

Her er vår grunnleggende PanAndThrow klasse. Lagre den som PanAndThrow.as i din nye "klasser" -mappen.
//Navne declarationpackage klasser //klasse declarationpublic klasse PanAndThrow {/* dette kalles konstruktøren, denne metoden /funksjon vil bli kalt når du oppretter * en forekomst av objektet, eller instantiate objektet. * For denne klassen vi ikke gjøre noe fordi vi kommer til å gjøre alt * i Init funksjon * /public funksjon PanAndThrow () {}}

Hvilke variabler og funksjoner trenger vi i vår PanAndThrow klasse? For å få det, kan du spørre deg selv "hva gjør klassen min trenger å gjøre, hva det trenger å vite, og hva betyr det trenger å være i stand til å gjøre det?" Så la oss lage noen pseudo-kode.

Quick Note

Når jeg først utviklet denne klassen jeg hadde satt alt i konstruktøren, men som fører til et problem når jeg opprettet start- og stoppmetoder på grunn av omfanget. Jeg kunne ikke bruke denne klassen på en global omfang med all nødvendig informasjon. Jeg gjorde derfor en init () -funksjonen, så forekomsten kan startes og stoppes fra utenfor klassen



Trinn 4:. Vår Pseudo-kode

"Pseudo-koden" bare betyr falsk kode, som vi kan bruke til å hjelpe oss selv å tenke på hva ekte kode trenger vi.
pakke classespublic klasse PanAndThrow {/* Disse vil være de variablene som vi gjør. Så hva trenger vi å vite? * AnObjectToThrow; * AnObjectToThrowItIn; * ObjectLocation; * PreviousObjectLocation; * Forfall; //For fysikk * disse er opplagte, men denne listen vil få mye større * som vi ser akkurat det vi trenger i våre funksjoner * /public funksjon PanAndThrow () {} /* Så hva er vår klasse kommer til å gjøre ? * i det(); //det er behov for å starte * stop (); //Vi ønsker å være i stand til å stoppe det liksom. * begynne(); //Hvis vi stopper må vi være i stand til å starte den igjen. * panne(); * kaste(); * /}

Nå som vi har noen pseudo-kode vi kan begynne å bygge klassen. La oss starte med init () -funksjonen. Dette vil også føre oss inn i en av prinsippene for objektorientert programmering heter innkapsling
, som omhandler tilgangen av biter av koden.

Denne koden skal gå i PanAndThrow klassen vi ' har nettopp startet. (Ikke sikker på hvor? Sjekk ut Document Class Quick Tips.)
//Takket være OOP, et lavere nivå klasse og en øvre nivå klassen (en som strekker //lavere nivå klasse) kan brukes. Som her, nesten alle underlag du vil bruke forlenger //Sprite-klassen. Så jeg må bare be om en Sprite objekt, og du kan gi en boks eller et Button.private Var targetObject: Sprite = new Sprite (); privat Var eventObject: Sprite = new Sprite (); privat Var originalDecay: Number = 0,9; private Var buttonDown: Boolean = false; privat Var moveY: Boolean = true; privat Var Movex: Boolean = true; privat Var TargetClick: Boolean = true; //Vi vil bruke dette til å sjekke hvor lenge musen har vært nede på et objekt uten moving.private Var t: Timer, private Var timerInterval: int = 100; offentlig funksjon init (ObjectToMove: Sprite, ObjectToEventise: Sprite, DecayAmout: Number = 0,9, isMoveY: Boolean = sant, isMoveX: Boolean = sant, OnlyMoveOnTargetClick: Boolean = true): void {targetObject = ObjectToMove; eventObject = ObjectToEventise; originalDecay = DecayAmount; Movex = isMoveX; moveY = isMoveY; TargetClick = OnlyMoveOnTargetClick; t = new Timer (timerInterval); start ();}

Bare et par ting jeg ønsker å påpeke. I funksjonen for init har jeg satt noen av argumentene for å være lik en verdi. Det betyr at jeg gir dem en standardverdi, og dermed gjør dem ekstra. Når du stiller inn standardverdier for argumentene til en funksjon, må de være de siste parametrene - du kan ikke ha en nødvendig variabel etter en valgfri en. Grunnen til at jeg har lagt standard variabler er å ringe kortere hvis vi bruker standardinnstillingene. Jeg kan ringe PanAndThrow (mover, eventer); og bli ferdig, i stedet for PanAndThrow (mover, enventer, decayer, yVal, ...) og så videre.

Har du noen gang lurt på hva "privat" eller "offentlig" foran funksjoner og variabler midler ? Det er eksponeringen av objektet. En "offentlig" objekt kan nås av noen annen klasse; en "privat" objekt kan bare bli sett av de andre medlemmene av denne klassen; en "beskyttet" objekt er skjult for alt unntatt klasser som er i samme pakke.

Vi ønsker å være i stand til å endre forfall fra vår MXML så vi trenger en offentlig krok for å komme til vår private variable; det er her getter og setter-funksjoner kommer inn:
private Var originalDecay: Number = 0,9; offentlig funksjon får forfall (): Antall {return originalDecay;}

Det er en "getter" -funksjon. Det betyr at, til utenfor klasser, ser det ut som den PanAndThrow klassen har en offentlig variabel kalt "forfall". Når de prøver å få tilgang til det, vil vi komme tilbake til dem verdien av våre (privat) originalDecay variabel.

Setter funksjoner er nesten det samme, men tillater utenfor klasser for å endre verdien av vår "fake" public variabel:
offentlig funksjon satt råte (verdi: Number): void {originalDecay = verdi;}

Dette er nyttig fordi du kan sette logikken i en Settere å begrense hva som kommer inn i ditt private var. For eksempel, hvis du putter et nummer i MXML lappen for en boks du vil få et sett høyde; hvis du setter en% (noe som gjør nummer en streng) vil du få en prosentandel høyde. Som er bygd inn i koden for boksens høyde setter. Nå som vi har vår getter og setter du får tilgang til forfallet variabel som dette fra utenfor klassen:
Var pt: PanAndThrow = new PanAndThrow (); pt.init (mål, foreldre); pt.decay = 0,7;



Trinn 5: Start, Lytt, Stopp

Vi har vår klasse, noen lokale variabler og en init () -funksjonen. La oss gjøre noe nå. Ved slutten av init () -funksjonen vi kalte "start ();" så la oss gjøre starten funksjon. Stort sett er det bare en haug med lytterne:
offentlig funksjon start (): void {//Med musen ned, er vi ute etter å starte vårt pan handling, men vi må være i stand //å sjekke våre OnlyMoveOnTargetClick som vi tildelt til vår globale feltet TargetClick targetObject.addEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget); eventObject.addEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget); //Når vi kaller vår pan, bruker den en mus flytte lytteren, noe som betyr at det blir kalt hver gang //musen beveger seg, så vi må se hvordan vi kan begrense når målet objektet beveger. eventObject.addEventListener (MouseEvent.MOUSE_MOVE, MOVEIT); //Dette er å kaste objektet etter en pan, dette er litt vanskelig fordi throwIt () -funksjonen kaller en annen lytteren. targetObject.addEventListener (MouseEvent.MOUSE_UP, throwIt); eventObject.addEventListener (MouseEvent.MOUSE_UP, throwIt); //den throwItOut metoden gjør vårt objekt handle som om vi slipper museknappen, men det får sparken når //musen forlater ordnede objektet targetObject.addEventListener (MouseEvent.MOUSE_OUT, throwItOut); eventObject.addEventListener (MouseEvent.MOUSE_OUT, throwItOut); //Dette er timeren lytteren, dette vil sjekke om du har vært å holde musen ned for en liten stund, vil jeg //forklare behovet for dette når vi kommer til timerOut () -funksjonen t.addEventListener (Timerevent. TIMER, timerOut); t.start ();}

Holdeplassen () -funksjonen er nesten det samme, men vi skal ta lytterne
offentlig funksjon stop (): void {targetObject.removeEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget);. eventObject.removeEventListener (MouseEvent.MOUSE_DOWN, handleOverTarget); eventObject.removeEventListener (MouseEvent.MOUSE_MOVE, MOVEIT); targetObject.removeEventListener (MouseEvent.MOUSE_UP, throwIt); eventObject.removeEventListener (MouseEvent.MOUSE_UP, throwIt); targetObject.removeEventListener (MouseEvent.MOUSE_OUT, throwItOut); eventObject.removeEventListener (MouseEvent.MOUSE_OUT, throwItOut); t.removeEventListener (TimerEvent.TIMER, timerOut); t.stop ();}

Nå kan vi lytte til hva som skjer, la oss gå gjennom hver av disse lytter funksjoner



Trinn 6:. MouseEvent.MOUSE_DOWN

. Vi kommer til å være å se på handleOverTarget hendelseshåndterer
privat funksjon handleOverTarget (e: MouseEvent): void {buttonDown = true; arMousePrevX = MousePrevX = MouseCurrX = eventObject.mouseX; arMousePrevY = MousePrevY = MouseCurrY = eventObject.mouseY; if (e.currentTarget == targetObject || TargetClick!) {overTarget = true; } Else if (e.target.toString () søke (targetObject.toString ()). ≪ 0) {overTarget = false; }}

Denne funksjonen vil bli kalt når det er en MOUSE_DOWN hendelse på begge tilfelle gjenstanden eller målobjektet. Det er svært viktig å merke seg at hvis jeg setter en lytter på en overordnet objekt, føreren vil selv bli kalt når hendelsen inntreffer på et barn. I dette tilfelle min målobjekt er et barn av arrangementet objektet. Når jeg klikker på målobjektet denne metoden vil bli kalt to ganger: først for musen ned på barnet da andre for musen ned på den overordnede. Det er veldig viktig for dette fordi vi kommer til å være å avgjøre om musen ned vil være i stand til å flytte vår target objekt slik at vi virkelig trenger å være i stand til å vite om at musen ned var på barnet eller ikke.

Den første setningen er ganske grei: sette vår klasse variabel buttonDown å true

Den neste to er ganske lett også, uten at jeg har introdusert et par nye variabler som må bli satt i vår klasse variabel listen.: MousePrevX, MousePrevY, arMousePrevX, arMousePrevY, MouseCurrX og MouseCurrY. Disse vil bli brukt mye i drag og pan funksjonene, så jeg vil vente med å snakke om dem til da.

hvis setningen sjekker for å se om objektet klikket er målet objektet. Husk TargetClick ble satt til argumentet vi gått over til init (), OnlyMoveOnTargetClick; hvis dette er usant vi ønsker å behandle alle barn objekt som målobjektet når klikket. Det er derfor vi har "||! TargetClick" sjekk.

Det er den enkle delen. Den neste delen er litt mer komplisert.

e.currentTarget returnerer objektet som utløste hendelsen. Den e.target vil returnere objektet som var selve målet. Så jeg kan si dette, ikke sant
if (e.target == TargetClick targetObject ||!) {OverTarget = true;}? Else {overTarget = false;}

Det er enkelt nok, men det er feil. Hva om mitt mål objekt har barn? Da min e.currentTarget kan være targetObject men e.target er targetObject er barn og vil ikke matche. Vi ønsker at dette skal flytte selv om vi er å bevege musen ned på et barn objekt.

Så her kommer String.search til unnsetning. Hvis vår currentTarget er ikke vår targetObject, bruker vi en "else if" for å se om vi kan finne målet objektet i målet. e.target.toString () vil produsere noe sånt som dette: "application2.eventobject3.targetobject2.targetchild4" for vår målgruppe objekt hvor targetObject.toString () vil produsere noe som dette "application2.eventobject3.targetobject2" alt jeg trenger å gjøre for å finne ut om våre mål er et barn av vår targetObject er etter dette.
e.target.toString () søke (targetObject.toString ())

Hvis det er en kamp det vil returnere den første indeksen i kamp, ​​eller hvis det ikke er en kamp det vil returnere en -1, så vi kan bare se om det er større enn -1 og bratsj, vi har funnet hvis objektet blir klikket på er et barn av vår targetObject. Anmeldelser

(Vi kunne kontrollere barn eller forelder (e) til objektet via getChildAt () funksjon og foreldre eiendom, men dette er en ryddig alternativ.)



Trinn 7: TimerOut og Pan

Timerfunksjonen er ganske enkelt også, spesielt siden vi har gjort dette før. Vel, nesten gjort dette før. Når vi har dratt rundt vår lille targetObject litt og bestemmer vi ønsker ikke å la det gå, vi elsker det for mye, og brått stopper musen, hva som ville skje hvis du slipper museknappen på det punktet? vel, hva tror du vil skje? Jeg kommer ikke til å svare på det for deg, jeg bare kommer til å hjelpe deg med den koden for å holde det skjer. I den siste koden, kommentere disse tre linjene ut. Dette bør se veldig kjent, vi bare brukte dette i knappen nede handler, med unntak av én variabel, MouseDragged. Vi kommer til å bruke det når vi kaller vår annen funksjon:
privat funksjon timerOut (e: Timerevent): void {MouseDragged = false; arMousePrevX = MousePrevX = MouseCurrX = eventObject.mouseX; arMousePrevY = MousePrevY = MouseCurrY = eventObject.mouseY;}

Så hvis du spør hvorfor vi trenger denne timeren hendelsen, har du sannsynligvis ikke prøve og ta den ut for å se hva som skjedde. Så gjør det.

Denne neste funksjonen er en av våre viktigste funksjoner; er det pan-funksjonen. Det er mye involvert så la oss dykke inn i vår pseudo-kode:
privat funksjon MOVEIT (e: MouseEvent): void {/* ok, så hva gjør vi trenger denne funksjonen til å gjøre? * det er behov for å panorere målet vårt objekt. * så kan se om vi er over målet vårt objekt * ///if (vi er over målet vårt objekt) //{//hvilke verktøy som vi kommer til å trenge å panorere? //Vel, kanskje vi bør sjekke for å se om den knappen er nede //if (knappen er nede) //{//vi kanskje trenger å sette knappen nede variabel. buttonDown = true; //Og hvis vi er i denne funksjonen på dette punktet vår knappen er nede og //musen har flyttet - det er en hemsko: så MouseDragged = true; //Hvis vi flytter objektet i henhold til musen flytte så vi bør //sikkert vet hvor vår mus er: MouseCurrX, Y = aktuell MouseX, Y; //Dette er en innføring i vår kunstig mus forrige, som vil bli forklart //i neste funksjon. Den ar står for "kunstig" eller "etter release", //avhengig av hva du foretrekker. Som må stilles til våre faktiske tidligere muse pos. //ArMousePrevX = MousePrevX; //ArMousePrevY = MousePrevY; //Så vi må faktisk flytte targetObject, //men husk våre variabler, Movex og moveY, så: //hvis Movex flytte x; //Hvis moveY flytte y; //Vi trenger å tilbakestille våre Decay (friksjon) tilbake til den opprinnelige tilstanden: //Decay = originalDecay; //Som bør avslutte hvis //} //hva annet? //{//Vi setter vår buttonDown til sann før, så lar sette den til false her. //buttonDown = false; //Hvis dette ikke er et mål klikk, bør vi sette vår overTarget til false slik: //if (! TargetClick) //overTarget = false; //det er alt. //} //Det er et par ting som vi ønsker skal skje uavhengig av forholdene. //Først, må vi sette vår mousePrevX, Y variabel - FØR musen //flyttet igjen! //MousePrevX = eventObject.mouseX; //MousePrevY = eventObject.mouseY; //Her er to variabler å holde styr på: xOpposideEdge og yOppositeEdge //vi tester for å se hva størrelsen på målet objekt er i forhold //til vårt arrangement objekt; hvis man er større vi trenger å endre oppførselen til sprett. //If (targetObject.width > eventObject.width) {xOppositeEdge = true;} //else {xOppositeEdge = false;} //if (targetObject.height > eventObject.height) {yOppositeEdge = true;} //annet {yOppositeEdge = false;} //og til slutt må vi stoppe og starte tidtakeren vår. //t.stop (); //t.start();//}

I innrømme dette er en litt mer psuedo-y enn sist; som er av to grunner: en, du vet ikke hva som kommer, og to, jeg er bare veldig glade for å få til koden:
privat funksjon MOVEIT (e: MouseEvent): void {//i vår pseudo -code dette var to forhold, men vi kan kombinere deretter til en, //vi teste for å se om vårt arrangement var en knapp nede, og hvis vi er over vårt mål, //hvis vi blir så la oss gå målobjektet. if (e.buttonDown & & overTarget) {buttonDown = true; MouseDragged = true; MouseCurrX = eventObject.mouseX; MouseCurrY = eventObject.mouseY; //Her er kunstig /etter frigjøre én. igjen, godt komme til det. arMousePrevX = MousePrevX; arMousePrevY = MousePrevY; /* Dette er den viktigste, i vår pseudo var det "flytte målet objekt", * så vi trenger å oversette det. For å hjelpe oss vi vil opprette en lokal variabel * Topper for toppen, og Sider for siden. * Så la oss se på Topper (det samme vil gjelde for Sider). * EventObject.mouseY ser på hvor vår mus er innsiden av eventObject. * Vi tar vår MousePrev bort fra det, og som vil gi oss hvor mye objektet * bør reise, slik at Y kan reise 2 piksler, eller -2 piksler avhengig * retning, så vi tar denne endringen og legge den til målets strøm * posisjon, men det skjer ikke ennå, dette er bare en var. * /Var Topper: int = (eventObject.mouseY - MousePrevY) + targetObject.y; Var Sider: int = (eventObject.mouseX - MousePrevX) + targetObject.x; //Her er der det skjer, hvis moveY (husker fra pseudo-kode) så vi //kan angi posisjonen til målet. if (moveY) {targetObject.y = Topper;} if (Movex) {targetObject.x = Sider;} //så egentlig vi bare bruker Topper og Sider å midlertidig lagre hvor //målobjektet skal flytte til Decay = originalDecay; } Else {buttonDown = false; if (TargetClick!) overTarget = false; } MousePrevX = eventObject.mouseX; MousePrevY = eventObject.mouseY; if (targetObject.width > eventObject.width) {xOppositeEdge = true;} else {xOppositeEdge = false;} if (targetObject.height > eventObject.height) {yOppositeEdge = true;} else {yOppositeEdge = false;} t. stoppe(); . t.start ();}

Og nå er vi panorering



Trinn 8: Kast, It, Out, etter

Dette er Repeater den andre store funksjon og med! Dette vil vi ha vår klasse bygget! Klar til å panorere og kaste en gjenstand du ser passer! Det er to funksjoner som vi trenger for å løse først:. ThrowIt (), som vi satt som et behandlingsprogram for MOUSE_UP hendelsen, og throwItOut (), som vi satt som et behandlingsprogram for MOUSE_OUT hendelsen
privat funksjon throwIt (e : MouseEvent): void {buttonDown = false; if (MouseDragged) {eventObject.addEventListener (Event.ENTER_FRAME, theRepeater); }} privat funksjon throwItOut (e: MouseEvent): void {buttonDown = false; if (e.relatedObject == null || e.relatedObject == eventObject.parent) {eventObject.addEventListener (Event.ENTER_FRAME, theRepeater); }}

Disse to funksjonene er nesten det samme (tross alt, de gjør det samme bare på ulike tidspunkt). I dem setter vi buttonDown til falske, fordi dette er en mus opp hendelsen, og sjekk for å se om musen ble dratt, enten ved hjelp MouseDragged (som vi satt i den siste funksjon) eller ved å sjekke "e.relatedObject"; objektet at musen nettopp flyttet ut av.

Hvis det ble dratt vi legge til en annen lytter. Den ENTER_FRAME arrangementet er en veldig kul en. Dette er grunnlaget for vår animasjon; hver gang vi går inn i en ny ramme innkastet () -funksjonen vil bli kjørt. Det er det som gjør at vi kan simulere en mus dra etter løslatelse (husker arMousePrevX, Y variabel? Det er hva det er for). Og det er alt kastet er virkelig gjør, simulere en mus dra, uten mus selvfølgelig. Så vi har ganske mye allerede fått funksjonen vi trenger, bortsett fra at vi må bytte ut samtaler til gjeldende muse stilling til vår kunstig mus posisjon.

Nesten fikk litt foran meg selv der. Så med disse to hendelses funksjoner, throwIt og throwItOut, de gjør det samme, men at hvis
i den andre funksjonen er verdt å nevne. Jeg slet en stund prøver å få denne funksjonaliteten, før jeg så på hendelsen litt nærmere. Problemet prøvde å få målet objekt til å handle som om jeg slipper knappen når markøren til venstre arrangementet objektet. Gå videre, prøve og gjøre dette uten e.relatedObject. Jeg hadde nesten det et par ganger, men klarte ikke å få det riktig. Hva e.relatedObject gjør er finner det objektet du er på, etter hendelsen kalles. Det er derfor det er såååå kult. Når vår markøren forlater filmen helt, returnerer den en null, ellers vil den returnere objektet du er på, slik at vi kan sjekke for å se om e.relatedObject er null eller er en forelder til eventObject. Som produserer den riktige handlingen vi leter etter.

I de ovennevnte funksjoner setter vi opp samtaler til theRepeater (). Dette vil være innkastet funksjon, og husk at det vil bli kalt hver gang vi går inn i en ny ramme. La oss gå gjennom dette linje for linje:
privat funksjon theRepeater (e: Hendelses): void {//timeren må stoppes, kan du prøve å fjerne dette og se hva som skjer. t.stop (); //Her er en lokal variabel som vil holde dagens (falske) markørposisjon. //Vel det er bare "fake" etter første omgang. Var oldxer: Number = MouseCurrX; Var oldyer: Number = MouseCurrY; //Nå, akkurat som vi gjorde før, vi trenger å finne forskjellen mellom vårt nåværende //og forrige posisjon. så hvordan er dette forskjellig fra før? hvorfor? Var xDiff: Number = MouseCurrX - arMousePrevX; Var yDiff: Number = MouseCurrY - arMousePrevY; //Hvis knappen er nede, vi kommer ikke til å flytte noe mer, vil knappen stoppe handlingen i dette tilfellet. if (buttonDown!) {//ta forskjellen og ganger det med forfallet. Dette vil gi oss den nye //forskjell, noe som vil være litt mindre enn den siste, som er slik //vi får friksjonseffekten med dette. //F.eks hvis Decay er 0,5 da avstanden flyttet vil halvere hver ramme. xDiff = xDiff * Decay; yDiff = yDiff * Decay; //Neste er en av de forvirrende deler til meg, betyr ikke flytte objektet på //tatt, det bare tester for å se om vår targetObject har nådd kanten. hvis den har, //vi trenger å sprette den tilbake. (dette kan endres til en annen handling hvis du //vil, kan du selv fjerne det, hva skjer hvis du gjør? prøve det! //i pannen funksjon vi setter denne variabelen, OppositeEdge, dette er hvor vi vil //bruke at "hvis targetObject er større enn hendelses Object" som vi satt i //init () -funksjonen. Jeg bare kommer til å gå gjennom x her fordi y er //nesten det samme (hva er annerledes? hvorfor ? tenke på det) if (xOppositeEdge) {/* slik at den første "bredden på eventObject, - bredden av targetObject - 50"!, * her, er bredden på targetObject større enn den for den eventObject * denne vil tillate motsatt kant av målobjektet å være 50 px i fra * motsatt kant. Hvis du går til eksempel film og krympe bildet til * 10% og kaste den rundt, deretter øke størrelsen til 200% og prøve og varsel * hva edge som gjør hva, så vil du se forskjellen mellom de spretter. * Det er den beste måten å forstå denne delen. * /If (targetObject.x < (eventObject.width - targetObject.width - 50)) {xDiff = -1 * xDiff; targetObject.x = eventObject.width - targetObject.width - 50; } //Gjør dette det samme for den andre kanten. if (targetObject.x > 50) {xDiff = -1 * xDiff; targetObject.x = 50; }} //Dette er om måleobjektet er mindre enn eventObject. else {/* så igjen vi skal teste kantene av targetObject mot * arrangementet objektet. Denne gangen vi har å gjøre med den samme kanten (vel, * 5px utenfor kanten). Så dette vil sprette ut som det er å treffe en vegg. * /If (targetObject.x < -5) {xDiff = -1 * xDiff; targetObject.x = -5; } If (targetObject.x > (eventObject.width - (targetObject.width - 5))) {xDiff = -1 * xDiff; targetObject.x = eventObject.width - (targetObject.width - 5); }} If (yOppositeEdge) {if (targetObject.y < (eventObject.height - targetObject.height - 50)) {yDiff = -1 * yDiff; targetObject.y = eventObject.height - targetObject.height - 50; } If (targetObject.y > 50) {yDiff = -1 * yDiff; targetObject.y = 50; }} Else {if (targetObject.y < -5) {yDiff = -1 * yDiff; targetObject.y = -5; } If (targetObject.y > (eventObject.height - (targetObject.height - 5))) {yDiff = -1 * yDiff; targetObject.y = eventObject.height - (targetObject.height - 5); }} //Vel, hvis du har spørsmål om den del, bare legge inn en kommentar om det, og jeg vil svare på dem. //Her er sider og Topper vars (akkurat som de fra den pan-funksjonen). Var sider: int = xDiff + targetObject.x; Var Topper: int = yDiff + targetObject.y; //Vi må sette dette klart for neste gå rundt. MouseCurrX = MouseCurrX + xDiff; MouseCurrY = MouseCurrY + yDiff; //Og deretter hvis Movex, Y (igjen som den pan-funksjon) if (moveY) {targetObject.y = Topper;} if (Movex) {targetObject.x = sider; } //Og nå satt vår kunstig mus forrige arMousePrevX = oldxer; arMousePrevY = oldyer; //Og hvis vi ikke er i friksjonsfri modus (OriginalDecay = 1) //vi kommer til å trekke et lite beløp fra vår forfall, til //gir det litt mer naturlig lettelser. if (originalDecay < 1) {Decay = Decay - 0,004; } //Slik at det bevegelige gjøres. } //Hvis knappen er nede vi må fjerne lytteren. else {eventObject.removeEventListener (Event.ENTER_FRAME, theRepeater); } //Nå trenger vi å sjekke om effekten er over, noe som er om våre x og y differ er mindre enn 1px. if ((Math.abs (xDiff) < 1 & & Math.abs (yDiff) < 1)) {eventObject.removeEventListener (Event.ENTER_FRAME, theRepeater); }}

Og med det, er vår klasse ferdig



Trinn 9:. Den Fullført Klassekode

Du kan hente den ferdige koden fra Source zip, knyttet til toppen av opplæringen. Det er i PanAndThrow.as klassen



Trinn 10:. Gjør noe med
det

For å gjøre noe med dette må vi gå tilbake til MXML og legge til et par linjer med kode . Legg vår erklæring i den globale variable delen, fyll i forfall metoden og ringe vår pan og kaste init () -funksjonen. Med alt som tilsettes, her er den komplette MXML filen:?
≪ xml version = "1.0" encoding = "utf-8" > < mx:? Søknad xmlns: mx = "http: //www. adobe.com/2006/mxml "framerate =" 24 "layout =" absolutt "creationComplete =" init () "bakgrunnsfarge =" # 888888 "> < mx: Script > <! [CDATA [import mx.states.SetStyle; import mx.effects.Move; //Husk å importere vår nye klassen! import classes.PanAndThrow; import mx.containers.HBox; import mx.containers.Box; //Her vi initial vår pan og kaste klasse offentlig Var pt: PanAndThrow = new PanAndThrow (); private Var imageWidth: Antall = 0;