Статьи

Совет: создание инструмента моментальных снимков во Flash

В этом кратком совете я покажу вам, как создать инструмент Shapshot, который копирует часть сцены и сохраняет результат в виде изображения PNG.


Это конечный результат. Просто нажмите на сцену, а затем перетащите мышь, чтобы сделать снимок.


Создайте новую папку для этого проекта и дайте ему любое имя. Перейдите на Github и загрузите последнюю версию класса as3corelib . Для этого Quick Tip я использовал версию .93. Извлеките ZIP-файл и перейдите к as3corelib-.93> src .

Скопируйте каталог com в вашу вновь созданную папку. Этот пакет имеет очень полезный класс PNGEncoder который мы будем использовать для кодирования
снимок в изображение PNG.


Запустите Flash и создайте новый документ Flash. Убедитесь, что он настроен для публикации в Actionscript 3.0 и Flash Player 10. Вы можете проверить это в Свойствах
панель или выбрав Опубликовать настройки … и затем нажав на вкладку Flash .

Панель свойств Flash

Нам необходим некоторый контент в файле Flash, чтобы проверить, правильно ли работает инструмент моментальных снимков. Мы собираемся создать несколько кругов и расположить их случайным образом вокруг сцены. Создайте новый класс документов с именем Circles.as и добавьте следующий код. Не забудьте связать класс с файлом Flash, написав круги в поле « Класс» на панели свойств .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package
{
    import flash.display.Shape;
    import flash.display.Sprite;
     
    public class Circles extends Sprite
    {
        private var _circleCount:int = 20;
         
        public function Circles()
        {
            makeCircles();
        }
         
        private function makeCircles():void
        {
            for (var i:int = 0; i < _circleCount; i++)
            {
                var circle:Shape = new Shape();
                circle.graphics.lineStyle(1, 0xCCCCCC, 1);
                circle.graphics.beginFill(0x333333, 0.5);
                circle.graphics.drawCircle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, (Math.random() * 40) + 20);
                circle.graphics.endFill();
                addChild(circle);
            }
        }
    }
}

Наша функция снимка будет работать с любым содержимым сцены, поэтому не думайте, что вам нужно ограничивать себя простыми формами!


Создайте новый файл Class и присвойте ему имя SnapShot.as . Это класс, который будет содержать все методы, используемые для создания снимка. Добавьте следующий код в класс.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
package
{
    import flash.display.Stage;
     
    public class SnapShot
    {
        private var _stage:Stage;
         
        public function Snapshot() {}
         
        public function activate(stage:Stage):void
        {
            _stage = stage;
        }
    }
}

Добавьте следующие строки кода в класс Circles . Мы используем метод SnapShot activate() для передачи ссылки на SnapShot класс SnapShot . Мы делаем это для того, чтобы получить доступ к контенту на сцене.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package
{
    import flash.display.Shape;
    import flash.display.Sprite;
     
    public class Circles extends Sprite
    {
        private var _circleCount:int = 20;
        private var _snapshot:SnapShot;
         
        public function Circles()
        {
            makeCircles();
            _snapshot = new SnapShot();
            _snapshot.activate(stage);
        }
         
        private function makeCircles():void
        {
            for (var i:int = 0; i < _circleCount; i++)
            {
                var circle:Shape = new Shape();
                circle.graphics.lineStyle(1, 0xCCCCCC, 1);
                circle.graphics.beginFill(0x333333, 0.5);
                circle.graphics.drawCircle(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight, (Math.random() * 40) + 20);
                circle.graphics.endFill();
                addChild(circle);
            }
        }
    }
}

Разверните класс SnapShot чтобы включить следующие методы. Эти методы используются для рисования рамки границ, которая позволяет пользователям выбирать, какая часть этапа будет скопирована в моментальный снимок.

01
02
03
04
05
06
07
08
09
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package
{
    import flash.display.Shape;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.MouseEvent;
     
    public class SnapShot
    {
        private var _stage:Stage;
        private var _boundary:Shape;
        private var _originX:int;
        private var _originY:int;
        private var _mouseX:int;
        private var _mouseY:int;
         
        public function SnapShot() {}
         
        public function activate(stage:Stage):void
        {
            _stage = stage;
            addMouseListeners();
        }
         
        private function addMouseListeners():void
        {
            _stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
            _stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
        }
         
        private function onMouseDown(e:MouseEvent):void
        {
            _stage.addEventListener(MouseEvent.MOUSE_MOVE, drawBoundaries);
             
            //These values are used later as a starting point for the boundary.
            _originX = _stage.mouseX;
            _originY = _stage.mouseY;
        }
         
        private function drawBoundaries(e:MouseEvent):void
        {
            if (_boundary == null) { _boundary = new Shape();
             
            clearBoundaries()
             
            //This is to make the mouseY value stay within the limits of the Stage.
            _mouseY = Math.max(Math.min(_stage.mouseY,_stage.stageHeight), 0);
            //This is to make the mouseX value stay within the limits of the Stage.
            _mouseX = Math.max(Math.min(_stage.mouseX,_stage.stageWidth), 0);
             
            _boundary.graphics.lineStyle(2, 0x0, 0.5);
            _boundary.graphics.drawRect(_originX, _originY, _mouseX — _originX, _mouseY — _originY);
            _boundary.graphics.lineStyle(4, 0x0, 0.2);
            //This code makes sure we always draw from the top left point to the bottom right.
            _boundary.graphics.drawRect(Math.min(_originX, _mouseX) — 3, Math.min(_originY, _mouseY) — 3, Math.abs(_mouseX — _originX) + 6, Math.abs(_mouseY — _originY) + 6);
            _stage.addChild(_boundary);
        }
         
        private function clearBoundaries():void
        {
            _boundary.graphics.clear();
        }
         
        private function onMouseUp(e:Event):void
        {
            _stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawBoundaries);
            clearBoundaries();
        }
    }
}

