Zoom in op je eigen canvas met inhoud

Bij sommige schilderijen moet je van dichterbij kijken om alle details te zien. Stel nu in plaats van een schilderij een leeg canvas voor dat gevuld kan worden met afbeeldingen en tekst en dynamische beschrijvingen.

We vonden deze geweldige auteur dankzij FlashGameLicense.com, dé plek om Flash-spellen te kopen en verkopen.

Notitie: Deze zelfstudie heeft niets te maken met het HTML5-canvaselement!


De demo is een viewertoepassing die zijn gegevens laadt vanuit XML. Inhoud wordt op het "canvas" geplaatst en de gebruiker kan inzoomen op het canvas of op een van de afbeeldingen klikken om het op het scherm te centreren. Instellingen zoals paginaformaat, achtergrondkleur / textuur en andere instellingen worden dynamisch geladen. Als een bonus kan de gebruiker meerdere pagina's maken.

In deze tutorial zullen we kijken naar de basisconcepten van het maken van een dergelijke applicatie. Het is raadzaam om de broncode naast je te houden tijdens het lezen van de tutorial, omdat niet elk onderdeel wordt uitgelegd. De broncode is beschikbaar voor gebruik met FlashDevelop of met Flash CS3 Professional en hoger.


Opmerking: de applicatie lokaal openen

Houd er rekening mee dat voordat u de toepassing vanaf uw vaste schijf probeert te openen, u deze moet toevoegen aan de lijst met "vertrouwde locaties" die is gespecificeerd in het hieronder getoonde venster Algemene beveiligingsinstellingen. Anders wordt geen toegang verleend om de afbeeldingen van uw harde schijf te pakken. Dit is niet nodig bij het uploaden naar een website zolang de afbeeldingen zich op dezelfde webserver bevinden.


Stap 1: Het XML-bestand instellen

Als u niet bekend bent met XML, bekijk dan de AS3 101: XML van Dru Kepple. Hieronder worden de XML-gegevens weergegeven die overeenkomen met één pagina die is gevuld met één afbeelding en één tekstveld. De hier opgegeven instellingen zijn van toepassing op alle pagina's. Zoals u ziet, wordt het maken van meerdere pagina's en het toevoegen van inhoud aan hen gemakkelijk gemaakt. Voor afbeeldingen kunt u een titel en beschrijving toevoegen die zichtbaar is wanneer u met de muis over het scherm beweegt. Meerregelige tekst wordt toegevoegd en de grootte en stijl kunnen worden aangepast. Elk tekstveld gebruikt een aangepast lettertype dat wordt gevonden in het FLA-bestand.

    0x000000 … /afbeeldingen/ 580 380 2000 1300 0xEEDEC0 0xC1C59C 10 10     Hallo daar en welkom bij de demonstratie van de canvas-applicatie. Gebruikt als onderwerp hier is mijn vakantie naar Kopenhagen. anno 2010. Voel je vrij om de teksten te lezen en de cultuur op te snuiven.  23 470 50   Kerk en meer De prachtige omgeving in Kastelskirken. Church_And_Lake.jpg 1 750 500   

Stap 2: De klasse Document en Canvas

Gebruik de volgende code om onze applicatie in te stellen. Het wordt bijna volledig gegenereerd door FlashDevelop met behulp van de sjabloon "AS3 Project". Hoofd is de documentklasse - die de eerst geladen klasse is bij het starten van de flits - en binnenin Canvas we bouwen onze applicatie.

 public class Hoofd breidt uit openbare functie Main (): void if (stage) init (); else addEventListener (Event.ADDED_TO_STAGE, init);  private function init (e: Event = null): void removeEventListener (Event.ADDED_TO_STAGE, init); // beginpunt var canvas: Canvas = nieuw Canvas (this); 

En een simplistische versie van Canvas. Merk op dat we een weergaveobjectcontainer als een parameter gebruiken om dat extra besturingselement toe te voegen om het Canvas toe te voegen of te verwijderen.

 public class Canvas breidt uit openbare functie Canvas (container: DisplayObjectContainer) // parameter opslaan lokaal this.container = container; // Toevoegen aan container container.addChild (this); 

