Интерактивная карта регионов во Flash

На этот раз ко мне обратился один приятель и спросил, как это во Flash программисты делают всякие интерактивные штуки? Привело его к этому желание сделать у себя на странице «крутую» интерактивную карту. Чтобы при наведении надписи появлялись... И дал мне собственноручно (надеюсь) нарисованную картинку:

Что нужно сделать

В итоге в выданном мне файле Map.psd имелся один слой с картой и несколько слоёв с наименованиями областей. Вот таким был слой карты:

Что нужно сделать

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

Переделывать всё «как положено» и разрабатывать хорошую архитектуру у меня времени и желания не было. Сделал «на коленке». Может кому-нибудь пригодится.

Открываем Adobe Flash и создаём новый проект «Flash File (ActionScript 3.0)». Щёлкаем в пустом месте и в окне Properties выставляем размер, равный размеру нашей карты, и частоту кадров около 25:

Свойства документа

Теперь импортируем в проект наши регионы. Выбираем File > Import > Import to Library и выбираем наш файл Map.psd. Мы должны увидеть, что все слои из файла добавились в библиотеку в виде растровых графических элементов группы «Map.psd Assets».

Импорт

Для дальнейшей работы из графических элементов необходимо сформировать символы. для этого щёлкаем два раза по значку клипа Map.psd, чтобы просмотреть его содержимое.

Импорт

Мы видим, что все импортированные растровые элементы здесь выделены. Снимаем выделение, щёлкнув где-нибудь снаружи карты. Теперь щёлкаем отдельно каждую надпись и конвертируем в символ типа Graphic. Для каждой области указываем понятное имя.

Если же Вы делаете надписи текстовыми полями в самом Flash, то их конвертирование можно пропустить.

Конвертация

В последнюю очередь не забудьте выделить и сконвертировать в символ Map_Graph саму карту.

Таким образом мы получили графические символы карты и надписей. Создайте для удобства группу «Графические символы» в окне библиотеки и перетащите в неё новые символы.

Теперь нам необходимо превратить все объекты в сущности, которые будут нам доступны в процессе программировнания. Для этого необходимо каждый символ типа Graphic поместить в клип MovieClip и разрешить доступ к нему из скрипта. Щелкаем правой кнопкой, выбираем Convert to Symbol, указываем понятное имя (Belgorod, Bransk, Kaluga, ...) и разрешаем экспорт:

Конвертация

Эту операцию нужно проделать со всеми спрайтами надписей и карты. Создайте группу «Клипы» и поместите в неё новые символы. Теперь мы сможем из скрипта создавать карту и области с помощью кода

var map = new Map;
var sm = new Smolensk;
var tb = new Tambov;
...

У всех клипов указывается класс по умолчанию flash.display.MovieClip. У нас все надписи будут интерактивные, то есть они будут следить за перемещением указателя мыши. Для добавления программного кода к элемену Smolensk можно было бы создать класс Smolensk в новом одноимённом файле «Smolensk.as». Но так как надписей у нас много мы сделаем общий класс и сделаем его родительским для всех надписей. Создадим файл RegLabel.as с пустым классом RegLabel

Внимательно относитесь к регистру символов в именах файлов, классов, переменных и прочих наименований в скриптах. Если назовёте файл с маленькой буквы, а в проекте напишете его с большой, то система этот файл не найдёт и выдаст ошибку.

package { 
 
    import flash.display.*;
 
    public class RegLabel extends MovieClip {
        public function RegLabel():void {
 
        }
    }
}

Теперь установим этот класс родительским (вместо flash.display.MovieClip) у клипа каждой надписи:

Конвертация

Для клипа карты класс менять не надо.

Итого у Вас должны получиться три «папки» в библиотеке:

  1. Map.psd Assets (содержит исходные растровые надписи)
  2. Графические символы (объекты надписей и карты)
  3. Клипы (клипы надписей и карты)

