Get Control Over [Embed]
The [Embed]
metadata tag has been in AS3 since the beginning, but few know how to use it fully. Today’s article shows how you can go beyond the standard usage to maximize the usefulness of [Embed]
. Read on for some useful tricks you may not know about and take another step toward mastering AS3.
First of all, let’s talk about the basics of [Embed]
in case it’s a new concept to you. This metadata tag tells the compiler to embed a file into the SWF and bind it to whatever comes after it. A huge majority of the code you see using this, including every [Embed]
on this site, looks like this:
public class MyClass { // Embed "someimage.png" and bind it to the SOME_IMAGE variable [Embed(source="someimage.png")] private static const SOME_IMAGE:Class; public function foo(): void { // Instantiate the bound variable to get an object with the file's data var someImageObj:Object = new SOME_IMAGE(); // Since we bound a PNG image file, the object you get is a Bitmap var someImage:Bitmap = someImageObj as Bitmap; // ... do whatever you'd like with someImage trace("Dimensions: " + someImage.width + "x" + someImage.height); } }
The above works for images. This works for arbitrary data files:
public class MyClass { // Embed "somedata.dat" and bind it to the SOME_DATA variable [Embed(source="somedata.dat", mimeType="application/octet-stream")] private static const SOME_DATA:Class; public function foo(): void { // Instantiate the bound variable to get an object with the file's data var someDataObj:Object = new SOME_DATA(); // Since we bound a binary file, the object you get is a ByteArray var someData:ByteArray = someDataObj as ByteArray; // ... do whatever you'd like with someData trace("Size KB: " + (someData.length / 1024)); } }
The only difference is in adding the mimeType
to the [Embed]
tag to tell the compiler to embed the file as a ByteArray
rather than a Bitmap
. There are other types you can embed (e.g. Font
), but we’ll limit to these two types for the purposes of this article.
One of the disadvantages to the above approach is that the mx.core.BitmapAsset
class will be included in your SWF and thus add to its file size even though you almost certainly only care that it ultimately derives from Bitmap
and therefore has all the useful properties like having an accessible BitmapData
for manipulator and uploading to Stage3D
textures. It turns out that if you’re willing to use an alternative syntax for the [Embed]
metadata tag that you can actually skip embedding these mostly-irrelevant classes. This isn’t covered in Adobe’s documentation. Here’s how the alternate version looks:
/////////////// // SomeImage.as /////////////// [Embed(source="someimage.png")] public class SomeImage extends Bitmap { public function get dimensions(): String { return width + "x" + height; } } ///////////// // MyClass.as ///////////// public class MyClass { public function foo(): void { // Instantiate the bound class to get the embedded image var someImage:SomeImage = new SomeImage(); // ... do whatever you'd like with someImage trace("Dimensions: " + someImage.dimensions); } }
Here you’re explicitly providing a class to bind the file to rather than using a variable typed as a Class
. So you don’t need any casting and know at compile time exactly what you’re instantiating. You can also add functionality to the class like how SomeImage
has a function to return a String
description of its dimensions. Unfortunately, it requires that you add another file if you want to use the embedded resource file from more than one source code (i.e. .as
) file.
Here’s how this alternate version would look for arbitrary, binary data:
/////////////// // SomeData.as /////////////// [Embed(source="somedata.dat", mimeType="application/octet-stream")] public class SomeData extends ByteArray { public function get lengthKB(): uint { return length / 1024; } } ///////////// // MyClass.as ///////////// public class MyClass { public function foo(): void { // Instantiate the bound class to get the embedded data var someData:SomeData = new SomeData(); // ... do whatever you'd like with someData trace("Size KB: " + someData.lengthKB); } }
In summary, this alternate syntax allows you to avoid embedding extra classes like mx.core.BitmapAsset
, derive classes from embedded files to add on functionality, and gain some compile-time confidence by skipping the need for casting from plain Object
. Why not give it a try next time you need to [Embed]
?
Spot a bug? Have a question or suggestion? Post a comment!
#1 by henke37 on August 12th, 2013 ·
Another advantage is that you get rid of the pointless variable/constant to hold the Class reference.
#2 by max troost on August 12th, 2013 ·
this is a great one, mx.core.BitmapAsset always seemed obsolete when building a AS3 only app.
But how would you implement this for a Font?
Would be something like this?
[Embed(source=”somefont.ttf”, ….)]
public class SomeImage extends Font
{
}
#3 by jackson on August 12th, 2013 ·
That’s the basic strategy, but there a few quirks to work around. For TrueType fonts you’ll need to add
embedAsCFF="false"
to get a font class like this:Then you’ll need to call
Font.registerFont
before you use the embedded font. ForTextField
, you also have to set theembedFonts
field to true. Here’s a little test app that uses the above font:Here’s a demo SWF showing off Trajan, which you probably don’t have installed on your computer. If you do, uninstall it before running the test an re-install afterward so you can confirm that it’s not a system font but actually embedded in the SWF.
#4 by Stephen Bailey on August 12th, 2013 ·
If you are using this to embed a swf, just remember that SWF’s are treated slightly differently, in that the embedded object is not the SWF, but rather it Loader , so you may have to wait on its event complete before you can use it ( although I do worry about the loader completing before your callback is in place, and you have little control over this since you are the one calling the load method in the first place? ).
Credit to this link where I first read about this : http://www.bit-101.com/blog/?p=1435
#5 by max troost on August 15th, 2013 ·
thanx allot Jackson!
#6 by Florent Cailhol on August 20th, 2013 ·
You could also embed an image as
BitmapData
.[Embed(source=”someimage.png”)]
public class SomeImage extends BitmapData
{
public function SomeImage()
{
super(0, 0);
}
}
#7 by test on August 22nd, 2013 ·
hello.why the embed not use in flex 4.10
#8 by jackson on August 22nd, 2013 ·
I’m not sure. Have you asked someone from the Apache Flex project?
#9 by erikdebruin on September 10th, 2013 ·
Hi,
You are always invited to report issues with the Flex SDK to the Apache Flex JIRA system [1]. Please provide a ‘detailed’ explanation and the smallest test project with which we can reproduce the issue (if possible, otherwise the report alone is fine.
Jackson: thanks, this is another amazing ‘hack’, I’m glad Flex can still surprise me ;-)
EdB
1: https://issues.apache.org/jira/browse/FLEX