Stap 3: Bulk Loader gebruiken om assets te laden

In deze toepassing gebruiken we de zogenaamde BulkLoader: een AS3-bibliotheek die het laden en beheren van complexe laadvereisten eenvoudiger en sneller wil maken. Bij het voor het eerst laden, gebruiken we het om het XML-bestand en een achtergrondafbeelding te pakken. De volgende code laat zien hoe u de BulkLoader en voeg twee items toe aan de laadwachtrij. De Compleet functie wordt aangeroepen wanneer alle items zijn geladen.

 // Init loader loader = nieuwe BulkLoader ("Canvas"); loader.add ("... /background.jpg", id: "background"); loader.add ("... /settings.xml", id: "xmldata"); // Loader-gebeurtenissen loader.addEventListener (BulkLoader.COMPLETE, Complete, false, 0, true); loader.addEventListener (BulkLoader.ERROR, HandleError, false, 0, true); // Start loader loader.start ();

Stap 4: De geladen activa opslaan

We slaan de geladen items in de klas op voor later gebruik. De BulkLoader biedt een eenvoudige manier om de items te pakken die we nodig hebben. Roep gewoon de functie aan die overeenkomt met het type object en gebruik de ID-tekenreeks van het object. Statische variabelen worden gebruikt om de XML-gegevens globaal beschikbaar te maken (bijvoorbeeld toegang tot een statische variabele met behulp van Canvas.viewerWidth). De pad variabele geeft aan waar de extern geladen afbeeldingen zich bevinden. Afbeeldingen kunnen alleen vanaf de eigen webserver worden geladen vanwege beveiligingsbeperkingen.

 // Krijg achtergrondafbeelding g_background = (loader.getBitmap ("background")). BitmapData; // XML-gegevens ophalen xmldata = loader.getXML ("xmldata"); // Statische vars instellen voor eenvoudige toegang viewerWidth = int (xmldata.settings.viewer_width); viewerHeight = int (xmldata.settings.viewer_height); viewerBgColor = uint (xmldata.settings.viewer_bg_color); path = String (xmldata.settings.image_path); customFont = new customFontClass (); contentWidth = int (xmldata.settings.content_width); contentHeight = int (xmldata.settings.content_height); // Remove complete listener loader.removeEventListener (BulkLoader.COMPLETE, Complete); // Verwijder alle gegevensverwijzingen die zijn opgeslagen in de loader loader.clear (); // Verwijder de lader uit het geheugen loader = null; // Stel viewer in InitialiseViewer ();

Stap 5: Introductie van de virtuele camera

Zoals je wel of niet raadde, maakt de applicatie gebruik van een virtuele camera om een ​​deel van het canvas uit te pakken en aan de gebruiker te tonen. De camera past schaal en vertaling toe op een weergaveobjectcontainer zodat alleen het gebied onder de camera op het scherm wordt weergegeven. De volgende demonstratie geeft u een beter idee van hoe het werkt.

De broncode van deze demonstratie is ook opgenomen in het archief. Laten we dit voorbeeld uitleggen door te beginnen met het configureren van de instellingen. We willen dat het kijkersgebied 305 x 230 is en het inhoudsgebied - de afmetingen van het bloembeeld - moet proberen de beeldverhouding van het kijkgebied te behouden, zodat het niet te veel vervormt. Onze bloem is 1000 x 750, wat dichtbij genoeg is. Om de hele bloem in de kijkerregio te tonen, moet de camera dezelfde grootte hebben als de bloem, die 1000 x 750 is.

De volgende code stelt de dimensie-instellingen in. In dit voorbeeld zijn ze hard gecodeerd, maar anders is het overgenomen van XML.

 // Instellingen viewerWidth = 305; viewerHeight = 230; contentWidth = 1000; contentHeight = 750;

Vervolgens maken we een viewer-container. De optie scrollRect wordt gebruikt om alles buiten een opgegeven rechthoek af te knippen. Dit is erg handig omdat slechts een deel van het canvas moet worden getoond wanneer wordt ingezoomd. Het is een nettere oplossing dan bijvoorbeeld het plaatsen van een zwarte rand rond de applicatie..

 // Viewer container viewerContainer = nieuwe Sprite (); viewerContainer.scrollRect = new Rectangle (0,0, viewerWidth, viewerHeight); addChild (viewerContainer);