Теперь необходимо зайти в каждый клип надписи и создать в нём анимацию появления и изчезания текста и расставить контрольные точки.

Заходим в клип надписи «Belgorod» для редактирования:

Клип

Для начала добавим новые кадры клавишей F5 и ещё два слоя:

Клип

Переименуем нижний слой в Text, второй в Points. Второй слой будет содержать ключевые кадры с метками. Станем на нужный кадр, нажмём F6:

Клип

Для добавления метки кадрам в свойствах фрейма укажем их имена Start, Over и Out:

Клип

Третий слой переименуем в Actions и вставим точки останова. Для этого добавим два ключевых кадра, откроем окно скриптов командой Actions контекстного меню ключевого фрейма и вставим строку

stop();

в оба ключевых фрейма.

Таким образом мы подготовили разметку для трёх состояний клипа:

Клип

Осталось создать анимацию текста. В начале (на участке Start) текст должен быть невидимым. Щёлкаем по первому кадру, выделяем символ с текстом, выбираем значение Alpha (Непрозрачноть) у параметра Color и вместо 100% ставим 1%. Надпись должна пропасть.

Клип

Создадим ещё несколько ключевых кадров напротив ключевых кадров других слоёв. Установим непрозрачность надписи в этих кадрах 100% и 1% как указано на рисунке. Идея в том, что на участке Over надпись должна появляться, а на участке Out исчезать.

Клип

Чтобы эффекты были плавными создадим анимацию на участках появления и исчезания.

Клип

На этом подготовка клипа надписи закончена. Вот что должно получиться:

Конвертация

При перемещении линии-курсора прозрачность подписи должна плавно изменяться. На участке Start надпись не видна (непрозрачность 1%), на участке Over она появляется (анимация непрозрачности от 1% до 100%) и на Out изчезает (от 100% до 1%).

Не ставьте исчезание до 0%, так как при этом клип не будет реагировать на события мыши!

Кадры с метками Start, Over и Out будут использоваться для переключения состояний из скрипта.

Теперь можно скопировать фреймы и вставить на новые слои в клипах всех остальных надписей:

Конвертация

Анимацию нижнего слоя скопировать не получится (придётся в каждом клипе вручную повторять расстановку прозрачности и создание анимации).

Итак, клипы мы создали, осталось дописать скрипты.

Общий для всех надписей файл RegLabel.as. При создании экземпляра надписи станем у клипа этой надписи на кадр Start и остановимся. При наведении и убирании указателя мыши будем переходить на соответствующие кадры (Over и Out).

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

package {
 
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
 
    public class RegLabel extends MovieClip {
 
        public var link = ''; //место для ссылки
 
        // Конструктор (срабатывает при создании надписи)
        public function RegLabel():void {
 
            // Перейдём у себя (в клипе) на кадр "Start" и остановимся 
            gotoAndStop('Start');
 
            // Повесим на себя события наведения и убирания мыши
            addEventListener(MouseEvent.MOUSE_OVER, _showMe);
            addEventListener(MouseEvent.MOUSE_OUT, _hideMe);
            // Ловим щелчки для работы перехода по ссылке
            addEventListener(MouseEvent.CLICK, _clickMe);
 
        }
 
        private function _showMe(e:MouseEvent):void {
            // Запустим воспроизведение себя с кадра "Over"
            gotoAndPlay('Over'); 
        }
 
        private function _hideMe(e:MouseEvent):void {
            // Аналогично с кадра "Out"
            gotoAndPlay('Out');
        }
 
        private function _clickMe(e:MouseEvent):void {
            // Если нам указали ссылку, то переходим по щелчку
            if (link){
                var targetURL = new URLRequest(link);
                navigateToURL(targetURL, '_self');
            }
        }
    }
}

Мы создали полноценные клипы вплывающих надписей и клип карты. Пора вывести это всё на экран. Вынесем программную часть проекта в отдельный файл. Создадим файл RegionMap.as с данным содержимым:

package {
 
    import flash.display.*;
 
    public class RegionMap extends Sprite {
 
        // Будем хранить все надписи в массиве для удобства
        public var labels = new Array;
 
        // Функция-конструктор (выполняется при запуске флэшки)
        public function RegionMap():void {
 
            // Как видно, в fla файле на единственном кадре ничего нет. 
            // Вставим на экран карту и надписи.
 
            // Создаём экземпляр клипа карты
            var map = new Map;
            map.x = map.y = 0;
            // Помещаем на экран
            addChild(map);
 
            // Создаём все надписи и помещаем их в массив labels
            // Каждая надпись наследует функционал класса RegLabel
 
            var r;
 
            r = new Belgorod;
            r.link = 'http://yandex.ru/yandsearch?text=belgorod';
            r.x = 8; r.y = 550; 
            labels.push(r);
 
            r = new Bransk; 
            r.x = 46; r.y = 380; 
            labels.push(r);
 
            r = new Kaluga; 
            r.x = 156; r.y = 392; 
            labels.push(r);
 
            r = new Kostroma; 
            r.x = 512; r.y = 438; 
            labels.push(r);
 
            r = new Kursk; 
            r.x = 50; r.y = 505; 
            labels.push(r);
 
            r = new Leningrad; 
            r.x = 348; r.y = 87; 
            labels.push(r);
 
            r = new Lipetsk; 
            r.x = 148; r.y = 556; 
            labels.push(r);
 
            r = new Moskow; 
            r.x = 266; r.y = 396; 
            labels.push(r);
 
            r = new Novgorod; 
            r.x = 300; r.y = 160; 
            labels.push(r);
 
            r = new Orel; 
            r.x = 108; r.y = 470; 
            labels.push(r);
 
            r = new Razan; 
            r.x = 256; r.y = 528; 
            labels.push(r);
 
            r = new Smolensk; 
            r.x = 150; r.y = 292; 
            labels.push(r);
 
            r = new Tambov; 
            r.x = 221; r.y = 612; 
            labels.push(r);
 
            r = new Voronezh; 
            r.x = 98; r.y = 632; 
            labels.push(r);
 
            // Теперь с массивом записей можно делать что угодно. 
            // Мы же просто выведем их на экран:
 
            for (var i=0; i<labels.length; i++){
                addChild(labels[i]);
            }
 
            // Больше ничего делать не надо, так как всё поведение 
            // надписей прописано в RegLabel.as
 
        }
    }
}

Для каждой надписи при необходимости укажите ссылку на нужный раздел сайта (как это показано для Belgorod)

Укажем этот класс исполняемым при запуске проекта:

Класс

Теперь можно запустить проект. Результат можно увидеть здесь.

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

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

Итог: друг оказался доволен приобщению к Flash и даже смог кое-что переделать в этом прототипе.

Дабы сразу предупредить «звёздную болезнь начинающего мастера» скажу, что этот примитивный способ далёк от идеалов более-менее обдуманного профессионального проектирования и совершенства кода и годится лишь в качестве урока. В общем, «Все имена и события вымышлены. Любое совпадение с реальными является случайностью. Не пытайтесь повторить это в реальной жизни».

Здесь мы обошлись всего заданием одного класса объекта и классом документа. Интереснее было бы создавать всё программными средствами (используя текстовые поля и порождая от одного класса) по массиву координат, применять прогаммно различные стили и трансформацию. Не помешало бы провести неслабый рефакторинг: вынести данные из логики (во внутренний массив или во внешний файл) с доступом к ресурсам через классы-модели, вынести низкоуровневые операции создания карты, создания и вывода областей в отдельные методы createMap(), createLabels() и showLabels(); инкапсулировать поле link, снабдив его сеттером с валидацией аргумента...

Если же хотите сразу что-то действительно стоящее (как на kremlin.ru, например) для серьёзного проекта и не поняли предыдущий параграф, то лучше самому сразу не пробовать.