Начнем с проверки, нажал ли пользователь на Stage . Когда он нажимает на сцену, мы запускаем метод drawBoundaries() всякий раз, когда мышь перемещается. Этот метод рисует границы; все, что попадает в тонкую черную линию, будет частью снимка. Когда пользователь отпускает мышь, мы прекращаем проверять движения мыши.

Импортируйте классы BitmapData и Matrix и добавьте свойство _content в список частных свойств.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package
{
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
     
    public class SnapShot
    {
        private var _stage:Stage;
        private var _boundary:Shape;
        private var _content:BitmapData;
        private var _originX:int;
        private var _originY:int;
        private var _mouseX:int;
        private var _mouseY:int;

Добавьте следующий код в конец класса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private function onMouseUp(e:Event):void
{
    _stage.removeEventListener(MouseEvent.MOUSE_MOVE, drawBoundaries);
    clearBoundaries();
    createBitmap();
}
         
private function createBitmap():void
{
    //We add the -2 to offset for the boundary line.
    _content = new BitmapData(Math.abs(_mouseX — _originX) — 2, Math.abs(_mouseY — _originY) — 2);
    //The -1 is added for the same reason, to keep the line from appearing in the final image.
    var bitmapMatrix:Matrix = new Matrix(1, 0, 0, 1, -Math.min(_originX, _mouseX) — 1, -Math.min(_originY, _mouseY) — 1);
    _content.draw(_stage, bitmapMatrix);
}

Метод createBitmap() создает новый объект BitmapData с шириной и высотой области содержимого внутри границы. Переменная матрицы перемещает (перемещает) изображение так, что при вызове метода draw() оно начинает копирование из левого верхнего угла области границы.

Чтобы сохранить растровое изображение, нам нужно импортировать несколько классов.

  • Класс ByteArray используется для кодирования объекта BitmapData .
  • Класс PNGEncoder используется для преобразования закодированных данных в изображение PNG.
  • Класс FileReference используется для сохранения изображения на жестком диске пользователя.

Мы также добавили свойство _imageCount которое мы используем для увеличения имен изображений.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package
{
    import com.adobe.images.PNGEncoder;
    import flash.display.BitmapData;
    import flash.display.Shape;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Matrix;
    import flash.geom.Rectangle;
    import flash.net.FileReference;
    import flash.utils.ByteArray;
     
    public class Snapshot
    {
        private var _stage:Stage;
        private var _boundary:Shape;
        private var _content:BitmapData;
        private var _originX:int;
        private var _originY:int;
        private var _mouseX:int;
        private var _mouseY:int;
 
        private var _imageCount:int = 1;

Добавьте следующий код в конец класса SnapShot:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
private function createBitmap():void
{
    _content = new BitmapData(Math.abs(_mouseX — _originX) — 2, Math.abs(_mouseY — _originY) — 2);
    var bitmapMatrix:Matrix = new Matrix(1, 0, 0, 1, -Math.min(_originX, _mouseX) — 1, -Math.min(_originY, _mouseY) — 1);
    _content.draw(_stage, bitmapMatrix);
             
    saveBitmap();
}
         
private function saveBitmap():void
{
    var encodedContent:ByteArray = PNGEncoder.encode(_content);
    var fileWindow:FileReference = new FileReference();
    fileWindow.save(encodedContent, «Image_» + _imageCount + «.png»);
    _imageCount++;
}

Метод saveBitmap довольно прост для понимания. Мы кодируем объект BitmapData и сохраняем его на жестком диске пользователя.
Мы используем свойство _imageCount чтобы пользователю было проще сохранять несколько изображений подряд.

Инструмент моментальных снимков завершен, и с помощью всего трех строк кода его можно внедрить в любой проект.

Убедитесь, что вы используете Flash Player 10 и у вас есть пакет as3corelib в правильном каталоге.

Я надеюсь, вам понравился этот Quick Tip, спасибо за чтение!