Aan de kijkercontainer voegen we nog een toe sprite riep viewerScroller. De functie van viewerScroller is gewoon om te fungeren als een container voor alles dat als inhoud voor de camera moet dienen. Het maakt het gemakkelijker om meerdere items aan de inhoudregio toe te voegen.

 // Pagina-scroller var viewerScroller: Sprite = nieuwe Sprite (); viewerContainer.addChild (viewerScroller);

Voeg inhoud toe aan de viewerScroller. In dit geval het bloembeeld.

 // Inhoud inhoud = nieuwe Sprite (); viewerScroller.addChild (inhoud); var bmp: Bitmap = nieuwe afbeelding (); content.addChild (BMP);

Voeg nu de Camera klasse. Hoewel we het nog moeten maken Camera klasse, de constructor neemt de dimensies van de kijker als parameter en de functie Bepaal doel heeft de inhoud sprite als parameter. We positioneren de Camera in het midden van de inhoud en geef het een eerste update.

 // Voeg virtuele camera toe cam = nieuwe Camera (viewer Wide, viewerHeight); cam.SetTarget (viewerScroller); cam.x = contentWidth / 2; cam.y = contentHeight / 2; cam.Update ();

Met al deze code kunnen we de camera renderen en manipuleren. Binnen een Event.ENTER_FRAME loop die je zou kunnen uitvoeren cam.Update () om de cameraweergave te vernieuwen. Het is echter efficiënter om alleen bij een wijziging bij te werken. Door te veranderen cam.x en cam.y je kunt de camera verplaatsen en veranderen cam.scaleX en cam.scaleY je kunt de schaal veranderen. Dit is precies wat de klaviertoetsen in het voorbeeld doen.


Stap 6: Camera Class A Closer Look

Hier kijken we naar de binnenkant van de Camera. In de constructorfunctie voegen we enkele grafische afbeeldingen toe die nodig zijn voor het manipuleren van de schaal van de schaal van de camera. We slaan de inhoudsmaten van de kijker ook lokaal op in de klas.

 openbare functie Camera (breedte: int, height: int, initialZoom: Number = 1) // Sprite gebruikt om de camera een breedte en hoogte te geven. g = nieuwe vorm (); g.graphics.drawRect (0, 0, 10, 10); g.graphics.endFill (); addChild (g); // Stel dimensies in van kijkerrechthoek tw = breedte; th = hoogte; // Initiële zoom this.scaleX = this.scaleY = initialZoom; 

Verbind de camera vervolgens met een voorwerp. De camera krijgt dezelfde schaal als het object.

 openbare functie SetTarget (doel: Sprite): void this.target = target; // pas de afmetingen van de camera aan g.width = target.width; g.hoogte = doel.hoogte; 

Dit is het meest interessante deel en de motor van de camera. Schalen en vertalen wordt toegepast op het object dat aan de camera is bevestigd door het een nieuwe transformatiematrix te geven. Bekijk de Matrix klasse in de AS3-documentatie voor meer informatie over het gebruik van matrices.

 public function Update (): void cw = this.width; ch = deze hoogte; tscaleX = tw / cw; tscaleY = th / ch; // nieuwe schaalwaarden aanbrengen mat.a = tscaleX; mat.d = tscaleY; // nieuwe waarden voor de nieuwe positie zetten. // de camerapositie wordt negatief gemaakt, omdat bijvoorbeeld wanneer de camera naar rechts beweegt, moet de pagina naar links bewegen om plaats te bieden. // cw en ch worden toegevoegd om de pagina naar het midden van het weergavegebied te verplaatsen // alle posities worden overeenkomstig geschaald mat.tx = (-mat.tx + cw / 2) * tscaleX; mat.ty = (-mat.ty + ch / 2) * tscaleY; target.transform.matrix = mat; 

Stap 7: De viewer instellen