Другие статьи

В Yii полезно использовать кеширование не только SQL-запросов, но и HTML-фрагментов страницы. Очень удобно то, что можно обрамить кеширующим блоком вызов любого более-менее статичного виджета в представлении или лэйауте чтобы он не пересобирался каждый раз заново. Но при этом возникает необходимость в придумывании для каждого фрагмента уникального ключа, по которому он будет записан в кэше.

В полудрёме на мягком диване, попивая свежевыжатый сок, вы зашли на нужный вам сайт. Окинули взглядом страницу, щелкнули по нужной ссылке, получили то, что желали и закрыли браузер. Вам кажется, что ничего особенного не произошло за эти несколько секунд, но, оказывается, это не так. Не всё так просто.

Каждый игрок на рынке услуг зазывает клиентов фразой «Закажите у нас! Круче чем у нас не найдёте!», но при нынешнем заполнении интернета сайтами многочисленных web-студий очень важно не прогадать с выбором исполнителя, которому Вы доверите осуществление Ваших замыслов. Если у Вас ещё нет сайта и нет денег на оплату услуг проверенной веб-студии, то когда-то вопрос выбора у Вас возникнет. Осмелюсь дать несколько советов как уберечь деньги и нервы заказчика при выборе исполнителя.

При первом обращении к web-разработчикам каждый спрашивает, сколько же стоит сайт, сколько времени он создаётся. Вы, наверное, сразу спросите то же самое? В этом процессе не может быть стандартных цен. Когда называют всем суммы от 6000 до 600 000 рублей и сроки от трех дней до года, то все клиенты удивляются, почему же такой большой разброс?

Комментарии

 

Дмитрий

Здравствуйте, спасибо за урок!
Хотелось бы разобраться в некоторых деталях в данной работе, можно ли получить исходники, чтобы глянуть?
Пытался сделать по уроку все, не получилось, хотелось бы глянуть исходники если возможно и выяснить что делал не так.
Могу отослать свои. Я сам только начал изучать flash.
Заранее спасибо с уважением Дмитрий.

Ответить

 

Дмитрий

И хотелось бы понять куда вставлять код:

var map = new Map;
var sm = new Smolensk;
var tb = new Tambov;
...

И код:
package {

import flash.display.*;
import flash.events.*;
import flash.net.*;
.......

А так все расписано довольно понятно, прямо по пунктам, но вот про то куда вставлять коды приведенные выше не совсем понятно.

И еще у меня выдает такие ошибки(помогите пожалуйста разобраться в данном вопросе):

\map\RegLable.as, строка 1 5008: Имя определения "RegLabel" не отображает местоположение этого файла. Измените имя определения внутри этого файла или переименуйте файл. C:\Users\Работа\Desktop\q1\map\RegLable.as

\map\RegLable.as, строка 1 5000: В класс "RegLable" должен входить подкласс "flash.display.MovieClip", так как он связывается с символом такого же типа в библиотеке.

\map\RegionMap.as, строка 1 5000: В класс "RegionMap" должен входить подкласс "flash.display.MovieClip", так как он связывается с символом такого же типа в библиотеке.

Остальные ошибки однотипные, по типу последних.
Заранее спасибо, с уважением Дмитрий.

Ответить

 

Дмитрий Елисеев
var map = new Map;
var sm = new Smolensk;
var tb = new Tambov;

Это код для примера. Вместо него приведён усовершенствованный файл RegionMap.as.

package { 
    import flash.display.*;
    import flash.events.*;
    import flash.net.*;

    public class RegLabel extends MovieClip {
        ...
    }
}

Как класс называется, так и должен называться файл.

Имя определения "RegLabel" не отображает местоположение этого файла.

У Вас файл назван RegLable.as вместо RegLabel.as.

Ответить

Оставить комментарий

Войти | Завести аккаунт


(никто не увидит)



Можно использовать теги <p> <ul> <li> <b> <i> <a> <pre>