Статьи

Создайте эффект впечатляющего увеличения с помощью ActionScript 3.0

Два раза в месяц мы возвращаемся к любимым постам наших читателей на протяжении всей истории Activetuts +. Этот учебник был впервые опубликован в апреле 2009 года.

В этом уроке мы создадим эффект лупы, демонстрирующий использование displacementMapFilter . Эффект может быть достигнут в относительно короткий промежуток времени и с очень небольшим количеством кода.


Давайте посмотрим на то, к чему мы стремимся:


Мы собираемся работать с двумя слоями плюс дополнительный дополнительный слой. Первый будет содержать изображение, которое будет содержать визуальную графику, это может быть что угодно. Вторым слоем будет цветовая карта, которая будет контролировать нажатие пикселей. Третий слой будет содержать ActionScript.

Дополнительный четвертый слой будет наложенным изображением, действующим как рамка или рамка объектива.

Давайте посмотрим на это!


Первое, что нам нужно сделать, это создать новый Flash-файл ActionScript 3.0 — размер документа 530px X 400px с частотой кадров 30 кадров в секунду.

«»

Затем нам нужно импортировать изображение, которое мы можем использовать для этого эффекта — я нашел классное, свободно доступное изображение рабочего стола с разрешением 1024×768 пикселей.

Импортируйте это на сцену и назовите слой «Image».

«»

Теперь давайте уменьшим изображение до 50% и отцентрируем его.

«»

Создайте новый слой сверху и назовите его «Действия». Тогда давайте выведем панель действий и начнем кодировать эффект. Сначала нам нужен фильтр для изображения, поэтому давайте создадим новый объект фильтра и назовем его «dFilter». Мы оставим фильтр свободным от параметров, так как их довольно много для настройки.

1
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();

Далее нам нужно установить эти параметры фильтра в представлении списка.


Давайте начнем с самых простых и установим шкалы около 50. Это величина, до которой увеличитель будет увеличиваться. Также можно установить отрицательное значение, но в этом случае нам нужно увеличить, а не уменьшить.

Дополнительные строки: 3,4

1
2
3
4
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50

Примечание: это не фактический порядок, в котором фильтр обычно принимает параметры. Однако в этом случае мы можем добавить их по своему желанию, потому что мы используем перечисленное представление для лучшего обзора.


Далее мы установим цветовые каналы компонента для X и Y — это определяет, какие цветовые каналы в контрольной карте (которую мы создадим через секунду) будет слушать фильтр.

Если вы знакомы с шестнадцатеричным кодом RGB #RRGGBB, мы можем выбрать BitmapDataChannel.RED, BitmapDataChannel.GREEN и BitmapDataChannel.BLUE. Чтобы сделать это проще, мы также можем просто написать 1 (красный), 2 (зеленый) или 4 (синий) — (и нет, я не допустил орфографическую ошибку, синий — 4; это устанавливается из фактической позиции канала в шестнадцатеричный код). В этом примере мы просто придерживаемся красного (1) и зеленого (2) — но вернемся к этому подробнее, когда будем разрабатывать карту фактического смещения.

Дополнительные строки: 5,6

1
2
3
4
5
6
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2

Далее нам нужно установить режим, чтобы определить, как будут реагировать пиксели, если они будут перемещаться дальше границ изображения. Здесь мы можем выбрать из:

DisplacementMapFilterMode.COLOR / DisplacementMapFilterMode.WRAP / DisplacementMapFilterMode.CLAMP / DisplacementMapFilterMode.IGNORE

Опять же, мы можем упростить это, написав «color», «зажим», «wrap», «ignore». Я не буду вдаваться в подробности этого урока, поэтому давайте просто используем «цвет», который лучше всего работает в большинстве случаев.

Дополнительные строки: 7

1
2
3
4
5
6
7
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»

Этот режим позволяет пикселям продолжать движение за границу изображения (в случае, если фильтр выдвигает пиксели дальше, чем край изображения).


Теперь давайте установим окружающий цвет на 0x000000 и альфа на 0. Это на 100% прозрачно, поэтому за пределами изображения ничего не отображается, кроме исходных пикселей.

Дополнительные строки: 8,9

1
2
3
4
5
6
7
8
9
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0