We keren terug naar onze applicatie. In deze stap leggen we de basis voor de zogenaamde Pagina objecten die het canvas met afbeeldingen en tekst bevatten. Maak eerst een achtergrond voor de hele applicatie. De kleur wordt gespecificeerd vanuit XML.

 // Achtergrond var bg: Sprite = nieuwe Sprite (); bg.graphics.beginFill (xmldata.settings.bgcolor); bg.graphics.drawRect (0, 0, stage.stageWidth, stage.stageHeight); bg.graphics.endFill (); addChild (bg);

Zoals in het voorbeeld met de Camera en de bloem, die we gebruiken pageContainer en pageScroller en Camera. Dit moet redelijk bekend voorkomen.

De volgende is het toevoegen van alle Pagina objecten vereist zoals gespecificeerd in de XML. In ons voorbeeld hebben we slechts één pagina gemaakt. Merk op dat de Pagina klasse bestaat nog niet, omdat we deze de volgende stap maken. pagina's is een array die alles vasthoudt Pagina referenties voor later gebruik.

Parameters gebruikt door Pagina zijn

  • pageScroller: de sprite waarop het Pagina zal worden toegevoegd aan
  • p: een XML-gegevensobject met alle informatie binnen een bepaalde pagina (alle afbeeldingen en tekst)
  • g_background: de achtergrondstructuur
 // Pagina's pagina's toevoegen = nieuwe matrix (xmldata.page.length ()); voor elk (var p: XML in xmldata.page) var id: int = int (p.attributes () [0]); pagina's [id] = nieuwe pagina (pageScroller, p, g_background); 

Stap 8: Een pagina maken

Hieronder wordt de constructor weergegeven van Pagina. We bewaren eenvoudig alle parameters lokaal in de klas voor later gebruik.

 public function Page (container: DisplayObjectContainer, data: XML, background: BitmapData) this.id = id; this.container = container; this.data = data; this.background = achtergrond; this.title = String (data.attributes () [1]); 

Nu een beetje meer interessant spul. De Laden functie van Pagina begint door de achtergrondstructuur te nemen die we eerder hebben geladen en deze over het canvas te wikkelen. Om dit te doen, moeten we de grootte van de achtergrondafbeelding die we in een lus hebben en de grootte van het hele canvas weten. Maak een sprite riep g_background welke functioneert als een grafische container. Voeg een effen achtergrondkleur toe om te voorkomen dat lijnen tussen de bitmapafbeeldingen worden weergegeven.

 var b: int = background.width; var h: int = background.height; var trueWidth: int = Canvas.contentWidth; var trueHeight: int = Canvas.contentHeight; // achtergrondlaag g_background = nieuwe Sprite (); addChild (g_background); // Een vaste achtergrondkleur var bg: Sprite = nieuwe Sprite (); bg.graphics.beginFill (Canvas.viewerBgColor); bg.graphics.drawRect (0, 0, trueWidth, trueHeight); bg.graphics.endFill (); g_background.addChild (bg);

Bij het wikkelen van de achtergrondstructuur worden twee lussen gebruikt, alleen verticaal en één horizontaal. Het blijft lussen totdat de rand is bereikt. Elke tegel op een even positie - zoals (2,2), (4,2), (4,6) et cetera - wordt omgedraaid met behulp van scaleX of scaleY. Hierdoor gaat de textuur naadloos over in de volgende. Controleren of een getal even is, gebeurt met de modulo-operator (%). Als de rest van een getal na het delen met 2 nul is, moet dat getal gelijk zijn. Rond de randen knippen we elke structuur af die buiten de inhoudsmaten valt zoals gespecificeerd in trueWidth en trueHeight. Het is belangrijk dat de Pagina object blijft zo groot omdat als u het groter maakt, de beeldverhouding verandert en het scherm vervormt.

 // Voeg een looped-achtergrondafbeelding toe var i: int, j: int; terwijl (i * b < trueWidth)  j = 0; while (j * h < trueHeight)  // new bitmap var s:Bitmap = new Bitmap(background); // position s.x = i * b; s.y = j * h; // alternate horizontal and vertical flip if (i % 2 != 0)  s.scaleX *= -1; s.x += b;  if (j % 2 != 0)  s.scaleY *= -1; s.y += h;  // clip if (i * b + b > trueWidth || j * h + h> trueHeight) var clipw: int = Math.min (trueWidth - i * b, b); var cliph: int = Math.min (trueHeight - j * h, h); var nbd: BitmapData = nieuwe BitmapData (clipw, cliph); nbd.copyPixels (background, new Rectangle (0, 0, clipw, cliph), new Point ()); s.bitmapData = nbd; if (s.scaleX == -1) s.x - = b - clipw; if (s.scaleY == -1) s.y - = h - cliph;  // bitmap toevoegen aan weergavelijst g_background.addChild (s); j ++;  i ++; 

Het resultaat van de herhalende achtergrond zou zoiets moeten zijn. Donkere randen worden toegevoegd voor de duidelijkheid.


Stap 9: tekst laden

Laten we onze vullende reis beginnen door tekst toe te voegen. Doorloop alle XML-items met het label "tekst" en geef hun gegevens door aan de Voeg tekst toe functie.

 texts = new Array (); voor elk (var text: XML in data.text) AddText (text); 

De Voeg tekst toe functie ziet er zo uit. Het eerste deel van de code valideert de XML-gegevens. Als sommige velden niet zijn ingevuld, wordt een standaardwaarde toegevoegd. QuickText is een klasse die wordt gebruikt om een ​​tekstveld te maken met bepaalde opties. Ten slotte moet de tekst worden uitgesloten van muisinteractie door te gebruiken mouseEnabled = false en mouseChildren = false.

 persoonlijke functie AddText (text: XML): void if (! text.font) text.font = null; if (! text.size) text.size = 12; if (! text.color) text.color = 0x000000; if (! text.bold) text.bold = 0; if (! text.italic) text.italic = 0; var qt: QuickText = nieuwe QuickText (text.x, text.y, String (text.content), Canvas.customFont, int (text.size), uint (text.color), Boolean (text.bold), Boolean ( text.italic)); qt.blendMode = BlendMode.LAYER; texts.push (qt); addChild (qt); qt.mouseEnabled = false; qt.mouseChildren = false; 

De volgende afbeelding toont alle opties van de QuickText klasse:

En het resultaat van de nieuwe pagina inclusief tekst:


Stap 10: Afbeeldingen laden

De eerste stap hier is om te creëren afbeelding objecten die de XML-gegevens, de bitmap en een beschrijvende tekst bevatten. Luisteraars worden direct toegepast voor muisinteractie. Al deze afbeelding objecten worden vervolgens in een array opgeslagen om later gemakkelijk toegankelijk te zijn.

 // pak alle afbeeldingen vast = nieuw Array (); voor elk (var image: XML in data.image) // nieuw beeldobject met informatie erin var picture: Picture = new Picture (afbeelding); pictures.push (afbeelding); // luisterers toevoegen aan picture.addEventListener (MouseEvent.MOUSE_OVER, PictureMouseOver); picture.addEventListener (MouseEvent.MOUSE_OUT, PictureMouseOut); picture.addEventListener (MouseEvent.MOUSE_DOWN, PictureMouseDown); 

En hier is de basisversie van de afbeelding klasse, alleen met de XML-gegevens. afbeelding strekt sprite, we kunnen het al ergens plaatsen. De schaalinstelling is geverifieerd voordat deze wordt gebruikt, omdat als de gebruiker deze weglaat uit de XML, deze 0. retourneert. De standaardwaarde voor schaal is 1.

 openbare functie Afbeelding (gegevens: XML) title = data.title; description = data.description; url = data.url; page = data.page; x = data.x; y = data.y; if (Number (data.scale)! = 0) imgscale = Number (data.scale); 

Maak een nieuw BulkLoader net zoals de eerste keer, maar nu om batches met afbeeldingen te laden. We laden 5 afbeeldingen tegelijk en tonen die als ze klaar zijn. Het blijft nieuwe afbeeldingen ophalen totdat alles klaar is. De functie Compleet wordt opgeroepen bij het voltooien van elke batch.

 // Bulloader maken. loader = nieuwe BulkLoader ("pagina" + id); loader.addEventListener (BulkLoader.COMPLETE, Complete, false, 0, true);