Теперь нам нужно установить позицию, где фильтр будет влиять на изображение; наша позиция объектива. Это должно быть установлено как объект Point, содержащий значения x и y. Мы начнем с создания точечного объекта, чтобы он был готов к использованию, когда мы назначим его для displacementMapFilter. Давайте назовем это «dPoint» и установим 0, 0 в качестве начальных значений. Мы вернемся к этому моменту, когда нам нужно будет проинструктировать эту точку следовать за мышью.

Затем мы назначаем «dPoint» для позиции «dFilter’s».

Дополнительные строки: 1,11

01
02
03
04
05
06
07
08
09
10
11
12
var dPoint:Point = new Point(0, 0);
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint;

И последнее, но не менее важное: нам нужно назначить контрольную карту для фильтра. Это карта, которая содержит цветные пиксели, которые слушают компоненты X и Y.

Дополнительные строки: 13

01
02
03
04
05
06
07
08
09
10
11
12
13
var dPoint:Point = new Point(0, 0);
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint;
dFilter.mapBitmap =

Здесь нам также нужен объект BitmapData, который будет действовать как контейнер данных для нашей карты цветов.


Сначала мы создаем квадрат с линейным градиентом от красного до черного размером 100px X 100px. Это возьмет текущие пиксели и сдвинет их влево и вправо, когда мы установим для компонента X красный цвет. Давайте сделаем этот видеоклип под названием «RedMap»

Затем мы делаем то же самое снова — но на этот раз с квадратом линейного градиента от зеленого к черному, снова 100px X 100px. На этот раз мы также повернем его на 90 °. Возможно, вы помните, что мы устанавливаем компонент для смещения оси Y зеленым (componentY = 2), чтобы градиент проходил вдоль оси y. Еще раз мы конвертируем его в мувиклип, на этот раз называя его «greenMap».

«»

Теперь у нас есть два отдельных цветных изображения; нам нужен только один, поэтому установите режим смешивания greenMap на «screen». Каждый цвет из зеленой карты будет просвечивать на красной карте. Поместите зеленую карту сверху красной карты и убедитесь, что они выровнены правильно.

Выберите оба фрагмента ролика, нажав на слой «Карта», и преобразуйте их в один фрагмент ролика, называемый «colorMap». Затем установите имя экземпляра в «colorMap_mc».

«»

Теперь давайте вернемся к коду и продолжим, записав мувиклип colorMap в bitmapData.

Перейдите в начало кода и создайте новый объект BitmapData. Давайте назовем его «dMap» и установим его размер в соответствии с размером нашей colorMap (в данном случае 100px X 100px, но это может быть почти что угодно). Мы установим прозрачность на «true» и цвет на 0x808080. Это гарантирует, что все оставшиеся пиксели в bitmapData будут нейтральными.

Дополнительные строки: 3

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint;
dFilter.mapBitmap =

Нам нужно нарисовать содержимое colorMap в bitmapData. Как только это будет сделано, мы сможем использовать скрипт для удаления colorMap со сцены. Это возможно, поскольку изображение colorMap будет содержаться в коде bitmapData.

Дополнительные строки: 5, 7

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
dMap.draw(colorMap_mc)
 
removeChild(colorMap_mc)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint;
dFilter.mapBitmap =

Добавьте bitmapData dMap в displacementMapFilter, установив последний параметр в списке (mapBitmap) на «dMap».

Модифицированные строки: 19

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
dMap.draw(colorMap_mc)
 
removeChild(colorMap_mc)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint
dFilter.mapBitmap = dMap

Фильтр готов! Теперь нам нужно добавить его к изображению, поэтому выберите изображение и убедитесь, что у него есть имя экземпляра — давайте назовем его «Image_mc». После этого мы можем установить фильтр на изображении. Мы делаем это в конце кода, устанавливая параметр Фильтры изображения как массив следующим образом:

Image_mc.filters = [dFilter]

Дополнительные строки: 21

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
dMap.draw(colorMap_mc)
 
removeChild(colorMap_mc)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint
dFilter.mapBitmap = dMap
 
Image_mc.filters = [dFilter]

Хорошо, давайте экспортируем фильм и посмотрим, как фильтр влияет на изображение. Это должно выглядеть примерно так:


То, что мы имеем до сих пор, не очень интересно, поэтому давайте попробуем заставить линзу следовать за мышью.

Сначала мы добавляем код цикла «enterFrame» следующим образом:

Дополнительные строки: 23,25,27

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
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
dMap.draw(colorMap_mc)
 
removeChild(colorMap_mc)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint
dFilter.mapBitmap = dMap
 
Image_mc.filters = [dFilter]
 
Image_mc.addEventListener(Event.ENTER_FRAME, onFrame)
 
function onFrame(e:Event){
 
}

Затем мы устанавливаем значения X и Y нашего dPoint, чтобы следовать за мышью. Кроме того, мы снова переназначим вновь измененный dPoint на dFilter и переназначим фильтр на изображение.

Дополнительные строки: 26,27,28,29

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
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
dMap.draw(colorMap_mc)
 
removeChild(colorMap_mc)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint
dFilter.mapBitmap = dMap
 
Image_mc.filters = [dFilter]
 
Image_mc.addEventListener(Event.ENTER_FRAME, onFrame)
 
function onFrame(e:Event){
    dPoint.x = mouseX
    dPoint.y = mouseY
    dFilter.mapPoint = dPoint
    Image_mc.filters = [dFilter]
}

Давайте проверим это снова. Это должно выглядеть так:


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

dPoint.x = mouseXdPoint.y = mouseY

Модифицированные строки: 26,27

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
var dPoint:Point = new Point(0, 0);
 
var dMap:BitmapData = new BitmapData(colorMap_mc.width, colorMap_mc.height, true, 0x808080)
 
dMap.draw(colorMap_mc)
 
removeChild(colorMap_mc)
 
var dFilter:DisplacementMapFilter = new DisplacementMapFilter ();
 
dFilter.scaleX = 50
dFilter.scaleY = 50
dFilter.componentX = 1
dFilter.componentY = 2
dFilter.mode = «color»
dFilter.color = 0x000000
dFilter.alpha = 0
dFilter.mapPoint = dPoint
dFilter.mapBitmap = dMap
 
Image_mc.filters = [dFilter]
 
Image_mc.addEventListener(Event.ENTER_FRAME, onFrame)
 
function onFrame(e:Event){
    dPoint.x += ((mouseX-colorMap_mc.width/2)-dPoint.x)*0.3
    dPoint.y += ((mouseY-colorMap_mc.height/2)-dPoint.y)*0.3
    dFilter.mapPoint = dPoint
    Image_mc.filters = [dFilter]
}

Подводя итог: мы вычитаем половину размера карты из положения карты, чтобы она центрировалась. Затем мы добавляем базовую функцию анимации, которую можно записать так:

this += (that-this)*speed


В довершение всего, я добавил увеличительное стекло, которое я подготовил в фотошопе. Я преобразовал его в мувиклип, дал ему имя экземпляра и сделал так, чтобы он следовал точке, которую мы используем для displacemenMapFilter.

«»

Это достигается установкой новых линз_frame_image X и Y, равных положению dPoint. Затем вычтите смещение для графического края, чтобы оно идеально совпало с эффектом фильтра.

Дополнительные строки: 4,5

1
2
3
4
5
6
7
8
function onFrame(e:Event){
    dPoint.x += ((mouseX-colorMap_mc.width/2)-dPoint.x)*0.3
    dPoint.y += ((mouseY-colorMap_mc.height/2)-dPoint.y)*0.3
    lens_mc.x = dPoint.x-8
    lens_mc.y = dPoint.y-8
    dFilter.mapPoint = dPoint
    Image_mc.filters = [dFilter]
}

Теперь наш результат должен выглядеть так:


Когда вы научитесь создавать этот эффект самостоятельно, настройка займет не более 15 минут. Помнить; если вы забудете, какие параметры имеют для displacementMapFilter, вы всегда можете найти их в «справке». Там вы получите перечисленный порядок и то, что делает каждый параметр.

Для быстрого эксперимента вы можете зайти на мой сайт и посмотреть в разделе «flash» в разделе «test / labs» — у меня есть несколько тестовых сред displacementMapFilter, которые вы можете попробовать.

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