// stel het totale aantal afbeeldingen in totalPictures = pictures.length; // pak de eerste 5 foto's of het totale aantal foto's als er minder zijn. i = 0; terwijl ik < Math.min(totalPictures,5)) loader.add(String(Canvas.path + pictures[i].url), id: "img" + i ); i++; // Start loader loader.start();

Stap 11: Afbeeldingen laden (vervolg)

In deze stap plaatsen we de geladen gegevens erin afbeelding voorwerpen. De items eigenschap van de lader bevat alle objecten die zijn geladen. Loop over al die objecten en controleer of ze een afbeelding zijn. Elk Bitmap wordt gegeven aan de overeenkomstige afbeelding object en de afbeelding wordt toegevoegd aan het canvas. We verwijderen ook de geladen afbeelding uit de lijst met laderitems om conflicten met een latere reeks geladen afbeeldingen te voorkomen.

 // Beeldbatch geladen. sla de gegevens op afzonderlijke Picture-objecten op. i = amountPicturesLoaded; voor elk (var item: LoadingItem in loader.items) if (item.isImage ()) pictures [i] .SetImage (loader.getBitmap (item.id)); loader.remove (item.id); AddPicture (foto's [i]); i ++; amountPicturesLoaded ++; 

En een kijkje op de setImage functie van afbeelding.

 openbare functie SetImage (ob: Bitmap): void // als er geen afbeeldingsgegevens zijn geladen, laat niets zien als (ob == null) return; // sla de gegevens op in de klasse img = ob; // show image addChild (img); // scale img.scaleX = img.scaleY = imgscale; 

En het toevoegen van een foto aan het canvas is net zo eenvoudig als bellen addChild.

 privéfunctie AddPicture (foto: afbeelding): void addChild (pict); 

Het resultaat wordt nu:


Stap 12: De pagina toevoegen

Het toevoegen van iets aan de cameraweergave gebeurt door een kind toe te voegen aan de viewerScroller houder. We hebben de viewerScroller voor elk Pagina object als een parameter, zodat we het als een kind kunnen toevoegen door het te gebruiken Laten zien() functie van Pagina.

 public function Show (): void container.addChild (this); 

Ga terug naar de Canvas class en bel de functies Load () en Show () wanneer we de gebruiker een pagina willen tonen. Voor het geval de Pagina is al geladen, Laden() zal direct terugkeren, zodat er geen onnodige acties worden uitgevoerd. De huidige Pagina we laten zien wordt opgeslagen in de klas als pagina. Deze referentie is belangrijk voor pagina-interactie.

 private functie ShowPage (nr: int): void // verberg oude pagina als (pagina) pagina. Verberg (); // stel nieuwe paginapagina in = pagina's [nr]; page.Load (); page.Show (); 

Stap 13: Zoommodi

Nu we onze pagina hebben gemaakt met afbeeldingen en tekst, is het noodzakelijk om deze te schalen zodat deze in onze kijkersregio past. We gebruiken de openbare statische variabelen zoom en magnifyStep Voor dit doeleinde. magnifyStep is een array met alle verschillende schaalwaarden van de camera en zoom is de huidige positie van magnifyStep de camera is geschaald naar. Om te weten welke schaalwaarde nodig is om te passen in de inhoud in de viewer, moeten we de verhouding kennen tussen de inhoud en de kijkerregio's. Om rekening te houden met verkeerde beeldverhoudingen nemen we de minimale verhouding tussen breedte en hoogte als volgt:

 // Stel magnify steplist magnifyStepList [0] = Math.min (viewerWidth / contentWidth, viewerHeight / contentHeight) in;

We zouden willen inzoomen wanneer we op het canvas klikken. Voeg een muisgebeurtenis toe aan het hitveld van Pagina. Het hitveld is eigenlijk gewoon de grafische weergave op de achtergrond van Pagina en omdat het een is sprite we kunnen er muisinteractie op plaatsen.

 page.hitField.addEventListener (MouseEvent.MOUSE_DOWN, MouseZoomIn);

Met een muisklik willen we dat de camera verkleind wordt naar de positiezoom in de magnifyStepList en ga naar het punt op het canvas waarop we hebben geklikt. Onthoud aan het voorbeeld dat naarmate de camera kleiner wordt (verkleint), de zoom op het canvas groter wordt. Dit is de reden waarom we de zoom voor geheel getal verlagen met de waarde één. De muispositie krijgen waarop we hebben geklikt, is gemakkelijk door te gebruiken page.mouseX en page.mouseY. Flash converteert de getallen automatisch zodat deze lokaal wordt weergegeven. Dit betekent dat als de pagina bijvoorbeeld 2000 px is verkleind met 50% en u half klikt, het 1000 px retourneert, hoewel de positie van de muis op schaalcoördinaten een stuk kleiner is.

 privéfunctie MouseZoomIn (e: MouseEvent): void var pt: Point; if (! cam.bZooming && zoom> 0) // Zoom in één stap zoomlens in ;-; // Nieuw camerapunt. Juiste grenzen. pt = nieuw punt (page.mouseX, page.mouseY); CameraBounds (pt); cam.Zoom (pt.x, pt.y, magnifyStepList [zoom]); 

Stap 14: Camerapositie corrigeren

Om het gebied van de camera binnen het canvas te houden, moeten we de positie binnen de grenzen van de camera corrigeren. Opnieuw naar het camera-voorbeeld kijken voor een demonstratie hiervan. De camera is gecentreerd rondom zichzelf, dus de positie horizontaal moet bijvoorbeeld binnen blijven 0 + camera halve breedte en contentWidth - camera halve breedte. Een betrouwbare manier om de breedte van de camera te berekenen wanneer is ingezoomd, is contentWidth / 2 * magnifyStepList [zoom], omdat de camera in de oorspronkelijke niet-ingevulde toestand de grootte heeft contentWidth (dezelfde grootte als het canvas).

 privéfunctie CameraBounds (pt: Point): void // horizontal if (pt.x < contentWidth/2 * magnifyStepList[zoom]) pt.x = contentWidth/2 * magnifyStepList[zoom]; else if (pt.x > contentWidth - contentWidth / 2 * magnifyStepList [zoom]) pt.x = contentWidth - contentWidth / 2 * magnifyStepList [zoom]; // verticaal als (pt.y < contentHeight/2 * magnifyStepList[zoom]) pt.y = contentHeight/2 * magnifyStepList[zoom]; else if (pt.y > contentHeight - contentHeight / 2 * magnifyStepList [zoom]) pt.y = contentHeight - contentHeight / 2 * magnifyStepList [zoom]; 

In de onderstaande afbeelding worden de camera en het canvas weergegeven, één keer ingezoomd. De rode lijnen geven de randen weer die de camera niet kan oversteken en die binnen moet blijven.


Stap 15: De zoom laten werken

Het zoomen wordt uitgevoerd door een schaal aan de camera toe te voegen. We gebruiken de tweener klasse en de "EasyOutQuint" overgang om dit op een vlotte manier te laten gebeuren. bZooming is een variabele die wordt gebruikt om te zien of de camera al zoomt of niet. U kunt niet opnieuw inzoomen op de pagina terwijl deze nog steeds bezig is met opschalen naar boven of beneden. Bij elke update van de camera de functie Bijwerken wordt aangeroepen, die de schaal op de inhoud uitvoert.

 publieke functie Zoom (newx: int, newy: int, newscale: Number): void bZooming = true; Tweener.addTween (this, time: 2, x: newx, y: newy, transition: "easeOutQuint", scaleX: newscale, scaleY: newscale, onComplete: function (): void bZooming = false;, onUpdate: Update ); 

Stap 16: een nadere kijk op foto's

Vergeet niet dat we hebben toegevoegd MouseEvent luisteraars naar alle afbeeldingen op de pagina. Wat we graag willen doen, is inzoomen op een foto wanneer er op wordt geklikt en ervoor zorgen dat deze goed past in de kijkerregio. Afbeeldingen die kleiner zijn dan de werkelijke kijkersregio mogen niet worden geschaald buiten hun resolutie.

 private function PictureMouseDown (e: MouseEvent): void var newScale: Number; var screenRatio: Number = Canvas.viewerWidth / Canvas.viewerHeight; var imgW: Number = Math.max (e.target.width * 1.05, Canvas.viewerWidth); var imgH: Number = Math.max (e.target.height * 1.05, Canvas.viewerHeight); var imgRatio: Number = e.target.img.width / e.target.img.height // Bereken afbeeldingschalen if (imgRatio < 1) newScale = imgH / Canvas.contentHeight; else newScale = imgW / Canvas.contentWidth; Canvas.cam.Zoom(e.target.x + e.target.width/2, e.target.y + e.target.height/2, newScale); Canvas.cam.bLocked = true; PictureMouseDisable(); 

Het basisconcept hierbij is dat eerst de beeldverhouding van een beeld moet worden bepaald. Als de breedte van een afbeelding dan hoger is dan de hoogte imgRatio < 1 zal waar zijn en vice versa als de hoogte groter is dan de breedte. We zullen altijd naar het grootste deel van een afbeelding schalen, wat betekent dat als de afbeelding bijvoorbeeld 200x400 px is, we de afbeelding zullen behandelen als een vierkant van 400x400. Een andere toevoeging is dat we het beeld eerst met 1,05 schalen, wat betekent dat het beeld 5% groter wordt. Op deze manier raakt het beeld de zijkanten niet wanneer wordt ingezoomd. Om de schaal van een afbeelding te berekenen in vergelijking met de inhoudsgrootte, delen we deze door de hoogte of breedte van de inhoud..

Bel de Zoom functie van de camera en ga naar het midden van de foto waar we ons op concentreren en pas de nieuwe schaal toe die we hebben berekend.

Hier is het zoomproces van afbeeldingen weergegeven in actie. Let op hoe de camera binnen de grenzen van de pagina wordt gehouden en hoe de volledige afbeelding inclusief beschrijving perfect in het scherm past.


Stap 17: Bladeren door de pagina

Als u het niet had gemerkt, kunt u wanneer u op een pagina inzoomt de muiscursor naar de randen van het scherm verplaatsen om te bladeren en meer van de pagina te bekijken. De onderstaande code ziet er misschien een beetje bizar uit; het is iets dat ik een tijdje geleden heb geschreven voor een RTS-achtige game-engine en het sindsdien opnieuw heb gebruikt voor alles dat scrollen vereist. Uitgangspunten hierbij is dat u controleert waar de muispositie zich bevindt en of deze zich zonder een bepaald bereik rond de maten beweegt (mouse_scroll_areax_reduced en mouse_scroll_areay_reduced) dan zal het naar een kant gaan bewegen met een snelheid die evenredig is met hoe ver je binnen dat bereik bent. Als de muiscursor niet binnen het bereik valt, wordt het slepen verplaatst om het uiteindelijk te vertragen.

 // Verkrijg de nodige scolling op basis van de muispositie mx = viewerContainer.mouseX; mijn = kijkerContainer.mouseY; als (mx < mouse_scroll_areax && mx > 0) scrollAmountX = (((((mx - mouse_scroll_areax) / mouse_scroll_areax_reduced) * mouse_scroll_factor) + .5) << 0;  else if ((viewerContainer.width - mx) < mouse_scroll_areax && mx < viewerContainer.width)  scrollAmountX = (((1 - (viewerContainer.width - mx) / mouse_scroll_areax_reduced) * mouse_scroll_factor) + .5) << 0;  if (my < mouse_scroll_areay && my > 0) scrollAmountY = ((((mijn - mouse_scroll_areay) / mouse_scroll_areay_reduced) * mouse_scroll_factor) + .5) << 0;  else if ((viewerContainer.height - my) < mouse_scroll_areay && my < viewerContainer.height)  scrollAmountY = (((1 - (viewerContainer.height - my) / mouse_scroll_areay_reduced) * mouse_scroll_factor) + .5) << 0;  // Put drag on the scroll, so it does not keep on